]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospfd/ospf_network.c
Support for multi-client and client reg msg
[mirror_frr.git] / ospfd / ospf_network.c
index 63851879e7bc637ffa330eb0f0fd4569fd3e4015..2f167a50a5e0fcaf459d675eaf8c00a93dc7b464 100644 (file)
@@ -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"
 
 
 
@@ -51,15 +52,17 @@ ospf_if_add_allspfrouters (struct ospf *top, struct prefix *p,
 {
   int ret;
   
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP,
-                                   p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
+  ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
+                                   htonl (OSPF_ALLSPFROUTERS),
                                    ifindex);
   if (ret < 0)
-    zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (AllSPFRouters): %s",
-               strerror (errno));
+    zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
+              "ifindex %u, AllSPFRouters): %s; perhaps a kernel limit "
+              "on # of multicast group memberships has been exceeded?",
+               top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
   else
-    zlog_info ("interface %s join AllSPFRouters Multicast group.",
-              inet_ntoa (p->u.prefix4));
+    zlog_debug ("interface %s [%u] join AllSPFRouters Multicast group.",
+              inet_ntoa (p->u.prefix4), ifindex);
 
   return ret;
 }
@@ -70,15 +73,16 @@ ospf_if_drop_allspfrouters (struct ospf *top, struct prefix *p,
 {
   int ret;
 
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP,
-                                   p->u.prefix4, htonl (OSPF_ALLSPFROUTERS),
+  ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
+                                   htonl (OSPF_ALLSPFROUTERS),
                                    ifindex);
   if (ret < 0)
-    zlog_warn("can't setsockopt IP_DROP_MEMBERSHIP (AllSPFRouters): %s",
-             strerror (errno));
+    zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
+              "ifindex %u, AllSPFRouters): %s",
+               top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
   else
-    zlog_info ("interface %s leave AllSPFRouters Multicast group.",
-              inet_ntoa (p->u.prefix4));
+    zlog_debug ("interface %s [%u] leave AllSPFRouters Multicast group.",
+               inet_ntoa (p->u.prefix4), ifindex);
 
   return ret;
 }
@@ -90,15 +94,17 @@ ospf_if_add_alldrouters (struct ospf *top, struct prefix *p, unsigned int
 {
   int ret;
 
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_ADD_MEMBERSHIP,
-                                   p->u.prefix4, htonl (OSPF_ALLDROUTERS),
+  ret = setsockopt_ipv4_multicast (top->fd, IP_ADD_MEMBERSHIP,
+                                   htonl (OSPF_ALLDROUTERS),
                                    ifindex);
   if (ret < 0)
-    zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (AllDRouters): %s",
-               strerror (errno));
+    zlog_warn ("can't setsockopt IP_ADD_MEMBERSHIP (fd %d, addr %s, "
+              "ifindex %u, AllDRouters): %s; perhaps a kernel limit "
+              "on # of multicast group memberships has been exceeded?",
+               top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
   else
-    zlog_info ("interface %s join AllDRouters Multicast group.",
-              inet_ntoa (p->u.prefix4));
+    zlog_debug ("interface %s [%u] join AllDRouters Multicast group.",
+               inet_ntoa (p->u.prefix4), ifindex);
 
   return ret;
 }
@@ -109,15 +115,16 @@ ospf_if_drop_alldrouters (struct ospf *top, struct prefix *p, unsigned int
 {
   int ret;
 
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_DROP_MEMBERSHIP,
-                                   p->u.prefix4, htonl (OSPF_ALLDROUTERS),
+  ret = setsockopt_ipv4_multicast (top->fd, IP_DROP_MEMBERSHIP,
+                                   htonl (OSPF_ALLDROUTERS),
                                    ifindex);
   if (ret < 0)
-    zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (AllDRouters): %s",
-              strerror (errno));
+    zlog_warn ("can't setsockopt IP_DROP_MEMBERSHIP (fd %d, addr %s, "
+              "ifindex %u, AllDRouters): %s",
+               top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
   else
-    zlog_info ("interface %s leave AllDRouters Multicast group.",
-              inet_ntoa (p->u.prefix4));
+    zlog_debug ("interface %s [%u] leave AllDRouters Multicast group.",
+               inet_ntoa (p->u.prefix4), ifindex);
 
   return ret;
 }
@@ -134,18 +141,21 @@ ospf_if_ipmulticast (struct ospf *top, struct prefix *p, unsigned int ifindex)
   /* Prevent receiving self-origined multicast packets. */
   ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&val, len);
   if (ret < 0)
-    zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0): %s", strerror (errno));
+    zlog_warn ("can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s",
+              top->fd, safe_strerror(errno));
   
   /* Explicitly set multicast ttl to 1 -- endo. */
   val = 1;
   ret = setsockopt (top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len);
   if (ret < 0)
-    zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1): %s", strerror (errno));
+    zlog_warn ("can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s",
+              top->fd, safe_strerror (errno));
 
-  ret = setsockopt_multicast_ipv4 (top->fd, IP_MULTICAST_IF,
-                                   p->u.prefix4, 0, ifindex);
+  ret = setsockopt_ipv4_multicast_if (top->fd, ifindex);
   if (ret < 0)
-    zlog_warn ("can't setsockopt IP_MULTICAST_IF: %s", strerror (errno));
+    zlog_warn("can't setsockopt IP_MULTICAST_IF(fd %d, addr %s, "
+             "ifindex %u): %s",
+             top->fd, inet_ntoa(p->u.prefix4), ifindex, safe_strerror(errno));
 
   return ret;
 }
