Mailing List Archive

[PATCH v2 05/10] bgpd: VRF RIB log updates enhancement
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@6wind.com>
---
bgpd/bgp_route.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
bgpd/bgp_route.h | 2 ++
bgpd/bgpd.c | 16 +++++++++
bgpd/bgpd.h | 3 ++
4 files changed, 124 insertions(+), 2 deletions(-)

diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 5744a3a2c27e..5eb195467c98 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1572,6 +1572,60 @@ void bgp_vrf_clean_tables (struct bgp_vrf *vrf)
}
}

+/* 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 (events, EVENTS))
+ {
+ char vrf_rd_str[RD_ADDRSTRLEN], rd_str[RD_ADDRSTRLEN], pfx_str[INET6_BUFSIZ];
+ char label_str[BUFSIZ] = "<?>", nh_str[BUFSIZ] = "<?>";
+
+ 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));
+ labels2str(label_str, sizeof(label_str),
+ selected->extra->labels, selected->extra->nlabels);
+
+ 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_debug ("vrf[%s] %s: prefix updated, best RD %s labels %s nexthop %s",
+ vrf_rd_str, pfx_str, rd_str, label_str, nh_str);
+ else
+ zlog_debug ("vrf[%s] %s: prefix withdrawn nh %s label %s",
+ vrf_rd_str, pfx_str, nh_str, label_str);
+ }
+}
+
/* updates selected bgp_info structure to bgp vrf rib table
* most of the cases, processing consists in adding or removing entries in RIB tables
* on some cases, there is an update request. then it is necessary to have both old and new ri
@@ -2098,9 +2152,13 @@ bgp_process_vrf_main (struct work_queue *wq, void *data)
struct bgp_node *rn = pq->rn;
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, &old_and_new, afi, safi);
@@ -2117,6 +2175,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);
@@ -2138,18 +2203,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 */
@@ -2374,6 +2474,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 80257fdbb41e..1357dee2eabb 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -99,6 +99,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/bgpd.c b/bgpd/bgpd.c
index 44a216e9844f..a0fe4de390fb 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -2091,6 +2091,22 @@ bgp_rt_hash_dealloc (struct bgp_rt_sub *rt_sub)
}

struct bgp_vrf *
+bgp_vrf_lookup_per_rn (struct bgp *bgp, int afi, struct bgp_node *vrf_rn)
+{
+ struct listnode *node;
+ struct bgp_vrf *vrf;
+
+ if(bgp_node_table (vrf_rn)->type != BGP_TABLE_VRF)
+ return NULL;
+ for (ALL_LIST_ELEMENTS_RO(bgp->vrfs, node, vrf))
+ if(vrf->rib[afi] == bgp_node_table (vrf_rn))
+ {
+ return vrf;
+ }
+ return NULL;
+}
+
+struct bgp_vrf *
bgp_vrf_lookup (struct bgp *bgp, struct prefix_rd *outbound_rd)
{
struct listnode *node;
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 85e2647b7e16..acf59c5aaf04 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -32,6 +32,8 @@ typedef u_int32_t as_t;
typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */
typedef u_int16_t bgp_size_t;

+struct bgp_node;
+
/* BGP router distinguisher value. */
#define BGP_RD_SIZE 8

@@ -1037,6 +1039,7 @@ extern int peer_ttl_security_hops_unset (struct peer *);
extern void bgp_scan_finish (void);
extern struct bgp_vrf *bgp_vrf_create (struct bgp *bgp, struct prefix_rd *outbound_rd);
extern struct bgp_vrf *bgp_vrf_lookup (struct bgp *bgp, struct prefix_rd *outbound_rd);
+extern struct bgp_vrf *bgp_vrf_lookup_per_rn (struct bgp *bgp, int afi, struct bgp_node *vrf_rn);
extern void bgp_vrf_delete (struct bgp_vrf *vrf);
extern void bgp_vrf_rt_export_set (struct bgp_vrf *vrf, struct ecommunity *rt_export);
extern void bgp_vrf_rt_import_set (struct bgp_vrf *vrf, struct ecommunity *rt_import);
--
2.1.4


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