]> git.puffer.fish Git - mirror/frr.git/commitdiff
BGP: VRF registration and cleanup
authorvivek <vivek@cumulusnetworks.com>
Fri, 12 Feb 2016 20:18:28 +0000 (12:18 -0800)
committervivek <vivek@cumulusnetworks.com>
Fri, 12 Feb 2016 21:50:22 +0000 (13:50 -0800)
Various changes and fixes related to VRF registration, deletion,
BGP exit etc.

- Define instance type
- Ensure proper handling upon instance create, delete and
  VRF add/delete from zebra
- Cleanup upon bgp_exit()
- Ensure messages are not sent to zebra for unknown VRFs

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Ticket: CM-9128, CM-7203
Reviewed By: CCR-4098
Testing Done: Manual

bgpd/bgp_fsm.c
bgpd/bgp_main.c
bgpd/bgp_nht.c
bgpd/bgp_nht.h
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.c
bgpd/bgpd.h

index 791064aca8ad7dd7e36bf9c3567e2094f68aeae3..962c528948fa15dbd1c7792deff917efba605b0d 100644 (file)
@@ -207,11 +207,6 @@ peer_xfer_conn(struct peer *from_peer)
   return(peer);
 }
 
-/* Check if suppress start/restart of sessions to peer. */
-#define BGP_PEER_START_SUPPRESSED(P) \
-  (CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \
-   || CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW))
-
 /* Hook function called after bgp event is occered.  And vty's
    neighbor command invoke this function after making neighbor
    structure. */
index 02dc3110febc0f6d9556eeddb58570eaba7fe7e9..7c1a9ea4a64b6e7159b51da0edc4cb5a7f26c56e 100644 (file)
@@ -236,20 +236,11 @@ bgp_exit (int status)
     bgp_delete (bgp);
   list_free (bm->bgp);
 
-  /* reverse bgp_zebra_init/if_init */
   if (retain_mode)
     if_add_hook (IF_DELETE_HOOK, NULL);
-  /*Pending: Must-Do, this needs to be moved in a loop for all the instances..
-    Do the iflist lookup for vrf associated with the instance
-  for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
-    {
-      struct listnode *c_node, *c_nnode;
-      struct connected *c;
 
-      for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
-        bgp_connected_delete (c);
-    }
-    */
+  /* free interface and connected route information. */
+  bgp_if_finish ();
 
   /* reverse bgp_attr_init */
   bgp_attr_finish ();
index 5b54c4b1f0d87e86858fdfa1b89a1200e05e2740..9d8d8f3b527ce0dafeb450e268f461804a0e7782 100644 (file)
@@ -539,15 +539,11 @@ sendmsg_zebra_rnh (struct bgp_nexthop_cache *bnc, int command)
 
   /* Check socket. */
   if (!zclient || zclient->sock < 0)
-    {
-      /* Hiding this error now, because bgp_nht_register_all() is implemented.
-         which tries it after zclient_connect()
-         zlog_debug("%s: Can't send NH register, Zebra client not established",
-                __FUNCTION__);
-         Pending: remove this comment after reviewing to see if no message is needed in this case
-       */
-      return;
-    }
+    return;
+
+  /* Don't try to register if Zebra doesn't know of this instance. */
+  if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp))
+    return;
 
   p = &(bnc->node->p);
   s = zclient->obuf;
@@ -702,48 +698,6 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
   RESET_FLAG(bnc->change_flags);
 }
 
-void
-bgp_nht_register_all (vrf_id_t vrf_id)
-{
-  struct bgp_node *rn;
-  struct bgp_nexthop_cache *bnc;
-  struct bgp *bgp;
-
-  bgp = bgp_lookup_by_vrf_id (vrf_id);
-  if (!bgp)
-    {
-      zlog_err("bgp_nht_register_all: instance not found for vrf_id %d", vrf_id);
-      return;
-    }
-
-  for (rn = bgp_table_top (bgp->nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
-    if ((bnc = rn->info) != NULL &&
-        !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
-      {
-        register_zebra_rnh(bnc, 0);
-      }
-  for (rn = bgp_table_top (bgp->nexthop_cache_table[AFI_IP6]); rn; rn = bgp_route_next (rn))
-    if ((bnc = rn->info) != NULL &&
-        !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
-      {
-        register_zebra_rnh(bnc, 0);
-      }
-
-  for (rn = bgp_table_top (bgp->import_check_table[AFI_IP]); rn; rn = bgp_route_next (rn))
-    if ((bnc = rn->info) != NULL &&
-        !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
-      {
-        register_zebra_rnh(bnc, 1);
-      }
-  for (rn = bgp_table_top (bgp->import_check_table[AFI_IP6]); rn; rn = bgp_route_next (rn))
-    if ((bnc = rn->info) != NULL &&
-        !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
-      {
-        register_zebra_rnh(bnc, 1);
-      }
-
-}
-
 /**
  * path_nh_map - make or break path-to-nexthop association.
  * ARGUMENTS:
index 4fc45e88d0bece39ad922bcdd1649ada898ebf57..af64750d755b97e2ed0e5fd36018b0e75ccbb299 100644 (file)
@@ -22,8 +22,6 @@
 #ifndef _BGP_NHT_H
 #define _BGP_NHT_H
 
-extern void bgp_nht_register_all (vrf_id_t);
-
 /**
  * bgp_parse_nexthop_update() - parse a nexthop update message from Zebra.
  */
index fb0e8b3831325eb42a9a179ba5bab6da3a7d1b42..ef2f07caf20c1590031af4a7e835cbe9d4117aef 100644 (file)
@@ -1828,8 +1828,9 @@ bgp_process_main (struct work_queue *wq, void *data)
   group_announce_route(bgp, afi, safi, rn, new_select);
 
   /* FIB update. */
-  if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) && (! bgp_flag_check(bgp, BGP_FLAG_INSTANCE_TYPE_VIEW) &&
-      ! bgp_option_check (BGP_OPT_NO_FIB)))
+  if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) &&
+      (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) &&
+      !bgp_option_check (BGP_OPT_NO_FIB))
     {
       if (new_select 
          && new_select->type == ZEBRA_ROUTE_BGP 
@@ -3784,6 +3785,48 @@ bgp_static_redo_import_check (struct bgp *bgp)
   bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
 }
 
+static void
+bgp_purge_af_static_redist_routes (struct bgp *bgp, afi_t afi, safi_t safi)
+{
+  struct bgp_table *table;
+  struct bgp_node *rn;
+  struct bgp_info *ri;
+
+  table = bgp->rib[afi][safi];
+  for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+    {
+      for (ri = rn->info; ri; ri = ri->next)
+        {
+          if (ri->peer == bgp->peer_self &&
+              ((ri->type == ZEBRA_ROUTE_BGP &&
+                ri->sub_type == BGP_ROUTE_STATIC) ||
+               (ri->type != ZEBRA_ROUTE_BGP &&
+                ri->sub_type == BGP_ROUTE_REDISTRIBUTE)))
+            {
+              bgp_aggregate_decrement (bgp, &rn->p, ri, afi, safi);
+              bgp_unlink_nexthop(ri);
+              bgp_info_delete (rn, ri);
+              bgp_process (bgp, rn, afi, safi);
+            }
+        }
+    }
+}
+
+/*
+ * Purge all networks and redistributed routes from routing table.
+ * Invoked upon the instance going down.
+ */
+void
+bgp_purge_static_redist_routes (struct bgp *bgp)
+{
+  afi_t afi;
+  safi_t safi;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+      bgp_purge_af_static_redist_routes (bgp, afi, safi);
+}
+
 int
 bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str,
                      const char *tag_str)
index 3a2d9382896a4acd0d9f42137d9436c2b9f2b46f..cc26249686a77fa5bc6536c103490f971249e112 100644 (file)
@@ -248,6 +248,7 @@ extern void bgp_redistribute_withdraw (struct bgp *, afi_t, int, u_short);
 extern void bgp_static_add (struct bgp *);
 extern void bgp_static_delete (struct bgp *);
 extern void bgp_static_redo_import_check (struct bgp *);
+extern void bgp_purge_static_redist_routes (struct bgp *bgp);
 extern void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static *,
                        afi_t, safi_t);
 extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t);
