NLRI entries received from MP-BGP peer exchange are exported in VRF RIB
tables. This commit introduces the BGP VRF processing handler that can
be used for further processing into VRF RIB tables: best selection
algorithm, multipath.

Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com>
---
 bgpd/bgp_main.c  |  5 ++++
 bgpd/bgp_route.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++-------
 bgpd/bgp_route.h |  3 ++
 bgpd/bgpd.c      |  5 ++++
 bgpd/bgpd.h      |  1 +
 5 files changed, 95 insertions(+), 10 deletions(-)

diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index af9c03052020..51a2770a5ead 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -258,6 +258,11 @@ bgp_exit (int status)
       work_queue_free (bm->process_rsclient_queue);
       bm->process_rsclient_queue = NULL;
     }
+  if (bm->process_vrf_queue)
+    {
+     work_queue_free (bm->process_vrf_queue);
+     bm->process_vrf_queue = NULL;
+    }
   
   /* reverse bgp_master_init */
   for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 3aa421ea400a..615cd375bb78 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1338,7 +1338,6 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
   
   bgp_mp_list_init (&mp_list);
   do_mpath = bgp_mpath_is_configured (bgp, afi, safi);
-
   /* bgp deterministic-med */
   new_select = NULL;
   if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
@@ -1707,7 +1706,7 @@ bgp_process_main (struct work_queue *wq, void *data)
   UNSET_FLAG(rn->flags, BGP_NODE_USER_CLEAR);
 
   if (old_select)
-    bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
+      bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
   if (new_select)
     {
       bgp_info_set_flag (rn, new_select, BGP_INFO_SELECTED);
@@ -1715,7 +1714,6 @@ bgp_process_main (struct work_queue *wq, void *data)
       UNSET_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG);
     }
 
-
   /* Check each BGP peer. */
   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     {
@@ -1748,6 +1746,65 @@ bgp_process_main (struct work_queue *wq, void *data)
   return WQ_SUCCESS;
 }
 
+/* processing done for BGP VRF tables */
+static wq_item_status
+bgp_process_vrf_main (struct work_queue *wq, void *data)
+{
+  struct bgp_process_queue *pq = data;
+  struct bgp *bgp = pq->bgp;
+  struct bgp_node *rn = pq->rn;
+  afi_t afi = pq->afi;
+  safi_t safi = pq->safi;
+  struct bgp_info *new_select;
+  struct bgp_info *old_select;
+  struct bgp_info_pair old_and_new;
+
+  /* Best path selection. */
+  bgp_best_selection (bgp, rn, &old_and_new, afi, safi);
+  old_select = old_and_new.old;
+  new_select = old_and_new.new;
+
+  /* Nothing to do. */
+  if (old_select && old_select == new_select)
+    {
+      if (! CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED))
+        {
+          /* no zebra announce */
+         UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
+          UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
+          return WQ_SUCCESS;
+        }
+    }
+  if (old_select && new_select)
+    {
+      if(!CHECK_FLAG (new_select->flags, BGP_INFO_MULTIPATH_CHG) &&
+         !CHECK_FLAG (new_select->flags, BGP_INFO_ATTR_CHANGED))
+        {
+          UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
+          return WQ_SUCCESS;
+        }
+    }
+
+  if (old_select)
+    {
+      bgp_info_unset_flag (rn, old_select, BGP_INFO_SELECTED);
+    }
+  if (new_select)
+    {
+      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);
+    }
+
+  /* Reap old select bgp_info, if it has been removed */
+  if (old_select && CHECK_FLAG (old_select->flags, BGP_INFO_REMOVED))
+    bgp_info_reap (rn, old_select);
+
+  UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
+  return WQ_SUCCESS;
+  /* no announce */
+}
+
 static void
 bgp_processq_del (struct work_queue *wq, void *data)
 {
@@ -1767,8 +1824,10 @@ bgp_process_queue_init (void)
     = work_queue_new (bm->master, "process_main_queue");
   bm->process_rsclient_queue
     = work_queue_new (bm->master, "process_rsclient_queue");
+  bm->process_vrf_queue
+    = work_queue_new (bm->master, "process_vrf_queue");
   
-  if ( !(bm->process_main_queue && bm->process_rsclient_queue) )
+  if ( !(bm->process_main_queue && bm->process_rsclient_queue && 
bm->process_vrf_queue) )
     {
       zlog_err ("%s: Failed to allocate work queue", __func__);
       exit (1);
@@ -1783,6 +1842,12 @@ bgp_process_queue_init (void)
   bm->process_rsclient_queue->spec.del_item_data = &bgp_processq_del;
   bm->process_rsclient_queue->spec.max_retries = 0;
   bm->process_rsclient_queue->spec.hold = 50;
+
+  bm->process_vrf_queue->spec.workfunc = &bgp_process_vrf_main;
+  bm->process_vrf_queue->spec.del_item_data = &bgp_processq_del;
+  bm->process_vrf_queue->spec.max_retries = 0;
+  bm->process_vrf_queue->spec.hold = 50;
+
 }
 
 void
@@ -1792,7 +1857,9 @@ bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t 
afi, safi_t safi)
   
   /* already scheduled for processing? */
   if (CHECK_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED))