@@ -154,20 +164,24 @@ int
 ospf_sock_init (void)
 {
   int ospf_sock;
-  int ret, tos, hincl = 1;
+  int ret, hincl = 1;
+  int bufsize = (8 * 1024 * 1024);
+  int optval;
+  socklen_t optlen = sizeof(optval);
 
   if ( ospfd_privs.change (ZPRIVS_RAISE) )
     zlog_err ("ospf_sock_init: could not raise privs, %s",
-               strerror (errno) );
+               safe_strerror (errno) );
     
   ospf_sock = socket (AF_INET, SOCK_RAW, IPPROTO_OSPFIGP);
   if (ospf_sock < 0)
     {
+      int save_errno = errno;
       if ( ospfd_privs.change (ZPRIVS_LOWER) )
         zlog_err ("ospf_sock_init: could not lower privs, %s",
-                   strerror (errno) );
-      zlog_err ("ospf_read_sock_init: socket: %s", strerror (errno));
-      exit(-1);
+                   safe_strerror (errno) );
+      zlog_err ("ospf_read_sock_init: socket: %s", safe_strerror (save_errno));
+      exit(1);
     }
     
 #ifdef IP_HDRINCL
@@ -175,24 +189,25 @@ ospf_sock_init (void)
   ret = setsockopt (ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof (hincl));
   if (ret < 0)
     {
+      int save_errno = errno;
       if ( ospfd_privs.change (ZPRIVS_LOWER) )
         zlog_err ("ospf_sock_init: could not lower privs, %s",
-                   strerror (errno) );
-      zlog_warn ("Can't set IP_HDRINCL option");
+                   safe_strerror (errno) );
+      zlog_warn ("Can't set IP_HDRINCL option for fd %d: %s",
+                ospf_sock, safe_strerror(save_errno));
     }
 #elif defined (IPTOS_PREC_INTERNETCONTROL)
 #warning "IP_HDRINCL not available on this system"
 #warning "using IPTOS_PREC_INTERNETCONTROL"
-  /* Set precedence field. */
-  tos = IPTOS_PREC_INTERNETCONTROL;
-  ret = setsockopt (ospf_sock, IPPROTO_IP, IP_TOS,
-                   (char *) &tos, sizeof (int));
+  ret = setsockopt_ipv4_tos(ospf_sock, IPTOS_PREC_INTERNETCONTROL);
   if (ret < 0)
     {
+      int save_errno = errno;
       if ( ospfd_privs.change (ZPRIVS_LOWER) )
         zlog_err ("ospf_sock_init: could not lower privs, %s",
-                   strerror (errno) );
-      zlog_warn ("can't set sockopt IP_TOS %d to socket %d", tos, ospf_sock);
+                   safe_strerror (errno) );
+      zlog_warn ("can't set sockopt IP_TOS %d to socket %d: %s",
+                tos, ospf_sock, safe_strerror(save_errno));
       close (ospf_sock);       /* Prevent sd leak. */
       return ret;
     }
@@ -201,15 +216,83 @@ ospf_sock_init (void)
   zlog_warn ("IP_HDRINCL option not available");
 #endif /* IP_HDRINCL */
 
-  ret = setsockopt_pktinfo (AF_INET, ospf_sock, 1);
+  ret = setsockopt_ifindex (AF_INET, ospf_sock, 1);
+
   if (ret < 0)
-     zlog_warn ("Can't set pktinfo option");
+     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",
-               strerror (errno) );
+               safe_strerror (errno) );
+    }
+
+  if ((ret = setsockopt (ospf_sock, SOL_SOCKET, SO_RCVBUF,
+                        &bufsize, sizeof (bufsize))) < 0)
+    {
+      zlog_err ("Couldn't increase raw rbuf size: %s\n", safe_strerror(errno));
+    }
+
+  if ((ret = getsockopt (ospf_sock, SOL_SOCKET, SO_RCVBUF,
+                        &optval, &optlen)) < 0)
+    {
+      zlog_err("getsockopt of SO_RCVBUF failed with error %s\n", safe_strerror(errno));
+    }
+  if (optval < bufsize)
+    {
+      zlog_err("Unable to SO_RCVBUF to %d, set to %d\n", bufsize, optval);
+    }
+
+
+  if ((ret = setsockopt (ospf_sock, SOL_SOCKET, SO_SNDBUF,
+                        &bufsize, sizeof (bufsize))) < 0)
+    {
+      zlog_err ("Couldn't increase raw wbuf size: %s\n", safe_strerror(errno));
+    }
+
+  if ((ret = getsockopt (ospf_sock, SOL_SOCKET, SO_SNDBUF,
+                        &optval, &optlen)) < 0)
+    {
+      zlog_err ("getsockopt of SO_SNDBUF failed with error %s\n", safe_strerror(errno));
+    }
+  if (optval < bufsize)
+    {
+      zlog_err ("Unable to SO_SNDBUF to %d, set to %d\n", bufsize, optval);
     }
  
   return ospf_sock;
 }
+
+void
+ospf_adjust_sndbuflen (struct ospf * ospf, unsigned 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
+   * (the MTU of a newly added interface). However, if the OS has
+   * truncated the actual buffer size to somewhat less size, try
+   * to detect it and update our records appropriately. The OS
+   * may allocate more buffer space, than requested, this isn't
+   * a error.
+   */
+  ret = setsockopt_so_sendbuf (ospf->fd, buflen);
+  newbuflen = getsockopt_so_sendbuf (ospf->fd);
+  if (ret < 0 || newbuflen < 0 || newbuflen < (int) buflen)
+    zlog_warn ("%s: tried to set SO_SNDBUF to %u, but got %d",
+      __func__, buflen, newbuflen);
+  if (newbuflen >= 0)
+    ospf->maxsndbuflen = (unsigned int)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));
+}