index a9ff7577806ba90cbaa27019311797f83e955907..cda5fc1c8d5faee52860c265d581b6ecc511f8dd 100644 (file)
@@ -607,6 +607,7 @@ DEFUN (router_bgp,
   as_t as;
   struct bgp *bgp;
   const char *name = NULL;
+  enum bgp_instance_type inst_type;
 
   // "router bgp" without an ASN
   if (argc < 1)
@@ -632,10 +633,17 @@ DEFUN (router_bgp,
     {
       VTY_GET_INTEGER_RANGE ("AS", as, argv[0], 1, BGP_AS4_MAX);
 
+      inst_type = BGP_INSTANCE_TYPE_DEFAULT;
       if (argc == 3)
-        name = argv[2];
+        {
+          name = argv[2];
+          if (!strcmp(argv[1], "vrf")) 
+            inst_type = BGP_INSTANCE_TYPE_VRF;
+          else if (!strcmp(argv[1], "view")) 
+            inst_type = BGP_INSTANCE_TYPE_VIEW;
+        }
 
-      ret = bgp_get (&bgp, &as, name);
+      ret = bgp_get (&bgp, &as, name, inst_type);
       switch (ret)
         {
         case BGP_ERR_MULTIPLE_INSTANCE_NOT_SET:
@@ -653,10 +661,6 @@ DEFUN (router_bgp,
         }
 
       /* Pending: handle when user tries to change a view to vrf n vv. */
-      if (argc == 3 && !strcmp(argv[1], "vrf")) 
-        bgp_flag_set (bgp, BGP_FLAG_INSTANCE_TYPE_VRF);
-      if (argc == 3 && !strcmp(argv[1], "view")) 
-        bgp_flag_set (bgp, BGP_FLAG_INSTANCE_TYPE_VIEW);
     }
 
   vty->node = BGP_NODE;
index 9ffe44f267e6be5c949ffba3f8d209e1110a3f27..8a171045ffd35c2c0bb499abcca9ea828142b595 100644 (file)
@@ -89,6 +89,20 @@ do { \
   bgp_attr_deep_free(info->attr); \
 } while (0)
 
+
+/* Can we install into zebra? */
+static inline int
+bgp_install_info_to_zebra (struct bgp *bgp)
+{
+  if (zclient->sock <= 0)
+    return 0;
+
+  if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
+    return 0;
+
+  return 1;
+}
+
 /* Router-id update message from zebra. */
 static int
 bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
@@ -104,15 +118,15 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
     {
       char buf[PREFIX2STR_BUFFER];
       prefix2str(&router_id, buf, sizeof(buf));
-      zlog_debug("Zebra rcvd: router id update %s vrf %u", buf, vrf_id);
+      zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf);
     }
 
-  if (!vrf_id)
+  if (vrf_id == VRF_DEFAULT)
     {
-      /* This is to cover all the views */
+      /* Router-id change for default VRF has to also update all views. */
       for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
         {
-          if (bgp_flag_check(bgp, BGP_FLAG_INSTANCE_TYPE_VRF))
+          if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
             continue;
 
           bgp->router_id_zebra = router_id.u.prefix4;
@@ -220,7 +234,7 @@ bgp_nbr_connected_delete (struct bgp *bgp, struct nbr_connected *ifc, int del)
     }
 }
 
-/* Inteface addition message from zebra. */
+/* VRF learnt from Zebra. */
 static int
 bgp_vrf_add (int command, struct zclient *zclient, zebra_size_t length,
     vrf_id_t vrf_id)
@@ -229,46 +243,24 @@ bgp_vrf_add (int command, struct zclient *zclient, zebra_size_t length,
   struct bgp *bgp;
 
   vrf = zebra_vrf_add_read (zclient->ibuf, vrf_id);
+  if (!vrf) // unexpected
+    return -1;
 
-  if (BGP_DEBUG (zebra, ZEBRA) && vrf)
-    zlog_debug("Zebra rcvd: vrf add %s", vrf->name);
+  if (BGP_DEBUG (zebra, ZEBRA))
+    zlog_debug("Rx VRF add %s id %d", vrf->name, vrf_id);
 
   bgp = bgp_lookup_by_name(vrf->name);
   if (bgp)
     {
+      /* We have instance configured, make it "up". */
       bgp->vrf_id = vrf_id;
-
-      if (BGP_DEBUG (zebra, ZEBRA) && vrf)
-        zlog_debug("zclient_send_reg_requests %u", vrf_id);
-
-      zclient_send_reg_requests (zclient, vrf_id);
-
       bgp_instance_up (bgp);
-      //Pending: See if the following can be moved inside bgp_instance_up ()
-      bgp_nht_register_all(vrf_id);
-      
     }
 
   return 0;
 }
 
-void
-bgp_vrf_update (struct bgp *bgp)
-{
-  struct vrf *vrf;
-
-  if (bgp->name)
-    {
-      vrf = vrf_lookup_by_name(bgp->name);
-      if (vrf)
-        bgp->vrf_id = vrf->vrf_id;
-    }
-
-  zclient_send_reg_requests (zclient, bgp->vrf_id);
-  bgp_nht_register_all (bgp->vrf_id);
-}
-
-/* Inteface deletion message from zebra. */
+/* VRF deleted by Zebra. */
 static int
 bgp_vrf_delete (int command, struct zclient *zclient, zebra_size_t length,
     vrf_id_t vrf_id)
@@ -276,18 +268,25 @@ bgp_vrf_delete (int command, struct zclient *zclient, zebra_size_t length,
   struct vrf *vrf;
   struct bgp *bgp;
 
+  /* Default VRF cannot be deleted. */
+  assert (vrf_id != VRF_DEFAULT);
+
   vrf = zebra_vrf_state_read (zclient->ibuf, vrf_id);
+  if (!vrf) // unexpected
+    return -1;
 
-  if (BGP_DEBUG (zebra, ZEBRA) && vrf)
-    zlog_debug("Zebra rcvd: vrf delete %s", vrf->name);
+  if (BGP_DEBUG (zebra, ZEBRA))
+    zlog_debug("Rx VRF del %s id %d", vrf->name, vrf_id);
 
   bgp = bgp_lookup_by_name(vrf->name);
   if (bgp)
     {
+      /* We have instance configured, make it "down". */
+      bgp->vrf_id = VRF_DEFAULT;
       bgp_instance_down (bgp);
-      bgp->vrf_id = 0;
     }
 
+  /* Note: This is a callback, the VRF will be deleted by the caller. */
   return 0;
 }
 
@@ -303,7 +302,7 @@ bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length,
   ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
 
   if (BGP_DEBUG (zebra, ZEBRA) && ifp)
-    zlog_debug("Zebra rcvd: interface add %s", ifp->name);
+    zlog_debug("Rx Intf add VRF %u IF %s", vrf_id, ifp->name);
 
   return 0;
 }
@@ -320,7 +319,7 @@ bgp_interface_delete (int command, struct zclient *zclient,
   ifp->ifindex = IFINDEX_INTERNAL;
 
   if (BGP_DEBUG (zebra, ZEBRA))
-    zlog_debug("Zebra rcvd: interface delete %s", ifp->name);
+    zlog_debug("Rx Intf del VRF %u IF %s", vrf_id, ifp->name);
 
   return 0;
 }
@@ -336,10 +335,6 @@ bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length,
   struct listnode *node, *nnode;
   struct bgp *bgp;
 
-  bgp = bgp_lookup_by_vrf_id (vrf_id);
-  if (!bgp)
-    return 0;
-
   s = zclient->ibuf;
   ifp = zebra_interface_state_read (s, vrf_id);
 
@@ -347,7 +342,11 @@ bgp_interface_up (int command, struct zclient *zclient, zebra_size_t length,
     return 0;
 
   if (BGP_DEBUG (zebra, ZEBRA))
-    zlog_debug("Zebra rcvd: interface %s up", ifp->name);
+    zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name);
+
+  bgp = bgp_lookup_by_vrf_id (vrf_id);
+  if (!bgp)
+    return 0;
 
   for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
     bgp_connected_add (bgp, c);
@@ -369,17 +368,17 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length,
   struct listnode *node, *nnode;
   struct bgp *bgp;
 
-  bgp = bgp_lookup_by_vrf_id (vrf_id);
-  if (!bgp)
-    return 0;
-
   s = zclient->ibuf;
   ifp = zebra_interface_state_read (s, vrf_id);
   if (! ifp)
     return 0;
 
   if (BGP_DEBUG (zebra, ZEBRA))
-    zlog_debug("Zebra rcvd: interface %s down", ifp->name);
+    zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name);
+
+  bgp = bgp_lookup_by_vrf_id (vrf_id);
+  if (!bgp)
+    return 0;
 
   for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, c))
     bgp_connected_delete (bgp, c);