-    return;
+    {
+      return;
+    }
   
   if (rn->info == NULL)
     {
@@ -1808,7 +1875,8 @@ bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t 
afi, safi_t safi)
     }
   
   if ( (bm->process_main_queue == NULL) ||
-       (bm->process_rsclient_queue == NULL) )
+       (bm->process_rsclient_queue == NULL) ||
+       (bm->process_vrf_queue == NULL) )
     bgp_process_queue_init ();
   
   pqnode = XCALLOC (MTYPE_BGP_PROCESS_QUEUE, 
@@ -1833,8 +1901,8 @@ bgp_process (struct bgp *bgp, struct bgp_node *rn, afi_t 
afi, safi_t safi)
         work_queue_add (bm->process_rsclient_queue, pqnode);
         break;
       case BGP_TABLE_VRF:
-        /* never called */
-        assert (0);
+        work_queue_add (bm->process_vrf_queue, pqnode);
+        break;
     }
   
   SET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
@@ -1945,7 +2013,7 @@ bgp_rib_remove (struct bgp_node *rn, struct bgp_info *ri, 
struct peer *peer,
   
   if (!CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
     bgp_info_delete (rn, ri); /* keep historical info */
-    
+
   bgp_process (peer->bgp, rn, afi, safi);
 }
 
@@ -2435,7 +2503,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, 
struct attr *attr,
          if (! CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
            bgp_damp_withdraw (ri, rn, afi, safi, 1);  
        }
-       
+
       /* Update to new attribute.  */
       bgp_attr_unintern (&ri->attr);
       ri->attr = attr_new;
@@ -2495,6 +2563,8 @@ bgp_update_main (struct peer *peer, struct prefix *p, 
struct attr *attr,
       bgp_aggregate_increment (bgp, p, ri, afi, safi);
 
       bgp_process (bgp, rn, afi, safi);
+
+      /* non null value for old_select to inform update */
       bgp_unlock_node (rn);
 
       return 0;
@@ -3255,6 +3325,7 @@ bgp_process_queues_drain_immediate(void)
 {
   bgp_drain_workqueue_immediate(bm->process_main_queue);
   bgp_drain_workqueue_immediate(bm->process_rsclient_queue);
+  bgp_drain_workqueue_immediate(bm->process_vrf_queue);
 }
 
 void
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 281785c54f18..80257fdbb41e 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -280,5 +280,8 @@ extern void bgp_peer_clear_node_queue_drain_immediate 
(struct peer *peer);
 extern void bgp_process_queues_drain_immediate (void);
 
 extern void bgp_vrf_apply_new_imports (struct bgp_vrf *vrf, afi_t afi);
+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_ROUTE_H */
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 5725730d9454..44a216e9844f 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -5937,4 +5937,9 @@ bgp_terminate (void)
       work_queue_free (bm->process_rsclient_queue);
       bm->process_rsclient_queue = NULL;
     }
+  if (bm->process_vrf_queue)
+    {
+      work_queue_free (bm->process_vrf_queue);
+      bm->process_vrf_queue = NULL;
+    }
 }
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 39fbbe5de525..85e2647b7e16 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -52,6 +52,7 @@ struct bgp_master
   /* work queues */
   struct work_queue *process_main_queue;
   struct work_queue *process_rsclient_queue;
+  struct work_queue *process_vrf_queue;
   
   /* Listening sockets */
   struct list *listen_sockets;
-- 
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to