2005-02-23 Andrew J. Schorr <ajschorr@alumni.princeton.edu>

* ospfd.h: Add new field struct stream *ibuf to struct ospf.
	* ospfd.c: (ospf_new) Check return code from ospf_sock_init.
	  Allocate ibuf using stream_new(OSPF_MAX_PACKET_SIZE+1).
	  (ospf_finish) Call stream_free(ospf->ibuf.
	* ospf_packet.c: (ospf_read) Call stream_reset(ospf->ibuf) and then
	  pass it to ospf_recv_packet for use in receiving the packet
	  (instead of allocating a new stream for each packet received).
	  Eliminate all calls to stream_free(ibuf).
	  (ospf_recv_packet) The struct stream *ibuf is now passed in as
	  an argument.  No need to use recvfrom to peek at the packet
	  header (to see how big it is), just use ospf->ibuf which is
	  always large enough (this eliminates a system call to recvfrom).
	  Therefore, no need to allocate a stream just for this packet,
	  and no need to free it when done.
This commit is contained in:
ajs 2005-02-23 15:43:01 +00:00
parent 9fc7ebf10b
commit 5c33349b3e
4 changed files with 58 additions and 50 deletions

View File

@ -1,3 +1,20 @@
2005-02-23 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ospfd.h: Add new field struct stream *ibuf to struct ospf.
* ospfd.c: (ospf_new) Check return code from ospf_sock_init.
Allocate ibuf using stream_new(OSPF_MAX_PACKET_SIZE+1).
(ospf_finish) Call stream_free(ospf->ibuf.
* ospf_packet.c: (ospf_read) Call stream_reset(ospf->ibuf) and then
pass it to ospf_recv_packet for use in receiving the packet
(instead of allocating a new stream for each packet received).
Eliminate all calls to stream_free(ibuf).
(ospf_recv_packet) The struct stream *ibuf is now passed in as
an argument. No need to use recvfrom to peek at the packet
header (to see how big it is), just use ospf->ibuf which is
always large enough (this eliminates a system call to recvfrom).
Therefore, no need to allocate a stream just for this packet,
and no need to free it when done.
2005-02-23 Vincenzo Eramo <eramo at infocom.ing.uniroma1.it>
* ospf_lsa.h: New flag to the LSA structure for the SPF calculation.

View File

@ -2033,12 +2033,11 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,
}
static struct stream *
ospf_recv_packet (int fd, struct interface **ifp)
ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf)
{
int ret;
struct ip iph;
struct ip *iph;
u_int16_t ip_len;
struct stream *ibuf;
unsigned int ifindex = 0;
struct iovec iov;
/* Header and data both require alignment. */
@ -2051,30 +2050,26 @@ ospf_recv_packet (int fd, struct interface **ifp)
msgh.msg_control = (caddr_t) buff;
msgh.msg_controllen = sizeof (buff);
/* XXX Is there an upper limit on the size of these packets? If there is,
it would be more efficient to read the whole packet in one shot without
peeking (this would cut down from 2 system calls to 1). And this would
make the error-handling logic a bit more robust. */
ret = recvfrom (fd, (void *)&iph, sizeof (iph), MSG_PEEK, NULL, 0);
if (ret != sizeof (iph))
ret = stream_recvmsg (ibuf, fd, &msgh, 0, OSPF_MAX_PACKET_SIZE+1);
if (ret < 0)
{
if (ret > 0)
{
zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
"(ip header size is %u)",
ret, (u_int)sizeof(iph));
recvfrom (fd, (void *)&iph, ret, 0, NULL, 0);
}
else
zlog_warn("ospf_recv_packet: recvfrom returned %d: %s",
ret, safe_strerror(errno));
zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
return NULL;
}
if (ret < sizeof(iph))
{
zlog_warn("ospf_recv_packet: discarding runt packet of length %d "
"(ip header size is %u)",
ret, (u_int)sizeof(iph));
return NULL;
}
sockopt_iphdrincl_swab_systoh (&iph);
/* Note that there should not be alignment problems with this assignment
because this is at the beginning of the stream data buffer. */
iph = (struct ip *) STREAM_DATA(ibuf);
sockopt_iphdrincl_swab_systoh (iph);
ip_len = iph.ip_len;
ip_len = iph->ip_len;
#if !defined(GNU_LINUX) && (OpenBSD < 200311)
/*
@ -2091,25 +2086,17 @@ ospf_recv_packet (int fd, struct interface **ifp)
*
* For more details, see <netinet/ip_input.c>.
*/
ip_len = ip_len + (iph.ip_hl << 2);
ip_len = ip_len + (iph->ip_hl << 2);
#endif
if ( (ibuf = stream_new (ip_len)) == NULL)
return NULL;
iov.iov_base = STREAM_DATA (ibuf);
iov.iov_len = ip_len;
ret = stream_recvmsg (ibuf, fd, &msgh, 0, ip_len);
ifindex = getsockopt_ifindex (AF_INET, &msgh);
*ifp = if_lookup_by_index (ifindex);
if (ret != ip_len)
{
zlog_warn ("ospf_recv_packet short read. "
"ip_len %d bytes read %d", ip_len, ret);
stream_free (ibuf);
zlog_warn ("ospf_recv_packet read length mismatch: ip_len is %d, "
"but recvmsg returned %d", ip_len, ret);
return NULL;
}
@ -2360,12 +2347,14 @@ ospf_read (struct thread *thread)
ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
/* read OSPF packet. */
ibuf = ospf_recv_packet (ospf->fd, &ifp);
if (ibuf == NULL)
stream_reset(ospf->ibuf);
if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
return -1;
/* Note that there should not be alignment problems with this assignment
because this is at the beginning of the stream data buffer. */
iph = (struct ip *) STREAM_DATA (ibuf);
sockopt_iphdrincl_swab_systoh (iph);
/* Note that sockopt_iphdrincl_swab_systoh was called in ospf_recv_packet. */
if (ifp == NULL)
/* Handle cases where the platform does not support retrieving the ifindex,
@ -2374,10 +2363,7 @@ ospf_read (struct thread *thread)
ifp = if_lookup_address (iph->ip_src);
if (ifp == NULL)
{
stream_free (ibuf);
return 0;
}
return 0;
/* IP Header dump. */
if (IS_DEBUG_OSPF_PACKET(0, RECV))
@ -2391,7 +2377,6 @@ ospf_read (struct thread *thread)
zlog_debug ("ospf_read[%s]: Dropping self-originated packet",
inet_ntoa (iph->ip_src));
}
stream_free (ibuf);
return 0;
}
@ -2418,7 +2403,6 @@ ospf_read (struct thread *thread)
zlog_warn ("Packet from [%s] received on link %s"
" but no ospf_interface",
inet_ntoa (iph->ip_src), ifp->name);
stream_free (ibuf);
return 0;
}
}
@ -2430,7 +2414,6 @@ ospf_read (struct thread *thread)
{
zlog_warn ("Packet from [%s] received on wrong link %s",
inet_ntoa (iph->ip_src), ifp->name);
stream_free (ibuf);
return 0;
}
else if (oi->state == ISM_Down)
@ -2441,7 +2424,6 @@ ospf_read (struct thread *thread)
inet_ntop(AF_INET, &iph->ip_src, buf[0], sizeof(buf[0])),
inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])),
ifp->name, if_flag_dump(ifp->flags));
stream_free (ibuf);
/* Fix multicast memberships? */
if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
@ -2463,7 +2445,6 @@ ospf_read (struct thread *thread)
zlog_warn ("Dropping packet for AllDRouters from [%s] via [%s] (ISM: %s)",
inet_ntoa (iph->ip_src), IF_NAME (oi),
LOOKUP (ospf_ism_state_msg, oi->state));
stream_free (ibuf);
/* Try to fix multicast membership. */
SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
ospf_if_set_multicast(oi);
@ -2500,7 +2481,6 @@ ospf_read (struct thread *thread)
ospf_packet_type_str[ospfh->type],
inet_ntoa (iph->ip_src));
}
stream_free (ibuf);
return ret;
}
@ -2534,7 +2514,6 @@ ospf_read (struct thread *thread)
break;
}
stream_free (ibuf);
return 0;
}

View File

@ -204,9 +204,19 @@ ospf_new ()
new, new->lsa_refresh_interval);
new->lsa_refresher_started = time (NULL);
new->fd = ospf_sock_init ();
if (new->fd >= 0)
new->t_read = thread_add_read (master, ospf_read, new, new->fd);
if ((new->fd = ospf_sock_init()) < 0)
{
zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
"a socket");
exit(1);
}
if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL)
{
zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
OSPF_MAX_PACKET_SIZE+1);
exit(1);
}
new->t_read = thread_add_read (master, ospf_read, new, new->fd);
new->oi_write_q = list_new ();
return new;
@ -360,6 +370,7 @@ ospf_finish (struct ospf *ospf)
OSPF_TIMER_OFF (ospf->t_write);
close (ospf->fd);
stream_free(ospf->ibuf);
#ifdef HAVE_OPAQUE_LSA
LSDB_LOOP (OPAQUE_AS_LSDB (ospf), rn, lsa)

View File

@ -248,6 +248,7 @@ struct ospf
struct thread *t_write;
struct thread *t_read;
int fd;
struct stream *ibuf;
struct list *oi_write_q;
/* Distribute lists out of other route sources. */