]> git.puffer.fish Git - matthieu/frr.git/commitdiff
When an interface goes down, any neigbors learnt on that interface
authorDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 12 Jun 2015 14:59:09 +0000 (07:59 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 12 Jun 2015 14:59:09 +0000 (07:59 -0700)
using IPv6 Router Advertisements (RAs) must be deleted. When an
interface comes up and neighbors are learnt on that interface, the
BGP FSM for any interface peer must be started only if a valid
local address exists; the local address may come up later after IPv6
Duplicate Address Detection.

bgpd/bgp_zebra.c
zebra/interface.c

index 054b0916ab9bf94348e62fc81415d16fc2b1e197..aade248f7c7ddbfd70ba55f106ae3ddd643c2786 100644 (file)
@@ -133,7 +133,7 @@ bgp_read_import_check_update(int command, struct zclient *zclient,
 }
 
 static void
-bgp_nbr_connected_add (struct nbr_connected *ifc)
+bgp_start_interface_nbrs (struct interface *ifp)
 {
   struct listnode *node, *nnode, *mnode;
   struct bgp *bgp;
@@ -143,7 +143,9 @@ bgp_nbr_connected_add (struct nbr_connected *ifc)
     {
       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
         {
-          if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0))
+          if (peer->conf_if &&
+              (strcmp (peer->conf_if, ifp->name) == 0) &&
+              peer->status != Established)
             {
               if (peer_active(peer))
                 BGP_EVENT_ADD (peer, BGP_Stop);
@@ -154,11 +156,37 @@ bgp_nbr_connected_add (struct nbr_connected *ifc)
 }
 
 static void
-bgp_nbr_connected_delete (struct nbr_connected *ifc)
+bgp_nbr_connected_add (struct nbr_connected *ifc)
+{
+  struct listnode *node;
+  struct connected *connected;
+  struct interface *ifp;
+  struct prefix *p;
+
+  /* Kick-off the FSM for any relevant peers only if there is a
+   * valid local address on the interface.
+   */
+  ifp = ifc->ifp;
+  for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
+    {
+      p = connected->address;
+      if (p->family == AF_INET6 &&
+          IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6))
+        break;
+    }
+  if (!connected)
+    return;
+
+  bgp_start_interface_nbrs (ifp);
+}
+
+static void
+bgp_nbr_connected_delete (struct nbr_connected *ifc, int del)
 {
   struct listnode *node, *nnode, *mnode;
   struct bgp *bgp;
   struct peer *peer;
+  struct interface *ifp;
 
   for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
     {
@@ -170,6 +198,13 @@ bgp_nbr_connected_delete (struct nbr_connected *ifc)
             }
         }
     }
+  /* Free neighbor also, if we're asked to. */
+  if (del)
+    {
+      ifp = ifc->ifp;
+      listnode_delete (ifp->nbr_connected, ifc);
+      nbr_connected_free (ifc);
+    }
 }
 
 /* Inteface addition message from zebra. */
@@ -251,7 +286,7 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
     bgp_connected_delete (c);
 
   for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nc))
-    bgp_nbr_connected_delete (nc);
+    bgp_nbr_connected_delete (nc, 1);
 
   /* Fast external-failover */
   {
@@ -339,7 +374,16 @@ bgp_interface_address_add (int command, struct zclient *zclient,
     }
 
   if (if_is_operative (ifc->ifp))
-    bgp_connected_add (ifc);
+    {
+      bgp_connected_add (ifc);
+      /* If we have learnt of any neighbors on this interface,
+       * check to kick off any BGP interface-based neighbors,
+       * but only if this is a link-local address.
+       */
+      if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) &&
+          !list_isempty(ifc->ifp->nbr_connected))
+        bgp_start_interface_nbrs (ifc->ifp);
+    }
 
   return 0;
 }
@@ -416,7 +460,7 @@ bgp_interface_nbr_address_delete (int command, struct zclient *zclient,
     }
 
   if (if_is_operative (ifc->ifp))
-    bgp_nbr_connected_delete (ifc);
+    bgp_nbr_connected_delete (ifc, 0);
 
   nbr_connected_free (ifc);
 
index 8af7ef7180775f9dc590b2b71c06b97d6d705b61..2f8de0b03da3762cfe42c480724f08a7d2bb5e51 100644 (file)
@@ -42,6 +42,7 @@
 #include "zebra/irdp.h"
 #include "zebra/zebra_ptm.h"
 #include "zebra/rt_netlink.h"
+#include "zebra/zserv.h"
 
 #define ZEBRA_PTM_SUPPORT
 
@@ -587,6 +588,19 @@ if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (struct interface *ifp)
     }
 }
 
+void
+if_down_del_nbr_connected (struct interface *ifp)
+{
+  struct nbr_connected *nbr_connected;
+  struct listnode *node, *nnode;
+
+  for (ALL_LIST_ELEMENTS (ifp->nbr_connected, node, nnode, nbr_connected))
+    {
+      listnode_delete (ifp->nbr_connected, nbr_connected);
+      nbr_connected_free (nbr_connected);
+    }
+}
+
 /* Interface is up. */
 void
 if_up (struct interface *ifp)
@@ -659,6 +673,9 @@ if_down (struct interface *ifp)
   rib_update ();
 
   if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
+
+  /* Delete all neighbor addresses learnt through IPv6 RA */
+  if_down_del_nbr_connected (ifp);
 }
 
 void