@@ -389,23 +388,18 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length,
 
   /* Fast external-failover */
   {
-    struct listnode *mnode;
-    struct bgp *bgp;
     struct peer *peer;
 
-    for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
-      {
-       if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
-         continue;
+    if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
+      return 0;
 
-       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
-         {
-           if ((peer->ttl != 1) && (peer->gtsm_hops != 1))
-             continue;
+    for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+      {
+        if ((peer->ttl != 1) && (peer->gtsm_hops != 1))
+          continue;
 
-           if (ifp == peer->nexthop.ifp)
-             BGP_EVENT_ADD (peer, BGP_Stop);
-         }
+        if (ifp == peer->nexthop.ifp)
+          BGP_EVENT_ADD (peer, BGP_Stop);
       }
   }
 
@@ -427,8 +421,8 @@ bgp_interface_address_add (int command, struct zclient *zclient,
     {
       char buf[PREFIX2STR_BUFFER];
       prefix2str(ifc->address, buf, sizeof(buf));
-      zlog_debug("Zebra rcvd: interface %s address add %s",
-                ifc->ifp->name, buf);
+      zlog_debug("Rx Intf address add VRF %u IF %s addr %s",
+                 vrf_id, ifc->ifp->name, buf);
     }
 
   if (if_is_operative (ifc->ifp))
@@ -437,10 +431,7 @@ bgp_interface_address_add (int command, struct zclient *zclient,
 
       bgp = bgp_lookup_by_vrf_id (vrf_id);
       if (!bgp)
-        {
-          zlog_err("instance not found\n");
-          return 0;
-        }
+        return 0;
 
       bgp_connected_add (bgp, ifc);
       /* If we have learnt of any neighbors on this interface,
@@ -462,10 +453,6 @@ bgp_interface_address_delete (int command, struct zclient *zclient,
   struct connected *ifc;
   struct bgp *bgp;
 
-  bgp = bgp_lookup_by_vrf_id (vrf_id);
-  if (!bgp)
-    return 0;
-
   ifc = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
 
   if (ifc == NULL)
@@ -475,12 +462,16 @@ bgp_interface_address_delete (int command, struct zclient *zclient,
     {
       char buf[PREFIX2STR_BUFFER];
       prefix2str(ifc->address, buf, sizeof(buf));
-      zlog_debug("Zebra rcvd: interface %s address delete %s",
-                ifc->ifp->name, buf);
+      zlog_debug("Rx Intf address del VRF %u IF %s addr %s",
+                 vrf_id, ifc->ifp->name, buf);
     }
 
   if (if_is_operative (ifc->ifp))
-    bgp_connected_delete (bgp, ifc);
+    {
+      bgp = bgp_lookup_by_vrf_id (vrf_id);
+      if (bgp)
+        bgp_connected_delete (bgp, ifc);
+    }
 
   connected_free (ifc);
 
@@ -494,10 +485,6 @@ bgp_interface_nbr_address_add (int command, struct zclient *zclient,
   struct nbr_connected *ifc = NULL;
   struct bgp *bgp;
 
-  bgp = bgp_lookup_by_vrf_id (vrf_id);
-  if (!bgp)
-    return 0;
-
   ifc = zebra_interface_nbr_address_read (command, zclient->ibuf, vrf_id);
 
   if (ifc == NULL)
@@ -507,12 +494,16 @@ bgp_interface_nbr_address_add (int command, struct zclient *zclient,
     {
       char buf[PREFIX2STR_BUFFER];
       prefix2str(ifc->address, buf, sizeof(buf));
-      zlog_debug("Zebra rcvd: interface %s nbr address add %s",
-                ifc->ifp->name, buf);
+      zlog_debug("Rx Intf neighbor add VRF %u IF %s addr %s",
+                 vrf_id, ifc->ifp->name, buf);
     }
 
   if (if_is_operative (ifc->ifp))
-    bgp_nbr_connected_add (bgp, ifc);
+    {
+      bgp = bgp_lookup_by_vrf_id (vrf_id);
+      if (bgp)
+        bgp_nbr_connected_add (bgp, ifc);
+    }
 
   return 0;
 }
@@ -524,10 +515,6 @@ bgp_interface_nbr_address_delete (int command, struct zclient *zclient,
   struct nbr_connected *ifc = NULL;
   struct bgp *bgp;
 
-  bgp = bgp_lookup_by_vrf_id (vrf_id);
-  if (!bgp)
-    return 0;
-
   ifc = zebra_interface_nbr_address_read (command, zclient->ibuf, vrf_id);
 
   if (ifc == NULL)
@@ -537,12 +524,16 @@ bgp_interface_nbr_address_delete (int command, struct zclient *zclient,
     {
       char buf[PREFIX2STR_BUFFER];
       prefix2str(ifc->address, buf, sizeof(buf));
-      zlog_debug("Zebra rcvd: interface %s nbr address delete %s",
-                ifc->ifp->name, buf);
+      zlog_debug("Rx Intf neighbor del VRF %u IF %s addr %s",
+                 vrf_id, ifc->ifp->name, buf);
     }
 
   if (if_is_operative (ifc->ifp))
-    bgp_nbr_connected_delete (bgp, ifc, 0);
+    {
+      bgp = bgp_lookup_by_vrf_id (vrf_id);
+      if (bgp)
+        bgp_nbr_connected_delete (bgp, ifc, 0);
+    }
 
   nbr_connected_free (ifc);
 
@@ -616,7 +607,8 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length,
       if (bgp_debug_zebra((struct prefix *)&p))
        {
          char buf[2][INET_ADDRSTRLEN];
-         zlog_debug("Zebra rcvd: IPv4 route add %s[%d] %s/%d nexthop %s metric %u tag %d",
+         zlog_debug("Rx IPv4 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %d",
+                     vrf_id,
                     zebra_route_string(api.type), api.instance,
                     inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
                     p.prefixlen,
@@ -646,8 +638,9 @@ zebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length,
       if (bgp_debug_zebra((struct prefix *)&p))
        {
          char buf[2][INET_ADDRSTRLEN];
-         zlog_debug("Zebra rcvd: IPv4 route delete %s[%d] %s/%d "
+         zlog_debug("Rx IPv4 route delete VRF %u %s[%d] %s/%d "
                     "nexthop %s metric %u tag %d",
+                     vrf_id,
                     zebra_route_string(api.type), api.instance,
                     inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])),
                     p.prefixlen,
@@ -735,7 +728,8 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length,
       if (bgp_debug_zebra((struct prefix *)&p))
        {
          char buf[2][INET6_ADDRSTRLEN];
-         zlog_debug("Zebra rcvd: IPv6 route add %s[%d] %s/%d nexthop %s metric %u tag %d",
+         zlog_debug("Rx IPv6 route add VRF %u %s[%d] %s/%d nexthop %s metric %u tag %d",
+                     vrf_id,
                     zebra_route_string(api.type), api.instance,
                     inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
                     p.prefixlen,
@@ -764,8 +758,9 @@ zebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length,
       if (bgp_debug_zebra((struct prefix *)&p))
        {
          char buf[2][INET6_ADDRSTRLEN];
-         zlog_debug("Zebra rcvd: IPv6 route delete %s[%d] %s/%d "
+         zlog_debug("Rx IPv6 route delete VRF %u %s[%d] %s/%d "
                     "nexthop %s metric %u tag %d",
+                     vrf_id,
                     zebra_route_string(api.type), api.instance,
                     inet_ntop(AF_INET6, &p.prefix, buf[0], sizeof(buf[0])),
                     p.prefixlen,
@@ -1170,7 +1165,10 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
   struct bgp_info *info_cp = &local_info;
   u_short tag;
 
-  if (zclient->sock < 0)
+  /* Don't try to install if we're not connected to Zebra or Zebra doesn't
+   * know of this instance.
+   */
+  if (!bgp_install_info_to_zebra (bgp))
     return;
 
   if ((p->family == AF_INET &&
@@ -1329,8 +1327,9 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
       if (bgp_debug_zebra(p))
         {
           int i;
-          zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u tag %d"
+          zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %d"
                      " count %d", (valid_nh_count ? "add":"delete"),
+                     bgp->vrf_id,
                      inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
                      p->prefixlen, api.metric, api.tag, api.nexthop_num);
           for (i = 0; i < api.nexthop_num; i++)
@@ -1508,8 +1507,8 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
           if (bgp_debug_zebra(p))
             {
               int i;
-              zlog_debug("Zebra send: IPv4 route %s %s/%d metric %u tag %d",
-                         valid_nh_count ? "add" : "delete",
+              zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %d",
+                         valid_nh_count ? "add" : "delete", bgp->vrf_id,
                          inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
                          p->prefixlen, api.metric, api.tag);
               for (i = 0; i < api.nexthop_num; i++)
@@ -1530,8 +1529,8 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
           if (bgp_debug_zebra(p))
             {
               int i;
-              zlog_debug("Zebra send: IPv6 route %s %s/%d metric %u tag %d",
-                         valid_nh_count ? "add" : "delete",
+              zlog_debug("Tx IPv6 route %s VRF %u %s/%d metric %u tag %d",
+                         valid_nh_count ? "add" : "delete", bgp->vrf_id,
                          inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
                          p->prefixlen, api.metric, api.tag);
               for (i = 0; i < api.nexthop_num; i++)
@@ -1555,6 +1554,12 @@ bgp_zebra_announce_table (struct bgp *bgp, afi_t afi, safi_t safi)
   struct bgp_table *table;
   struct bgp_info *ri;
 
+  /* Don't try to install if we're not connected to Zebra or Zebra doesn't
+   * know of this instance.
+   */
+  if (!bgp_install_info_to_zebra (bgp))
+    return;
+
   table = bgp->rib[afi][safi];
   if (!table) return;
 
@@ -1572,10 +1577,14 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
   int flags;
   struct peer *peer;
 
-  if (zclient->sock < 0)
-    return;
-
   peer = info->peer;
+  assert(peer);
+
+  /* Don't try to install if we're not connected to Zebra or Zebra doesn't
+   * know of this instance.
+   */
+  if (!bgp_install_info_to_zebra (peer->bgp))
+    return;
 
   if ((p->family == AF_INET &&
        !vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_BGP], peer->bgp->vrf_id))
@@ -1623,7 +1632,8 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
       if (bgp_debug_zebra(p))
        {
          char buf[2][INET_ADDRSTRLEN];
-         zlog_debug("Zebra send: IPv4 route delete %s/%d metric %u tag %d",
+         zlog_debug("Tx IPv4 route delete VRF %u %s/%d metric %u tag %d",
+                     peer->bgp->vrf_id,
                     inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
                     p->prefixlen, api.metric, api.tag);
        }
@@ -1661,7 +1671,8 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
       if (bgp_debug_zebra(p))
        {
          char buf[2][INET6_ADDRSTRLEN];
-         zlog_debug("Zebra send: IPv6 route delete %s/%d metric %u tag %d",
+         zlog_debug("Tx IPv6 route delete VRF %u %s/%d metric %u tag %d",
+                     peer->bgp->vrf_id,
                     inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
                     p->prefixlen, api.metric, api.tag);
        }
@@ -1750,12 +1761,15 @@ bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type, u_short instance)
       vrf_bitmap_set (zclient->redist[afi][type], bgp->vrf_id);
     }
 
-  /* Return if zebra connection is not established. */
-  if (zclient->sock < 0)
+  /* Don't try to register if we're not connected to Zebra or Zebra doesn't
+   * know of this instance.
+   */
+  if (!bgp_install_info_to_zebra (bgp))
     return CMD_WARNING;
 
   if (BGP_DEBUG (zebra, ZEBRA))
-    zlog_debug("Zebra send: redistribute add afi %d %s %d", afi,
+    zlog_debug("Tx redistribute add VRF %u afi %d %s %d",
+               bgp->vrf_id, afi,
                zebra_route_string(type), instance);
 
   /* Send distribute add message to zebra. */
@@ -1768,12 +1782,15 @@ bgp_redistribute_set (struct bgp *bgp, afi_t afi, int type, u_short instance)
 int
 bgp_redistribute_resend (struct bgp *bgp, afi_t afi, int type, u_short instance)
 {
-  /* Return if zebra connection is not established. */
-  if (zclient->sock < 0)
+  /* Don't try to send if we're not connected to Zebra or Zebra doesn't
+   * know of this instance.
+   */
+  if (!bgp_install_info_to_zebra (bgp))
     return -1;
 
   if (BGP_DEBUG (zebra, ZEBRA))
-    zlog_debug("Zebra send: redistribute delete/add afi %d %s %d", afi,
+    zlog_debug("Tx redistribute del/add VRF %u afi %d %s %d",
+               bgp->vrf_id, afi,
                zebra_route_string(type), instance);
 
   /* Send distribute add message to zebra. */
@@ -1854,12 +1871,12 @@ bgp_redistribute_unreg (struct bgp *bgp, afi_t afi, int type, u_short instance)
       vrf_bitmap_unset (zclient->redist[afi][type], bgp->vrf_id);
     }
 
-  if (zclient->sock >= 0)
+  if (bgp_install_info_to_zebra (bgp))
     {
       /* Send distribute delete message to zebra. */
       if (BGP_DEBUG (zebra, ZEBRA))
-       zlog_debug("Zebra send: redistribute delete afi %d %s %d",
-                  afi, zebra_route_string(type), instance);
+       zlog_debug("Tx redistribute del VRF %u afi %d %s %d",
+                  bgp->vrf_id, afi, zebra_route_string(type), instance);
       zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type, instance,
                                bgp->vrf_id);
     }
@@ -1903,14 +1920,60 @@ bgp_zclient_reset (void)
   zclient_reset (zclient);
 }
 
+/* Register this instance with Zebra. Invoked upon connect (for
+ * default instance) and when other VRFs are learnt (or created and
+ * already learnt).
+ */
+void
+bgp_zebra_instance_register (struct bgp *bgp)
+{
+  /* Don't try to register if we're not connected to Zebra */
+  if (zclient->sock < 0)
+    return;
+
+  if (BGP_DEBUG (zebra, ZEBRA))
+    zlog_debug("Registering VRF %u", bgp->vrf_id);
+
+  /* Register for router-id, interfaces, redistributed routes. */
+  zclient_send_reg_requests (zclient, bgp->vrf_id);
+}
+
+/* Deregister this instance with Zebra. Invoked upon the instance
+ * being deleted (default or VRF) and it is already registered.
+ */
+void
+bgp_zebra_instance_deregister (struct bgp *bgp)
+{
+  /* Don't try to deregister if we're not connected to Zebra */
+  if (zclient->sock < 0)
+    return;
+
+  if (BGP_DEBUG (zebra, ZEBRA))
+    zlog_debug("Deregistering VRF %u", bgp->vrf_id);
+
+  /* Deregister for router-id, interfaces, redistributed routes. */
+  zclient_send_dereg_requests (zclient, bgp->vrf_id);
+}
+
+/* BGP has established connection with Zebra. */
 static void
 bgp_zebra_connected (struct zclient *zclient)
 {
-  struct listnode *node, *nnode;
   struct bgp *bgp;
 
-  for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
-    bgp_vrf_update (bgp);
+  /* At this point, we may or may not have BGP instances configured, but
+   * we're only interested in the default VRF (others wouldn't have learnt
+   * the VRF from Zebra yet.)
+   */
+  bgp = bgp_get_default();
+  if (!bgp)
+    return;
+
+  bgp_zebra_instance_register (bgp);
+
+  /* TODO - What if we have peers and networks configured, do we have to
+   * kick-start them?
+   */
 }
 
 
index e21141238ca84ac5ea9a4408be713c145609f742..308834ce2bfbfa5281f01efa668bd69ed7f586e4 100644 (file)
@@ -29,7 +29,6 @@ extern struct stream *bgp_ifindices_buf;
 
 extern void bgp_zebra_init(struct thread_master *master);
 extern int bgp_if_update_all (void);
-extern void bgp_vrf_update (struct bgp *);
 extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,
                                      safi_t, int *);
 extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
@@ -39,6 +38,9 @@ extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *
 extern void bgp_zebra_announce_table (struct bgp *, afi_t, safi_t);
 extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t);
 
+extern void bgp_zebra_instance_register (struct bgp *);
+extern void bgp_zebra_instance_deregister (struct bgp *);
+
 extern struct bgp_redist *bgp_redist_lookup (struct bgp *, afi_t, u_char, u_short);
 extern struct bgp_redist *bgp_redist_add (struct bgp *, afi_t, u_char, u_short);
 extern int bgp_redistribute_set (struct bgp *, afi_t, int, u_short);
index 09a9f9dc93ab9dfc65f3485018196d3a381b830d..ef2004295e3cafe0c4c4db799aae93a243793559 100644 (file)
@@ -80,6 +80,7 @@ struct bgp_master *bm;
 /* BGP community-list.  */
 struct community_list_handler *bgp_clist;
 
+extern struct zclient *zclient;
 
 void
 bgp_session_reset(struct peer *peer)
@@ -2698,10 +2699,9 @@ bgp_startup_timer_expire (struct thread *thread)
   return 0;
 }
 
-
 /* BGP instance creation by `router bgp' commands. */
 static struct bgp *
-bgp_create (as_t *as, const char *name)
+bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type)
 {
   struct bgp *bgp;
   afi_t afi;
@@ -2710,7 +2710,19 @@ bgp_create (as_t *as, const char *name)
   if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
     return NULL;
   
+  if (BGP_DEBUG (zebra, ZEBRA))
+    {
+      if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+        zlog_debug("Creating Default VRF, AS %u", *as);
+      else
+        zlog_debug("Creating %s %s, AS %u",
+                   (inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW",
+                   name, *as);
+    }
+
   bgp_lock (bgp);
+  bgp->inst_type = inst_type;
+  bgp->vrf_id = VRF_DEFAULT; /* initialization. */
   bgp->peer_self = peer_new (bgp);
   if (bgp->peer_self->host)
     XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
@@ -2757,7 +2769,7 @@ bgp_create (as_t *as, const char *name)
     }
   else
     {
-      //Pending: See if calling bgp_instance_up() makes more sense.
+      /* TODO - The startup timer needs to be run for the whole of BGP */
       THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
                        bgp, bgp->restart_time);
     }
@@ -2769,38 +2781,16 @@ bgp_create (as_t *as, const char *name)
   return bgp;
 }
 
-void
-bgp_instance_up (struct bgp *bgp)
-{
-  struct peer *peer;
-  struct listnode *node, *next;
-  afi_t afi;
-  int i;
-
-  THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
-                   bgp, bgp->restart_time);
-
-  /* Delete static route. */
-  bgp_static_add (bgp);
-
-  /* Set redistribution. */
-  for (afi = AFI_IP; afi < AFI_MAX; afi++)
-    for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 
-      if (i != ZEBRA_ROUTE_BGP && bgp_redist_lookup(bgp, afi, i, 0))
-       bgp_redistribute_set (bgp, afi, i, 0);
-
-  for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
-    {
-      BGP_EVENT_ADD (peer, BGP_Start);
-    }
-}
-
-/* Return first entry of BGP. */
+/* Return the "default VRF" instance of BGP. */
 struct bgp *
 bgp_get_default (void)
 {
-  if (bm->bgp->head)
-    return (listgetdata (listhead (bm->bgp)));
+  struct bgp *bgp;
+  struct listnode *node, *nnode;
+
+  for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
+    if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+      return bgp;
   return NULL;
 }
 
@@ -2833,8 +2823,7 @@ bgp_lookup_by_name (const char *name)
   return NULL;
 }
 
