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 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