mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-09 07:56:29 +00:00
In the "write" direction added a command to ensure that Quagga
is able to send out K (=3 by default) packets per thread-write. Signed-off-by: Ayan Banerjee <ayan@cumulusnetworks.com> Reviewed-by: JR Rivers <jrrivers@cumulusnetworks.com>
This commit is contained in:
parent
a78d75b04c
commit
2f8f370e35
@ -217,6 +217,13 @@ ospf_fifo_flush (struct ospf_fifo *fifo)
|
|||||||
fifo->count = 0;
|
fifo->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the current fifo count */
|
||||||
|
static int
|
||||||
|
ospf_fifo_count (struct ospf_fifo *fifo)
|
||||||
|
{
|
||||||
|
return (fifo->count);
|
||||||
|
}
|
||||||
|
|
||||||
/* Free ospf packet fifo. */
|
/* Free ospf packet fifo. */
|
||||||
void
|
void
|
||||||
ospf_fifo_free (struct ospf_fifo *fifo)
|
ospf_fifo_free (struct ospf_fifo *fifo)
|
||||||
@ -647,6 +654,7 @@ ospf_write (struct thread *thread)
|
|||||||
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
||||||
u_int16_t maxdatasize;
|
u_int16_t maxdatasize;
|
||||||
#define OSPF_WRITE_IPHL_SHIFT 2
|
#define OSPF_WRITE_IPHL_SHIFT 2
|
||||||
|
int pkt_count = 0;
|
||||||
|
|
||||||
ospf->t_write = NULL;
|
ospf->t_write = NULL;
|
||||||
|
|
||||||
@ -668,132 +676,136 @@ ospf_write (struct thread *thread)
|
|||||||
maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) -
|
maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) -
|
||||||
sizeof (struct ip);
|
sizeof (struct ip);
|
||||||
|
|
||||||
/* Get one packet from queue. */
|
while ((pkt_count < ospf->write_multiplier) && ospf_fifo_count(oi->obuf))
|
||||||
op = ospf_fifo_head (oi->obuf);
|
{
|
||||||
assert (op);
|
pkt_count++;
|
||||||
assert (op->length >= OSPF_HEADER_SIZE);
|
/* Get one packet from queue. */
|
||||||
|
op = ospf_fifo_head (oi->obuf);
|
||||||
|
assert (op);
|
||||||
|
assert (op->length >= OSPF_HEADER_SIZE);
|
||||||
|
|
||||||
if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
|
if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
|
||||||
|| op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
|
|| op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
|
||||||
ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
|
ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
|
||||||
|
|
||||||
/* Rewrite the md5 signature & update the seq */
|
/* Rewrite the md5 signature & update the seq */
|
||||||
ospf_make_md5_digest (oi, op);
|
ospf_make_md5_digest (oi, op);
|
||||||
|
|
||||||
/* Retrieve OSPF packet type. */
|
/* Retrieve OSPF packet type. */
|
||||||
stream_set_getp (op->s, 1);
|
stream_set_getp (op->s, 1);
|
||||||
type = stream_getc (op->s);
|
type = stream_getc (op->s);
|
||||||
|
|
||||||
/* reset get pointer */
|
/* reset get pointer */
|
||||||
stream_set_getp (op->s, 0);
|
stream_set_getp (op->s, 0);
|
||||||
|
|
||||||
memset (&iph, 0, sizeof (struct ip));
|
memset (&iph, 0, sizeof (struct ip));
|
||||||
memset (&sa_dst, 0, sizeof (sa_dst));
|
memset (&sa_dst, 0, sizeof (sa_dst));
|
||||||
|
|
||||||
sa_dst.sin_family = AF_INET;
|
sa_dst.sin_family = AF_INET;
|
||||||
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||||
sa_dst.sin_len = sizeof(sa_dst);
|
sa_dst.sin_len = sizeof(sa_dst);
|
||||||
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
||||||
sa_dst.sin_addr = op->dst;
|
sa_dst.sin_addr = op->dst;
|
||||||
sa_dst.sin_port = htons (0);
|
sa_dst.sin_port = htons (0);
|
||||||
|
|
||||||
/* Set DONTROUTE flag if dst is unicast. */
|
/* Set DONTROUTE flag if dst is unicast. */
|
||||||
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
|
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
|
||||||
if (!IN_MULTICAST (htonl (op->dst.s_addr)))
|
if (!IN_MULTICAST (htonl (op->dst.s_addr)))
|
||||||
flags = MSG_DONTROUTE;
|
flags = MSG_DONTROUTE;
|
||||||
|
|
||||||
iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT;
|
iph.ip_hl = sizeof (struct ip) >> OSPF_WRITE_IPHL_SHIFT;
|
||||||
/* it'd be very strange for header to not be 4byte-word aligned but.. */
|
/* it'd be very strange for header to not be 4byte-word aligned but.. */
|
||||||
if ( sizeof (struct ip)
|
if ( sizeof (struct ip)
|
||||||
> (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) )
|
> (unsigned int)(iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) )
|
||||||
iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */
|
iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */
|
||||||
|
|
||||||
iph.ip_v = IPVERSION;
|
iph.ip_v = IPVERSION;
|
||||||
iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
|
iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
|
||||||
iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
|
iph.ip_len = (iph.ip_hl << OSPF_WRITE_IPHL_SHIFT) + op->length;
|
||||||
|
|
||||||
#if defined(__DragonFly__)
|
#if defined(__DragonFly__)
|
||||||
/*
|
/*
|
||||||
* DragonFly's raw socket expects ip_len/ip_off in network byte order.
|
* DragonFly's raw socket expects ip_len/ip_off in network byte order.
|
||||||
*/
|
*/
|
||||||
iph.ip_len = htons(iph.ip_len);
|
iph.ip_len = htons(iph.ip_len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
||||||
/* XXX-MT: not thread-safe at all..
|
/* XXX-MT: not thread-safe at all..
|
||||||
* XXX: this presumes this is only programme sending OSPF packets
|
* XXX: this presumes this is only programme sending OSPF packets
|
||||||
* otherwise, no guarantee ipid will be unique
|
* otherwise, no guarantee ipid will be unique
|
||||||
*/
|
*/
|
||||||
iph.ip_id = ++ipid;
|
iph.ip_id = ++ipid;
|
||||||
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
||||||
|
|
||||||
iph.ip_off = 0;
|
iph.ip_off = 0;
|
||||||
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
|
||||||
iph.ip_ttl = OSPF_VL_IP_TTL;
|
iph.ip_ttl = OSPF_VL_IP_TTL;
|
||||||
else
|
else
|
||||||
iph.ip_ttl = OSPF_IP_TTL;
|
iph.ip_ttl = OSPF_IP_TTL;
|
||||||
iph.ip_p = IPPROTO_OSPFIGP;
|
iph.ip_p = IPPROTO_OSPFIGP;
|
||||||
iph.ip_sum = 0;
|
iph.ip_sum = 0;
|
||||||
iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
|
iph.ip_src.s_addr = oi->address->u.prefix4.s_addr;
|
||||||
iph.ip_dst.s_addr = op->dst.s_addr;
|
iph.ip_dst.s_addr = op->dst.s_addr;
|
||||||
|
|
||||||
memset (&msg, 0, sizeof (msg));
|
memset (&msg, 0, sizeof (msg));
|
||||||
msg.msg_name = (caddr_t) &sa_dst;
|
msg.msg_name = (caddr_t) &sa_dst;
|
||||||
msg.msg_namelen = sizeof (sa_dst);
|
msg.msg_namelen = sizeof (sa_dst);
|
||||||
msg.msg_iov = iov;
|
msg.msg_iov = iov;
|
||||||
msg.msg_iovlen = 2;
|
msg.msg_iovlen = 2;
|
||||||
iov[0].iov_base = (char*)&iph;
|
iov[0].iov_base = (char*)&iph;
|
||||||
iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
|
iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
|
||||||
iov[1].iov_base = STREAM_PNT (op->s);
|
iov[1].iov_base = STREAM_PNT (op->s);
|
||||||
iov[1].iov_len = op->length;
|
iov[1].iov_len = op->length;
|
||||||
|
|
||||||
/* Sadly we can not rely on kernels to fragment packets because of either
|
/* Sadly we can not rely on kernels to fragment packets because of either
|
||||||
* IP_HDRINCL and/or multicast destination being set.
|
* IP_HDRINCL and/or multicast destination being set.
|
||||||
*/
|
*/
|
||||||
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
#ifdef WANT_OSPF_WRITE_FRAGMENT
|
||||||
if ( op->length > maxdatasize )
|
if ( op->length > maxdatasize )
|
||||||
ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize,
|
ospf_write_frags (ospf->fd, op, &iph, &msg, maxdatasize,
|
||||||
oi->ifp->mtu, flags, type);
|
oi->ifp->mtu, flags, type);
|
||||||
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
#endif /* WANT_OSPF_WRITE_FRAGMENT */
|
||||||
|
|
||||||
/* send final fragment (could be first) */
|
/* send final fragment (could be first) */
|
||||||
sockopt_iphdrincl_swab_htosys (&iph);
|
sockopt_iphdrincl_swab_htosys (&iph);
|
||||||
ret = sendmsg (ospf->fd, &msg, flags);
|
ret = sendmsg (ospf->fd, &msg, flags);
|
||||||
sockopt_iphdrincl_swab_systoh (&iph);
|
sockopt_iphdrincl_swab_systoh (&iph);
|
||||||
if (IS_DEBUG_OSPF_EVENT)
|
if (IS_DEBUG_OSPF_EVENT)
|
||||||
zlog_debug ("ospf_write to %s, "
|
zlog_debug ("ospf_write to %s, "
|
||||||
"id %d, off %d, len %d, interface %s, mtu %u:",
|
"id %d, off %d, len %d, interface %s, mtu %u:",
|
||||||
inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
|
inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
|
||||||
oi->ifp->name, oi->ifp->mtu);
|
oi->ifp->name, oi->ifp->mtu);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
zlog_warn ("*** sendmsg in ospf_write failed to %s, "
|
zlog_warn ("*** sendmsg in ospf_write failed to %s, "
|
||||||
"id %d, off %d, len %d, interface %s, mtu %u: %s",
|
"id %d, off %d, len %d, interface %s, mtu %u: %s",
|
||||||
inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
|
inet_ntoa (iph.ip_dst), iph.ip_id, iph.ip_off, iph.ip_len,
|
||||||
oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
|
oi->ifp->name, oi->ifp->mtu, safe_strerror (errno));
|
||||||
|
|
||||||
/* Show debug sending packet. */
|
/* Show debug sending packet. */
|
||||||
if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
|
if (IS_DEBUG_OSPF_PACKET (type - 1, SEND))
|
||||||
{
|
{
|
||||||
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
|
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
|
||||||
{
|
{
|
||||||
zlog_debug ("-----------------------------------------------------");
|
zlog_debug ("-----------------------------------------------------");
|
||||||
ospf_ip_header_dump (&iph);
|
ospf_ip_header_dump (&iph);
|
||||||
stream_set_getp (op->s, 0);
|
stream_set_getp (op->s, 0);
|
||||||
ospf_packet_dump (op->s);
|
ospf_packet_dump (op->s);
|
||||||
|
}
|
||||||
|
|
||||||
|
zlog_debug ("%s sent to [%s] via [%s].",
|
||||||
|
LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst),
|
||||||
|
IF_NAME (oi));
|
||||||
|
|
||||||
|
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
|
||||||
|
zlog_debug ("-----------------------------------------------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now delete packet from queue. */
|
||||||
|
ospf_packet_delete (oi);
|
||||||
}
|
}
|
||||||
|
|
||||||
zlog_debug ("%s sent to [%s] via [%s].",
|
|
||||||
LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst),
|
|
||||||
IF_NAME (oi));
|
|
||||||
|
|
||||||
if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
|
|
||||||
zlog_debug ("-----------------------------------------------------");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now delete packet from queue. */
|
|
||||||
ospf_packet_delete (oi);
|
|
||||||
|
|
||||||
/* Move this interface to the tail of write_q to
|
/* Move this interface to the tail of write_q to
|
||||||
serve everyone in a round robin fashion */
|
serve everyone in a round robin fashion */
|
||||||
list_delete_node (ospf->oi_write_q, node);
|
list_delete_node (ospf->oi_write_q, node);
|
||||||
|
@ -2531,6 +2531,37 @@ DEFUN (no_ospf_auto_cost_reference_bandwidth,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN (ospf_write_multiplier,
|
||||||
|
ospf_write_multiplier_cmd,
|
||||||
|
"write-multiplier <1-50>",
|
||||||
|
"Number of writes per thread callback\n")
|
||||||
|
{
|
||||||
|
struct ospf *ospf = vty->index;
|
||||||
|
u_int32_t write_multiplier;
|
||||||
|
|
||||||
|
write_multiplier = strtol (argv[0], NULL, 10);
|
||||||
|
if (write_multiplier < 1 || write_multiplier > 50)
|
||||||
|
{
|
||||||
|
vty_out (vty, "write-multiplier value is invalid%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
ospf->write_multiplier = write_multiplier;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_ospf_write_multiplier,
|
||||||
|
no_ospf_write_multiplier_cmd,
|
||||||
|
"no write-multiplier",
|
||||||
|
NO_STR
|
||||||
|
"Number of writes per thread callback\n")
|
||||||
|
{
|
||||||
|
struct ospf *ospf = vty->index;
|
||||||
|
|
||||||
|
ospf->write_multiplier = OSPF_WRITE_MULTIPLIER_DEFAULT;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
const char *ospf_abr_type_descr_str[] =
|
const char *ospf_abr_type_descr_str[] =
|
||||||
{
|
{
|
||||||
"Unknown",
|
"Unknown",
|
||||||
@ -2760,6 +2791,10 @@ DEFUN (show_ip_ospf,
|
|||||||
ospf_timer_dump (ospf->t_spf_calc, timebuf, sizeof (timebuf)),
|
ospf_timer_dump (ospf->t_spf_calc, timebuf, sizeof (timebuf)),
|
||||||
VTY_NEWLINE);
|
VTY_NEWLINE);
|
||||||
|
|
||||||
|
/* Show write multiplier values */
|
||||||
|
vty_out (vty, " Write Multiplier set to %d %s",
|
||||||
|
ospf->write_multiplier, VTY_NEWLINE);
|
||||||
|
|
||||||
/* Show refresh parameters. */
|
/* Show refresh parameters. */
|
||||||
vty_out (vty, " Refresh timer %d secs%s",
|
vty_out (vty, " Refresh timer %d secs%s",
|
||||||
ospf->lsa_refresh_interval, VTY_NEWLINE);
|
ospf->lsa_refresh_interval, VTY_NEWLINE);
|
||||||
@ -7287,6 +7322,11 @@ ospf_config_write (struct vty *vty)
|
|||||||
ospf->spf_delay, ospf->spf_holdtime,
|
ospf->spf_delay, ospf->spf_holdtime,
|
||||||
ospf->spf_max_holdtime, VTY_NEWLINE);
|
ospf->spf_max_holdtime, VTY_NEWLINE);
|
||||||
|
|
||||||
|
/* Write multiplier print. */
|
||||||
|
if (ospf->write_multiplier != OSPF_WRITE_MULTIPLIER_DEFAULT)
|
||||||
|
vty_out (vty, " ospf write-multiplier %d%s",
|
||||||
|
ospf->write_multiplier, VTY_NEWLINE);
|
||||||
|
|
||||||
/* Max-metric router-lsa print */
|
/* Max-metric router-lsa print */
|
||||||
config_write_stub_router (vty, ospf);
|
config_write_stub_router (vty, ospf);
|
||||||
|
|
||||||
@ -7723,6 +7763,10 @@ ospf_vty_init (void)
|
|||||||
install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd);
|
install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd);
|
||||||
install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd);
|
install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd);
|
||||||
|
|
||||||
|
/* write multiplier commands */
|
||||||
|
install_element (OSPF_NODE, &ospf_write_multiplier_cmd);
|
||||||
|
install_element (OSPF_NODE, &no_ospf_write_multiplier_cmd);
|
||||||
|
|
||||||
/* Init interface related vty commands. */
|
/* Init interface related vty commands. */
|
||||||
ospf_vty_if_init ();
|
ospf_vty_if_init ();
|
||||||
|
|
||||||
|
@ -233,6 +233,7 @@ ospf_new (void)
|
|||||||
}
|
}
|
||||||
new->t_read = thread_add_read (master, ospf_read, new, new->fd);
|
new->t_read = thread_add_read (master, ospf_read, new, new->fd);
|
||||||
new->oi_write_q = list_new ();
|
new->oi_write_q = list_new ();
|
||||||
|
new->write_multiplier = OSPF_WRITE_MULTIPLIER_DEFAULT;
|
||||||
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
@ -219,6 +219,8 @@ struct ospf
|
|||||||
struct thread *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/
|
struct thread *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/
|
||||||
|
|
||||||
struct thread *t_write;
|
struct thread *t_write;
|
||||||
|
#define OSPF_WRITE_MULTIPLIER_DEFAULT 3
|
||||||
|
int write_multiplier; /* Num of packets sent per thread invocation */
|
||||||
struct thread *t_read;
|
struct thread *t_read;
|
||||||
int fd;
|
int fd;
|
||||||
unsigned int maxsndbuflen;
|
unsigned int maxsndbuflen;
|
||||||
|
Loading…
Reference in New Issue
Block a user