-/* Lookup BGP structure by view name. */
-//Pending: move this based on the vrf_hash lookup and find the linked bgp instance.
+/* Lookup BGP instance based on VRF id */
 struct bgp *
 bgp_lookup_by_vrf_id (vrf_id_t vrf_id)
 {
@@ -2847,9 +2836,34 @@ bgp_lookup_by_vrf_id (vrf_id_t vrf_id)
   return NULL;
 }
 
+/* Link BGP instance to VRF, if present. */
+static void
+bgp_vrf_link (struct bgp *bgp)
+{
+  struct vrf *vrf;
+
+  vrf = vrf_lookup_by_name(bgp->name);
+  if (!vrf)
+    return;
+  bgp->vrf_id = vrf->vrf_id;
+}
+
+/* Unlink BGP instance from VRF, if present. */
+static void
+bgp_vrf_unlink (struct bgp *bgp)
+{
+  struct vrf *vrf;
+
+  vrf = vrf_lookup (bgp->vrf_id);
+  if (!vrf)
+    return;
+  bgp->vrf_id = VRF_DEFAULT;
+}
+
 /* Called from VTY commands. */
 int
-bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
+bgp_get (struct bgp **bgp_val, as_t *as, const char *name,
+         enum bgp_instance_type inst_type)
 {
   struct bgp *bgp;
 
@@ -2869,6 +2883,8 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
              *as = bgp->as;
              return BGP_ERR_INSTANCE_MISMATCH;
            }
