summaryrefslogtreecommitdiff
path: root/net/quagga/files/patch-cvs-5-sendbuffer
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--net/quagga/files/patch-cvs-5-sendbuffer294
1 files changed, 294 insertions, 0 deletions
diff --git a/net/quagga/files/patch-cvs-5-sendbuffer b/net/quagga/files/patch-cvs-5-sendbuffer
new file mode 100644
index 000000000000..52187f7e0426
--- /dev/null
+++ b/net/quagga/files/patch-cvs-5-sendbuffer
@@ -0,0 +1,294 @@
+--- lib/sockopt.c.orig 2007-07-09 16:36:45.000000000 +0400
++++ lib/sockopt.c 2007-08-02 17:38:50.000000000 +0400
+@@ -29,20 +29,49 @@
+ int ret;
+
+ if ( (ret = setsockopt (sock, SOL_SOCKET, SO_RCVBUF, (char *)
+ &size, sizeof (int))) < 0)
+ zlog_err ("fd %d: can't setsockopt SO_RCVBUF to %d: %s",
+ sock,size,safe_strerror(errno));
+
+ return ret;
+ }
+
++int
++setsockopt_so_sendbuf (const int sock, int size)
++{
++ int ret = setsockopt (sock, SOL_SOCKET, SO_SNDBUF,
++ (char *)&size, sizeof (int));
++
++ if (ret < 0)
++ zlog_err ("fd %d: can't setsockopt SO_SNDBUF to %d: %s",
++ sock, size, safe_strerror (errno));
++
++ return ret;
++}
++
++int
++getsockopt_so_sendbuf (const int sock)
++{
++ u_int32_t optval;
++ socklen_t optlen = sizeof (optval);
++ int ret = getsockopt (sock, SOL_SOCKET, SO_SNDBUF,
++ (char *)&optval, &optlen);
++ if (ret < 0)
++ {
++ zlog_err ("fd %d: can't getsockopt SO_SNDBUF: %d (%s)",
++ sock, errno, safe_strerror (errno));
++ return ret;
++ }
++ return optval;
++}
++
+ static void *
+ getsockopt_cmsg_data (struct msghdr *msgh, int level, int type)
+ {
+ struct cmsghdr *cmsg;
+ void *ptr = NULL;
+
+ for (cmsg = ZCMSG_FIRSTHDR(msgh);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(msgh, cmsg))
+ if (cmsg->cmsg_level == level && cmsg->cmsg_type)
+--- lib/sockopt.h.orig 2007-07-09 16:36:45.000000000 +0400
++++ lib/sockopt.h 2007-08-01 17:37:33.000000000 +0400
+@@ -16,20 +16,22 @@
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+ #ifndef _ZEBRA_SOCKOPT_H
+ #define _ZEBRA_SOCKOPT_H
+
+ extern int setsockopt_so_recvbuf (int sock, int size);
++extern int setsockopt_so_sendbuf (const int sock, int size);
++extern int getsockopt_so_sendbuf (const int sock);
+
+ #ifdef HAVE_IPV6
+ extern int setsockopt_ipv6_pktinfo (int, int);
+ extern int setsockopt_ipv6_checksum (int, int);
+ extern int setsockopt_ipv6_multicast_hops (int, int);
+ extern int setsockopt_ipv6_unicast_hops (int, int);
+ extern int setsockopt_ipv6_hoplimit (int, int);
+ extern int setsockopt_ipv6_multicast_loop (int, int);
+ #endif /* HAVE_IPV6 */
+
+--- ospfd/ospfd.c.orig 2007-05-01 03:42:20.000000000 +0400
++++ ospfd/ospfd.c 2007-08-01 19:07:46.000000000 +0400
+@@ -205,20 +205,22 @@
+ new->t_lsa_refresher = thread_add_timer (master, ospf_lsa_refresh_walker,
+ new, new->lsa_refresh_interval);
+ new->lsa_refresher_started = quagga_time (NULL);
+
+ if ((new->fd = ospf_sock_init()) < 0)
+ {
+ zlog_err("ospf_new: fatal error: ospf_sock_init was unable to open "
+ "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",
+ 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;
+--- ospfd/ospfd.h.orig 2006-10-18 00:45:04.000000000 +0400
++++ ospfd/ospfd.h 2007-08-01 17:10:36.000000000 +0400
+@@ -122,20 +122,23 @@
+
+ /* OSPF Database Description flags. */
+ #define OSPF_DD_FLAG_MS 0x01
+ #define OSPF_DD_FLAG_M 0x02
+ #define OSPF_DD_FLAG_I 0x04
+ #define OSPF_DD_FLAG_ALL 0x07
+
+ #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
+ {
+ /* OSPF instance. */
+ struct list *ospf;
+
+ /* OSPF thread master. */
+ struct thread_master *master;
+
+ /* Zebra interface list. */
+@@ -259,20 +262,21 @@
+ #ifdef HAVE_OPAQUE_LSA
+ struct thread *t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */
+ #endif /* HAVE_OPAQUE_LSA */
+ struct thread *t_maxage; /* MaxAge LSA remover timer. */
+ struct thread *t_maxage_walker; /* MaxAge LSA checking timer. */
+ struct thread *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/
+
+ struct thread *t_write;
+ struct thread *t_read;
+ int fd;
++ int maxsndbuflen;
+ struct stream *ibuf;
+ struct list *oi_write_q;
+
+ /* Distribute lists out of other route sources. */
+ struct
+ {
+ char *name;
+ struct access_list *list;
+ } dlist[ZEBRA_ROUTE_MAX];
+ #define DISTRIBUTE_NAME(O,T) (O)->dlist[T].name
+--- ospfd/ospf_interface.c.orig 2007-04-22 17:26:38.000000000 +0400
++++ ospfd/ospf_interface.c 2007-08-02 18:31:53.000000000 +0400
+@@ -774,20 +774,25 @@
+ int
+ ospf_if_up (struct ospf_interface *oi)
+ {
+ if (oi == NULL)
+ return 0;
+
+ if (oi->type == OSPF_IFTYPE_LOOPBACK)
+ 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);
+ }
+
+ return 1;
+ }
+
+ int
+ ospf_if_down (struct ospf_interface *oi)
+ {
+--- ospfd/ospf_network.c.orig 2005-05-09 22:37:56.000000000 +0400
++++ ospfd/ospf_network.c 2007-08-01 20:03:26.000000000 +0400
+@@ -34,20 +34,21 @@
+ extern struct zebra_privs_t ospfd_privs;
+
+ #include "ospfd/ospfd.h"
+ #include "ospfd/ospf_network.h"
+ #include "ospfd/ospf_interface.h"
+ #include "ospfd/ospf_asbr.h"
+ #include "ospfd/ospf_lsa.h"
+ #include "ospfd/ospf_lsdb.h"
+ #include "ospfd/ospf_neighbor.h"
+ #include "ospfd/ospf_packet.h"
++#include "ospfd/ospf_dump.h"
+
+
+
+ /* Join to the OSPF ALL SPF ROUTERS multicast group. */
+ int
+ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
+ unsigned int ifindex)
+ {
+ int ret;
+
+@@ -226,10 +227,44 @@
+ zlog_warn ("Can't set pktinfo option for fd %d", ospf_sock);
+
+ if (ospfd_privs.change (ZPRIVS_LOWER))
+ {
+ zlog_err ("ospf_sock_init: could not lower privs, %s",
+ safe_strerror (errno) );
+ }
+
+ 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));
++}
+--- ospfd/ospf_network.h.orig 2005-05-06 21:26:18.000000000 +0400
++++ ospfd/ospf_network.h 2007-08-01 19:17:11.000000000 +0400
+@@ -27,12 +27,13 @@
+ extern int ospf_if_add_allspfrouters (struct ospf *, struct prefix *,
+ unsigned int);
+ extern int ospf_if_drop_allspfrouters (struct ospf *, struct prefix *,
+ unsigned int);
+ extern int ospf_if_add_alldrouters (struct ospf *, struct prefix *,
+ unsigned int);
+ 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 */
+--- ospfd/ospf_packet.c.orig 2007-05-10 00:59:34.000000000 +0400
++++ ospfd/ospf_packet.c 2007-08-01 18:32:36.000000000 +0400
+@@ -595,22 +595,26 @@
+ assert (node);
+ oi = listgetdata (node);
+ assert (oi);
+
+ #ifdef WANT_OSPF_WRITE_FRAGMENT
+ /* seed ipid static with low order bits of time */
+ if (ipid == 0)
+ 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);
+ assert (op);
+ assert (op->length >= OSPF_HEADER_SIZE);
+
+ if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS)
+ || op->dst.s_addr == htonl (OSPF_ALLDROUTERS))
+ ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex);
+