summaryrefslogtreecommitdiff
path: root/ospfd
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd')
-rw-r--r--ospfd/ChangeLog13
-rw-r--r--ospfd/ospf_interface.c5
-rw-r--r--ospfd/ospf_network.c35
-rw-r--r--ospfd/ospf_network.h1
-rw-r--r--ospfd/ospf_packet.c8
-rw-r--r--ospfd/ospfd.c2
-rw-r--r--ospfd/ospfd.h4
7 files changed, 66 insertions, 2 deletions
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 <paul.jakma@sun.com>
* 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;