[frr] [PATCH 04/11] bgpd: VRF RIB log updates enhancement

Philippe Guibert philippe.guibert at 6wind.com
Wed Dec 21 09:13:49 EST 2016


On adding/removing/updating NLRI entries into VRF RIB tables, a BGP
event is fired. Note that only selected entries, and entries that are
part of multipath entries, and where one of the multipath entry is
selected.

Signed-off-by: Philippe Guibert <philippe.guibert at 6wind.com>
---
 bgpd/bgp_route.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++--
 bgpd/bgp_route.h |  2 ++
 bgpd/bgp_vrf.c   | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bgpd/bgp_vrf.h   |  4 ++++
 4 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 81d33df024fa..f9454d371ff1 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2033,9 +2033,13 @@ bgp_process_vrf_main (struct work_queue *wq, void *data)
   struct bgp *bgp = pq->bgp;
   afi_t afi = pq->afi;
   safi_t safi = pq->safi;
-  struct bgp_info *new_select;
+  struct bgp_info *new_select, *ri;
   struct bgp_info *old_select;
   struct bgp_info_pair old_and_new;
+  struct bgp_vrf *vrf = NULL;
+
+  if(rn)
+    vrf = bgp_vrf_lookup_per_rn(bgp, afi, rn);
 
   /* Best path selection. */
   bgp_best_selection (bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new);
@@ -2052,6 +2056,13 @@ bgp_process_vrf_main (struct work_queue *wq, void *data)
             {
               UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
               SET_FLAG (old_select->flags, BGP_INFO_MULTIPATH);
+              for(ri = rn->info; ri; ri = ri->next)
+                {
+                  if(ri == old_select)
+                    continue;
+                  if(!bgp_is_mpath_entry(ri, new_select))
+                    bgp_vrf_update(vrf, afi, rn, ri, false);
+                }
             }
           /* no zebra announce */
 	  UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
@@ -2073,18 +2084,53 @@ bgp_process_vrf_main (struct work_queue *wq, void *data)
     {
       if( CHECK_FLAG (old_select->flags, BGP_INFO_SELECTED))
         {
-          if(bgp_is_mpath_entry(old_select, new_select))
+          if(!bgp_is_mpath_entry(old_select, new_select))
+            {
+              bgp_vrf_update(vrf, afi, rn, old_select, false);
+            }
+          else
             {
               UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
               SET_FLAG (old_select->flags, BGP_INFO_MULTIPATH);
             }
         }
+      /* withdraw mp entries which could have been removed
+       * and that a update has previously been sent
+       */
+      for(ri = rn->info; ri; ri = ri->next)
+        {
+          if(ri == old_select || (ri == new_select) )
+            continue;
+          if(!bgp_is_mpath_entry(ri, new_select))
+            {
+              bgp_vrf_update(vrf, afi, rn, ri, false);
+            }
+        }
+      bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
     }
   if (new_select)
     {
+      if(!CHECK_FLAG (new_select->flags, BGP_INFO_SELECTED) ||
+         CHECK_FLAG (new_select->flags, BGP_INFO_MULTIPATH) ||
+         CHECK_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG))
+        {
+          bgp_vrf_update(vrf, afi, rn, new_select, true);
+        }
       bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
       bgp_info_unset_flag (rn, new_select, BGP_INFO_ATTR_CHANGED);
       UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
+      /* append mp entries which could have been added 
+       * and that a update has not been sent
+       */
+      for(ri = rn->info; ri; ri = ri->next)
+        {
+          if( (ri == new_select) || ( ri == old_select))
+            continue;
+          if(bgp_is_mpath_entry(ri, new_select))
+            {
+              bgp_vrf_update(vrf, afi, rn, ri, true);
+            }
+        }
     }
 
   /* Reap old select bgp_info, if it has been removed */
@@ -2321,6 +2367,7 @@ bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
   bgp_process (peer->bgp, rn, afi, safi);
 }
 
+
 static void
 bgp_rib_withdraw (struct bgp_node *rn, struct bgp_info *ri, struct peer *peer,
 		  afi_t afi, safi_t safi, struct prefix_rd *prd)
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 1bbd9cc99745..57ab7e8ec8d0 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -147,6 +147,8 @@ struct bgp_info
 #define BGP_INFO_COUNTED	(1 << 10)
 #define BGP_INFO_MULTIPATH      (1 << 11)
 #define BGP_INFO_MULTIPATH_CHG  (1 << 12)