+          if (bgp->inst_type != inst_type)
+            return BGP_ERR_INSTANCE_MISMATCH;
          *bgp_val = bgp;
          return 0;
        }
@@ -2894,7 +2910,7 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
        }
     }
 
-  bgp = bgp_create (as, name);
+  bgp = bgp_create (as, name, inst_type);
   bgp_router_id_set(bgp, &bgp->router_id_zebra);
   bgp_address_init (bgp);
   bgp_scan_init (bgp);
@@ -2914,74 +2930,73 @@ bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
 
   listnode_add (bm->bgp, bgp);
 
-  bgp_vrf_update (bgp);
+  /* If VRF, link to the VRF structure, if present. */
+  if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
+    bgp_vrf_link (bgp);
+
+  /* Register with Zebra, if needed */
+  if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
+    bgp_zebra_instance_register (bgp);
+
 
   return 0;
 }
 
-/* Delete BGP instance. */
+/*
+ * Make BGP instance "up". Applies only to VRFs (non-default) and
+ * implies the VRF has been learnt from Zebra.
+ */
 void
-bgp_instance_down (struct bgp *bgp)
+bgp_instance_up (struct bgp *bgp)
 {
   struct peer *peer;
-  struct peer_group *group;
-  struct listnode *node, *pnode;
-  struct listnode *next, *pnext;
-  afi_t afi;
-  int i;
+  struct listnode *node, *next;
 
-  THREAD_OFF (bgp->t_startup);
+  /* Register with zebra. */
+  bgp_zebra_instance_register (bgp);
 
+  /* Kick off any peers that may have been configured. */
   for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
     {
-      if (peer->status == Established ||
-          peer->status == OpenSent ||
-          peer->status == OpenConfirm)
-        {
-            bgp_notify_send (peer, BGP_NOTIFY_CEASE,
-                             BGP_NOTIFY_CEASE_PEER_UNCONFIG);
-        }
+      if (!BGP_PEER_START_SUPPRESSED (peer))
+        BGP_EVENT_ADD (peer, BGP_Start);
     }
 
-  if (bgp->t_rmap_update)
-    BGP_TIMER_OFF(bgp->t_rmap_update);
-
-  /* Delete static route. */
-  bgp_static_delete (bgp);
+  /* Process any networks that have been configured. */
+  bgp_static_add (bgp);
+}
 
