]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospf6d: fix ifmtu settings when kernel changes values
authorDon Slice <dslice@cumulusnetworks.com>
Thu, 22 Jun 2017 16:17:24 +0000 (09:17 -0700)
committerDon Slice <dslice@cumulusnetworks.com>
Mon, 26 Jun 2017 15:07:23 +0000 (11:07 -0400)
Problem reported by customer that if an mtu value was set in the kernel,
quagga/frr would get very confused about what had been configured and
what had been learned.  This caused peers to not be successfully established.
Resolved by keeping a configuration value separate than the operational value
and set the operational accordingly.  If configured, it wins unless the config
defines a value that is higher than the kernel supports.

Ticket: CM-16876
Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
Reviewed By: CCR-6399
Testing Done: Manual testing successful, submitter tested, ospf-smoke completed
with no new failures.

ospf6d/ospf6_interface.c
ospf6d/ospf6_interface.h

index 111ca3f3d26d6e32742531636925f3a026cb67f2..4d07e24b8821dbf4299ecc1ef9a4628c44c1c50f 100644 (file)
@@ -202,6 +202,7 @@ ospf6_interface_create (struct interface *ifp)
   oi->state = OSPF6_INTERFACE_DOWN;
   oi->flag = 0;
   oi->mtu_ignore = 0;
+  oi->c_ifmtu = 0;
 
   /* Try to adjust I/O buffer size with IfMtu */
   oi->ifmtu = ifp->mtu6;
@@ -388,6 +389,22 @@ ospf6_interface_state_update (struct interface *ifp)
   if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
     return;
 
+  /* Adjust the mtu values if the kernel told us something new */
+  if (ifp->mtu6 != oi->ifmtu)
+    {
+      /* If nothing configured, just accept it */
+      if (!oi->c_ifmtu)
+        oi->ifmtu = ifp->mtu6;
+      else if (oi->c_ifmtu > ifp->mtu6)
+        {
+          oi->ifmtu = ifp->mtu6;
+          zlog_warn ("Configured mtu %u on %s overridden by kernel %u",
+                      oi->c_ifmtu, ifp->name, ifp->mtu6);
+        }
+      else
+        oi->ifmtu = oi->c_ifmtu;
+    }
+
   if (if_is_operative (ifp)
       && (ospf6_interface_get_linklocal_address(oi->interface)
           || if_is_loopback(oi->interface)))
@@ -1112,7 +1129,7 @@ DEFUN (ipv6_ospf6_ifmtu,
 
   ifmtu = strtol (argv[idx_number]->arg, NULL, 10);
 
-  if (oi->ifmtu == ifmtu)
+  if (oi->c_ifmtu == ifmtu)
     return CMD_SUCCESS;
 
   if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu)
@@ -1129,13 +1146,13 @@ DEFUN (ipv6_ospf6_ifmtu,
         {
           vty_out (vty, "%s's ifmtu is adjusted to I/O buffer size (%d).%s",
                    ifp->name, iobuflen, VNL);
-          oi->ifmtu = iobuflen;
+          oi->ifmtu = oi->c_ifmtu = iobuflen;
         }
       else
-        oi->ifmtu = ifmtu;
+        oi->ifmtu = oi->c_ifmtu = ifmtu;
     }
   else
-    oi->ifmtu = ifmtu;
+    oi->ifmtu = oi->c_ifmtu = ifmtu;
 
   /* re-establish adjacencies */
   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
@@ -1149,11 +1166,12 @@ DEFUN (ipv6_ospf6_ifmtu,
 
 DEFUN (no_ipv6_ospf6_ifmtu,
        no_ipv6_ospf6_ifmtu_cmd,
-       "no ipv6 ospf6 ifmtu",
+       "no ipv6 ospf6 ifmtu [(1-65535)]",
        NO_STR
        IP6_STR
        OSPF6_STR
        "Interface MTU\n"
+       "OSPFv3 Interface MTU\n"
        )
 {
   VTY_DECLVAR_CONTEXT(interface, ifp);
@@ -1184,6 +1202,8 @@ DEFUN (no_ipv6_ospf6_ifmtu,
   else
     oi->ifmtu = ifp->mtu;
 
+  oi->c_ifmtu = 0;
+
   /* re-establish adjacencies */
   for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
     {
@@ -1745,8 +1765,8 @@ config_write_ospf6_interface (struct vty *vty)
 
       if (ifp->desc)
         vty_out (vty, " description %s%s", ifp->desc, VNL);
-      if (ifp->mtu6 != oi->ifmtu)
-        vty_out (vty, " ipv6 ospf6 ifmtu %d%s", oi->ifmtu, VNL);
+      if (oi->c_ifmtu)
+        vty_out (vty, " ipv6 ospf6 ifmtu %d%s", oi->c_ifmtu, VNL);
 
       if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
         vty_out (vty, " ipv6 ospf6 cost %d%s",
index 0408fc69d6305b56a79e73540ce3cdc723f37edd..327402d752f9ef7ad0f374337295f34d85231b04 100644 (file)
@@ -76,6 +76,9 @@ struct ospf6_interface
   /* I/F MTU */
   u_int32_t ifmtu;
 
+  /* Configured MTU */
+  u_int32_t c_ifmtu;
+
   /* Interface State */
   u_char state;