+#define BGP_INFO_UPDATE_SENT    (1 << 13)
+#define BGP_INFO_WITHDRAW_SENT  (1 << 14)
 
   /* BGP route type.  This can be static, RIP, OSPF, BGP etc.  */
   u_char type;
diff --git a/bgpd/bgp_vrf.c b/bgpd/bgp_vrf.c
index d1883a5c95bd..dbd9bc9d32f4 100644
--- a/bgpd/bgp_vrf.c
+++ b/bgpd/bgp_vrf.c
@@ -369,6 +369,60 @@ static bool rd_same (const struct prefix_rd *a, const struct prefix_rd *b)
   return !memcmp(&a->val, &b->val, sizeof(a->val));
 }
 
+/* messages sent to ODL to signify that an entry
+ * has been selected, or unselected
+ */
+void
+bgp_vrf_update (struct bgp_vrf *vrf, afi_t afi, struct bgp_node *rn,
+                struct bgp_info *selected, uint8_t announce)
+{
+  if(!vrf || (rn && bgp_node_table (rn)->type != BGP_TABLE_VRF))
+    return;
+  if (announce == true)
+    {
+      if(CHECK_FLAG (selected->flags, BGP_INFO_UPDATE_SENT))
+        return;
+      SET_FLAG (selected->flags, BGP_INFO_UPDATE_SENT);
+      UNSET_FLAG (selected->flags, BGP_INFO_WITHDRAW_SENT);
+    }
+  else
+    {
+      /* if not already sent, do nothing */
+      if(!CHECK_FLAG (selected->flags, BGP_INFO_UPDATE_SENT))
+        return;
+      if(CHECK_FLAG (selected->flags, BGP_INFO_WITHDRAW_SENT))
+        return;
+      SET_FLAG (selected->flags, BGP_INFO_WITHDRAW_SENT);
+      UNSET_FLAG (selected->flags, BGP_INFO_UPDATE_SENT);
+    }
+  if (BGP_DEBUG (bgp_vrf, BGPVRF))
+    {
+      char vrf_rd_str[RD_ADDRSTRLEN], rd_str[RD_ADDRSTRLEN], pfx_str[INET6_BUFSIZ];
+      char nh_str[BUFSIZ] = "<?>";
+      uint32_t label;
+
+      prefix_rd2str(&vrf->outbound_rd, vrf_rd_str, sizeof(vrf_rd_str));
+      prefix_rd2str(&selected->extra->vrf_rd, rd_str, sizeof(rd_str));
+      prefix2str(&rn->p, pfx_str, sizeof(pfx_str));
+      label = decode_label (selected->extra->tag);
+
+      if (selected->attr && selected->attr->extra)
+        {
+          if (afi == AFI_IP)
+            strcpy (nh_str, inet_ntoa (selected->attr->extra->mp_nexthop_global_in));
+          else if (afi == AFI_IP6)
+            inet_ntop (AF_INET6, &selected->attr->extra->mp_nexthop_global, nh_str, BUFSIZ);
+        }
+
+      if (announce)
+        zlog_info ("vrf[%s] %s: prefix updated, best RD %s label %u nexthop %s",
+                   vrf_rd_str, pfx_str, rd_str, label, nh_str);
+      else
+        zlog_info ("vrf[%s] %s: prefix withdrawn nh %s label %u",
+                    vrf_rd_str, pfx_str, nh_str, label);
+    }
+}
+
 /* VRF import processing */
 /* updates selected bgp_info structure to bgp vrf rib table
  * most of the cases, processing consists in adding or removing entries in RIB tables
diff --git a/bgpd/bgp_vrf.h b/bgpd/bgp_vrf.h
index 40f885b46a00..3cae3e1cbc3e 100644
--- a/bgpd/bgp_vrf.h
+++ b/bgpd/bgp_vrf.h
@@ -101,5 +101,9 @@ bgp_vrf_process_imports (struct bgp *bgp, afi_t afi, safi_t safi,
                          struct bgp_info *old_select,
                          struct bgp_info *new_select);
 
+extern void
+bgp_vrf_update (struct bgp_vrf *vrf, afi_t afi, struct bgp_node *rn,
+                struct bgp_info *selected, uint8_t announce);
+
 #endif /* _QUAGGA_BGP_VRF */
 
-- 
2.1.4





More information about the dev mailing list