-  /* Unset redistribution. */
-  for (afi = AFI_IP; afi < AFI_MAX; afi++)
-    for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 
-      if (i != ZEBRA_ROUTE_BGP)
-       bgp_redistribute_unreg (bgp, afi, i, 0);
+/*
+ * Make BGP instance "down". Applies only to VRFs (non-default) and
+ * implies the VRF has been deleted by Zebra.
+ */
+void
+bgp_instance_down (struct bgp *bgp)
+{
+  struct peer *peer;
+  struct listnode *node;
+  struct listnode *next;
 
-  for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
+  /* Stop timers. */
+  if (bgp->t_rmap_update)
+    BGP_TIMER_OFF(bgp->t_rmap_update);
+  if (bgp->t_rmap_def_originate_eval)
     {
-      for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
-       {
-         if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
-           {
-             /* Send notify to remote peer. */
-             bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
-           }
-       }
+      BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
+      bgp_unlock(bgp);  /* TODO - This timer is started with a lock - why? */
     }
 
+  /* Bring down peers, so corresponding routes are purged. */
   for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
     {
       if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
-       {
-         /* Send notify to remote peer. */
-         bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
-       }
-    }
-
-  if (bgp->t_rmap_def_originate_eval)
-    {
-      BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
+        bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
+      else
+        bgp_session_reset(peer);
     }
 
-  return;
+  /* Purge network and redistributed routes. */
+  bgp_purge_static_redist_routes (bgp);
 }
 
 /* Delete BGP instance. */
