From b7fe4141123c6fc26fffec68d0db62ecf474c074 Mon Sep 17 00:00:00 2001 From: Denis Ovsienko Date: Tue, 21 Aug 2007 16:32:56 +0000 Subject: Bug #362 is fixed now. --- ospfd/ChangeLog | 13 +++++++++++++ ospfd/ospf_interface.c | 5 +++++ ospfd/ospf_network.c | 35 +++++++++++++++++++++++++++++++++++ ospfd/ospf_network.h | 1 + ospfd/ospf_packet.c | 8 ++++++-- ospfd/ospfd.c | 2 ++ ospfd/ospfd.h | 4 ++++ 7 files changed, 66 insertions(+), 2 deletions(-) (limited to 'ospfd') diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog index af5ace48..feba89a3 100644 --- a/ospfd/ChangeLog +++ b/ospfd/ChangeLog @@ -1,3 +1,16 @@ +2007-08-21 Denis Ovsienko + + * ospfd.h: Extend struct ospf with maxsndbuflen field and + define its default value. + * ospfd.c: (ospf_new) init maxsndbuflen + * ospf_interface.c: (ospf_if_up) Call ospf_adjust_sndbuflen() + for each regular interface being brought up. + * ospf_network.[ch]: (ospf_adjust_sndbuflen) New function + makes sure ospf socket sending buffer is large enough + to cover the biggest interface MTU we have seen ever. + * ospf_packet.c: (ospf_write) Use maxsndbuflen to decide on + the biggest amount of data we are going to send at once. + 2007-08-07 Paul Jakma * ospf_spf.c: (ospf_spf_next) Finish off the explanatory diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index bf53668b..862735be 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -781,6 +781,11 @@ ospf_if_up (struct ospf_interface *oi) OSPF_ISM_EVENT_SCHEDULE (oi, ISM_LoopInd); else { + struct ospf *ospf = ospf_lookup (); + if (ospf != NULL) + ospf_adjust_sndbuflen (ospf, oi->ifp->mtu); + else + zlog_warn ("%s: ospf_lookup() returned NULL"); ospf_if_stream_set (oi); OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp); } diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index e8c98371..11155dbc 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -41,6 +41,7 @@ extern struct zebra_privs_t ospfd_privs; #include "ospfd/ospf_lsdb.h" #include "ospfd/ospf_neighbor.h" #include "ospfd/ospf_packet.h" +#include "ospfd/ospf_dump.h" @@ -233,3 +234,37 @@ ospf_sock_init (void) return ospf_sock; } + +void +ospf_adjust_sndbuflen (struct ospf * ospf, int buflen) +{ + int ret, newbuflen; + /* Check if any work has to be done at all. */ + if (ospf->maxsndbuflen >= buflen) + return; + if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) + zlog_debug ("%s: adjusting OSPF send buffer size to %d", + __func__, buflen); + if (ospfd_privs.change (ZPRIVS_RAISE)) + zlog_err ("%s: could not raise privs, %s", __func__, + safe_strerror (errno)); + /* Now we try to set SO_SNDBUF to what our caller has requested + * (OSPF_SNDBUFLEN_DEFAULT initially, which seems to be a sane + * default; or the MTU of a newly added interface). However, + * if the OS has truncated the actual buffer size to somewhat + * less or bigger size, try to detect it and update our records + * appropriately. + */ + ret = setsockopt_so_sendbuf (ospf->fd, buflen); + newbuflen = getsockopt_so_sendbuf (ospf->fd); + if (ret < 0 || newbuflen != buflen) + zlog_warn ("%s: tried to set SO_SNDBUF to %d, but got %d", + __func__, buflen, newbuflen); + if (newbuflen >= 0) + ospf->maxsndbuflen = newbuflen; + else + zlog_warn ("%s: failed to get SO_SNDBUF", __func__); + if (ospfd_privs.change (ZPRIVS_LOWER)) + zlog_err ("%s: could not lower privs, %s", __func__, + safe_strerror (errno)); +} diff --git a/ospfd/ospf_network.h b/ospfd/ospf_network.h index 1b43df1c..f6909912 100644 --- a/ospfd/ospf_network.h +++ b/ospfd/ospf_network.h @@ -34,5 +34,6 @@ extern int ospf_if_drop_alldrouters (struct ospf *, struct prefix *, unsigned int); extern int ospf_if_ipmulticast (struct ospf *, struct prefix *, unsigned int); extern int ospf_sock_init (void); +extern void ospf_adjust_sndbuflen (struct ospf *, int); #endif /* _ZEBRA_OSPF_NETWORK_H */ diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 4735f99b..a778a50b 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -602,8 +602,12 @@ ospf_write (struct thread *thread) ipid = (time(NULL) & 0xffff); #endif /* WANT_OSPF_WRITE_FRAGMENT */ - /* convenience - max OSPF data per packet */ - maxdatasize = oi->ifp->mtu - sizeof (struct ip); + /* convenience - max OSPF data per packet, + * and reliability - not more data, than our + * socket can accept + */ + maxdatasize = MIN (oi->ifp->mtu, ospf->maxsndbuflen) - + sizeof (struct ip); /* Get one packet from queue. */ op = ospf_fifo_head (oi->obuf); diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index 80b97fab..8133050d 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -212,6 +212,8 @@ ospf_new (void) "a socket"); exit(1); } + new->maxsndbuflen = 0; + ospf_adjust_sndbuflen (new, OSPF_SNDBUFLEN_DEFAULT); if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE+1)) == NULL) { zlog_err("ospf_new: fatal error: stream_new(%u) failed allocating ibuf", diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h index ec9d9d6b..b0a14ce2 100644 --- a/ospfd/ospfd.h +++ b/ospfd/ospfd.h @@ -129,6 +129,9 @@ #define OSPF_LS_REFRESH_SHIFT (60 * 15) #define OSPF_LS_REFRESH_JITTER 60 +/* Initial send buffer size for ospfd raw sending socket. */ +#define OSPF_SNDBUFLEN_DEFAULT 1024 + /* OSPF master for system wide configuration and variables. */ struct ospf_master { @@ -266,6 +269,7 @@ struct ospf struct thread *t_write; struct thread *t_read; int fd; + int maxsndbuflen; struct stream *ibuf; struct list *oi_write_q; -- cgit v1.2.1