Mailing List Archive

[PATCH v2 02/10] bgpd: BGP VRF processing handling
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.guibert@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 99637b6dba51..1a0ea222322e 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