@@ -2996,10 +3011,33 @@ bgp_delete (struct bgp *bgp)
 
   THREAD_OFF (bgp->t_startup);
 
+  if (BGP_DEBUG (zebra, ZEBRA))
+    {
+      if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+        zlog_debug("Deleting Default VRF");
+      else
+        zlog_debug("Deleting %s %s",
+                   (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW",
+                   bgp->name);
+    }
+
+  /* Stop timers. */
   if (bgp->t_rmap_update)
     BGP_TIMER_OFF(bgp->t_rmap_update);
+  if (bgp->t_rmap_def_originate_eval)
+    {
+      BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
+      bgp_unlock(bgp);  /* TODO - This timer is started with a lock - why? */
+    }
+
+  /* Inform peers we're going down. */
+  for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
+    {
+      if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+        bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
+    }
 
-  /* Delete static route. */
+  /* Delete static routes (networks). */
   bgp_static_delete (bgp);
 
   /* Unset redistribution. */
@@ -3008,28 +3046,22 @@ bgp_delete (struct bgp *bgp)
       if (i != ZEBRA_ROUTE_BGP)
        bgp_redistribute_unset (bgp, afi, i, 0);
 
+  /* Free peers and peer-groups. */
   for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
-    {
-      peer_group_delete (group);
-    }
+    peer_group_delete (group);
 
   for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
-    {
-      peer_delete (peer);
-    }
+    peer_delete (peer);
 
   if (bgp->peer_self) {
     peer_delete(bgp->peer_self);
     bgp->peer_self = NULL;
   }
 
-  if (bgp->t_rmap_def_originate_eval)
-    {
-      BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
-      bgp_unlock(bgp);
-    }
-
   update_bgp_group_free (bgp);
+
+  /* TODO - Other memory may need to be freed - e.g., NHT */
+
   /* Remove visibility via the master list - there may however still be
    * routes to be processed still referencing the struct bgp.
    */
@@ -3037,6 +3069,14 @@ bgp_delete (struct bgp *bgp)
   if (list_isempty(bm->bgp))
     bgp_close ();
 
+  /* Deregister from Zebra, if needed */
+  if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
+    bgp_zebra_instance_deregister (bgp);
+
+  /* If VRF, unlink from the VRF structure. */
+  if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
+    bgp_vrf_unlink (bgp);
+
   thread_master_free_unused(bm->master);
   bgp_unlock(bgp);  /* initial reference */
 
@@ -3174,10 +3214,10 @@ peer_lookup (struct bgp *bgp, union sockunion *su)
   
       for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
         {
-          /*
-           * Don't have to cross the instance boundaries for VRFs.
+          /* Skip VRFs, this function will not be invoked without an instance
+           * when examining VRFs.
            */
-          if (bgp_flag_check(bgp, BGP_FLAG_INSTANCE_TYPE_VRF))
+          if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
             continue;
 
           peer = hash_lookup(bgp->peerhash, &tmp_peer);
@@ -6904,8 +6944,9 @@ bgp_config_write (struct vty *vty)
       if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
        {
          if (bgp->name)
-           vty_out (vty, " %s %s", (bgp_flag_check(bgp, BGP_FLAG_INSTANCE_TYPE_VIEW) ? 
-                                     "view" : "vrf"), bgp->name);
+           vty_out (vty, " %s %s",
+                     (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) ?
+                     "view" : "vrf", bgp->name);
        }
       vty_out (vty, "%s", VTY_NEWLINE);
 
@@ -7130,6 +7171,36 @@ bgp_master_init (void)
   bgp_process_queue_init();
 }
 
+/*
+ * Free up connected routes and interfaces; invoked upon bgp_exit()
+ */
+void
+bgp_if_finish (void)
+{
+  struct bgp *bgp;
+  struct listnode *node, *nnode;
+
+  for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
+    {
+      struct listnode *ifnode;
+      struct interface *ifp;
+  
+      if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
+        continue;
+
+      for (ALL_LIST_ELEMENTS_RO (vrf_iflist(bgp->vrf_id), ifnode, ifp))
+        {
+          struct listnode *c_node, *c_nnode;
+          struct connected *c;
+
+          for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
+            bgp_connected_delete (bgp, c);
+           
+          if_delete (ifp);
+        }
+      list_free (vrf_iflist(bgp->vrf_id));
+    }
+}
 
 void
 bgp_init (void)
index 9414da4d0999088b0da82956fc3b21c453a459e4..ce318b33848c186233258540337d6c2dc786bf6e 100644 (file)
@@ -129,6 +129,21 @@ struct bgp_redist
   struct bgp_rmap rmap;
 };
 
+/*
+ * Type of 'struct bgp'.
+ * - Default: The default instance
+ * - VRF: A specific (non-default) VRF
+ * - View: An instance used for route exchange
+ * The "default" instance is treated separately to simplify the code. Note
+ * that if deployed in a Multi-VRF environment, it may not exist.
+ */
+enum bgp_instance_type
+{
+  BGP_INSTANCE_TYPE_DEFAULT,
+  BGP_INSTANCE_TYPE_VRF,
+  BGP_INSTANCE_TYPE_VIEW
+};
+
 /* BGP instance structure.  */
 struct bgp 
 {
@@ -138,6 +153,8 @@ struct bgp
   /* Name of this BGP instance.  */
   char *name;
 
+  /* Type of instance and VRF id. */
+  enum bgp_instance_type inst_type;
   vrf_id_t vrf_id;
   
   /* Reference count to allow peer_delete to finish after bgp_delete */
@@ -256,8 +273,6 @@ struct bgp
 #define BGP_FLAG_MULTIPATH_RELAX_AS_SET   (1 << 17)
 #define BGP_FLAG_FORCE_STATIC_PROCESS     (1 << 18)
 #define BGP_FLAG_SHOW_HOSTNAME            (1 << 19)
-#define BGP_FLAG_INSTANCE_TYPE_VIEW       (1 << 20)
-#define BGP_FLAG_INSTANCE_TYPE_VRF        (1 << 21)
 
   /* BGP Per AF flags */
   u_int16_t af_flags[AFI_MAX][SAFI_MAX];
@@ -333,6 +348,10 @@ struct bgp
 
 #define BGP_ROUTE_ADV_HOLD(bgp) (bgp->main_peers_update_hold)
 
+#define IS_BGP_INST_KNOWN_TO_ZEBRA(bgp) \
+        (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT || \
+         (bgp->inst_type == BGP_INSTANCE_TYPE_VRF && bgp->vrf_id != VRF_DEFAULT))
+
 /* BGP peer-group support. */
 struct peer_group
 {
@@ -837,6 +856,11 @@ u_char last_reset_cause[BGP_MAX_PACKET_SIZE];
   char *domainname;
 };
 
+/* Check if suppress start/restart of sessions to peer. */
+#define BGP_PEER_START_SUPPRESSED(P) \
+  (CHECK_FLAG ((P)->flags, PEER_FLAG_SHUTDOWN) \
+   || CHECK_FLAG ((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW))
+
 #define PEER_PASSWORD_MINLEN   (1)
 #define PEER_PASSWORD_MAXLEN   (80)
 
@@ -1150,6 +1174,7 @@ extern char *peer_uptime (time_t, char *, size_t, u_char, json_object *);
 extern int bgp_config_write (struct vty *);
 extern void bgp_config_write_family_header (struct vty *, afi_t, safi_t, int *);
 
+extern void bgp_if_finish (void);
 extern void bgp_master_init (void);
 
 extern void bgp_init (void);
@@ -1160,7 +1185,7 @@ extern int bgp_option_set (int);
 extern int bgp_option_unset (int);
 extern int bgp_option_check (int);
 
-extern int bgp_get (struct bgp **, as_t *, const char *);
+extern int bgp_get (struct bgp **, as_t *, const char *, enum bgp_instance_type);
 extern void bgp_instance_up (struct bgp *);
 extern void bgp_instance_down (struct bgp *);
 extern int bgp_delete (struct bgp *);