bgpd rfapi: fix issue where advertised prefixes were not being disambiguated

by RD

Signed-off-by: Lou Berger <lberger@labn.net>
This commit is contained in:
Lou Berger 2017-01-15 16:43:20 -05:00
parent 764581d286
commit d1dc07bb04
7 changed files with 92 additions and 68 deletions

View File

@ -2777,7 +2777,7 @@ rfapi_register (
NULL,
action == RFAPI_REGISTER_KILL);
if (0 == rfapiApDelete (bgp, rfd, &p, pfx_mac, &adv_tunnel))
if (0 == rfapiApDelete (bgp, rfd, &p, pfx_mac, &prd, &adv_tunnel))
{
if (adv_tunnel)
rfapiTunnelRouteAnnounce (bgp, rfd, &rfd->max_prefix_lifetime);

View File

@ -103,12 +103,11 @@ sl_adb_lifetime_cmp (void *adb1, void *adb2)
return 0;
}
void
rfapiApInit (struct rfapi_advertised_prefixes *ap)
{
ap->ipN_by_prefix = skiplist_new (0, vnc_prefix_cmp, NULL);
ap->ip0_by_ether = skiplist_new (0, vnc_prefix_cmp, NULL);
ap->ipN_by_prefix = skiplist_new (0, rfapi_rib_key_cmp, NULL);
ap->ip0_by_ether = skiplist_new (0, rfapi_rib_key_cmp, NULL);
ap->by_lifetime = skiplist_new (0, sl_adb_lifetime_cmp, NULL);
}
@ -192,7 +191,7 @@ rfapiApReadvertiseAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
* TBD this is not quite right. When pfx_ip is 0/32 or 0/128,
* we need to substitute the VN address as the prefix
*/
add_vnc_route (rfd, bgp, SAFI_MPLS_VPN, &adb->prefix_ip, &prd, /* RD to use (0 for ENCAP) */
add_vnc_route (rfd, bgp, SAFI_MPLS_VPN, &adb->u.s.prefix_ip, &prd, /* RD to use (0 for ENCAP) */
&rfd->vn_addr, /* nexthop */
&local_pref, &adb->lifetime, NULL, NULL, /* struct rfapi_un_option */
NULL, /* struct rfapi_vn_option */
@ -221,11 +220,11 @@ rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
struct prefix pfx_vn_buf;
struct prefix *pfx_ip;
if (!(RFAPI_0_PREFIX (&adb->prefix_ip) &&
RFAPI_HOST_PREFIX (&adb->prefix_ip)))
if (!(RFAPI_0_PREFIX (&adb->u.s.prefix_ip) &&
RFAPI_HOST_PREFIX (&adb->u.s.prefix_ip)))
{
pfx_ip = &adb->prefix_ip;
pfx_ip = &adb->u.s.prefix_ip;
}
else
@ -247,7 +246,7 @@ rfapiApWithdrawAll (struct bgp *bgp, struct rfapi_descriptor *rfd)
}
}
del_vnc_route (rfd, rfd->peer, bgp, SAFI_MPLS_VPN, pfx_ip ? pfx_ip : &pfx_vn_buf, &adb->prd, /* RD to use (0 for ENCAP) */
del_vnc_route (rfd, rfd->peer, bgp, SAFI_MPLS_VPN, pfx_ip ? pfx_ip : &pfx_vn_buf, &adb->u.s.prd, /* RD to use (0 for ENCAP) */
ZEBRA_ROUTE_BGP, BGP_ROUTE_RFP, NULL, 0);
}
}
@ -404,19 +403,19 @@ rfapiApAdjustLifetimeStats (
{
void *cursor;
struct prefix *prefix;
struct rfapi_adb *adb;
struct rfapi_rib_key rk;
struct rfapi_adb *adb;
int rc;
vnc_zlog_debug_verbose ("%s: walking to find new min/max", __func__);
cursor = NULL;
for (rc = skiplist_next (rfd->advertised.ipN_by_prefix,
(void **) &prefix, (void **) &adb,
(void **) &rk, (void **) &adb,
&cursor); !rc;
rc =
skiplist_next (rfd->advertised.ipN_by_prefix,
(void **) &prefix, (void **) &adb, &cursor))
(void **) &rk, (void **) &adb, &cursor))
{
uint32_t lt = adb->lifetime;
@ -428,10 +427,10 @@ rfapiApAdjustLifetimeStats (
}
cursor = NULL;
for (rc = skiplist_next (rfd->advertised.ip0_by_ether,
(void **) &prefix, (void **) &adb,
(void **) &rk, (void **) &adb,
&cursor); !rc;
rc =
skiplist_next (rfd->advertised.ip0_by_ether, (void **) &prefix,
skiplist_next (rfd->advertised.ip0_by_ether, (void **) &rk,
(void **) &adb, &cursor))
{
@ -483,14 +482,15 @@ rfapiApAdd (
struct rfapi_adb *adb;
uint32_t old_lifetime = 0;
int use_ip0 = 0;
struct rfapi_rib_key rk;
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip))
{
use_ip0 = 1;
assert (pfx_eth);
rc =
skiplist_search (rfd->advertised.ip0_by_ether, pfx_eth,
skiplist_search (rfd->advertised.ip0_by_ether, &rk,
(void **) &adb);
}
@ -499,7 +499,7 @@ rfapiApAdd (
/* find prefix in advertised prefixes list */
rc =
skiplist_search (rfd->advertised.ipN_by_prefix, pfx_ip,
skiplist_search (rfd->advertised.ipN_by_prefix, &rk,
(void **) &adb);
}
@ -510,19 +510,17 @@ rfapiApAdd (
adb = XCALLOC (MTYPE_RFAPI_ADB, sizeof (struct rfapi_adb));
assert (adb);
adb->lifetime = lifetime;
adb->prefix_ip = *pfx_ip;
if (pfx_eth)
adb->prefix_eth = *pfx_eth;
adb->u.key = rk;
if (use_ip0)
{
assert (pfx_eth);
skiplist_insert (rfd->advertised.ip0_by_ether, &adb->prefix_eth,
skiplist_insert (rfd->advertised.ip0_by_ether, &adb->u.key,
adb);
}
else
{
skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->prefix_ip,
skiplist_insert (rfd->advertised.ipN_by_prefix, &adb->u.key,
adb);
}
@ -537,19 +535,12 @@ rfapiApAdd (
adb->lifetime = lifetime;
assert (!skiplist_insert (rfd->advertised.by_lifetime, adb, adb));
}
if (!use_ip0 && pfx_eth && prefix_cmp (&adb->prefix_eth, pfx_eth))
{
/* mac address changed */
adb->prefix_eth = *pfx_eth;
}
}
adb->cost = cost;
if (l2o)
adb->l2o = *l2o;
else
memset (&adb->l2o, 0, sizeof (struct rfapi_l2address_option));
adb->prd = *prd;
if (rfapiApAdjustLifetimeStats
(rfd, (rc ? NULL : &old_lifetime), &lifetime))
@ -568,16 +559,19 @@ rfapiApDelete (
struct rfapi_descriptor *rfd,
struct prefix *pfx_ip,
struct prefix *pfx_eth,
struct prefix_rd *prd,
int *advertise_tunnel) /* out */
{
int rc;
struct rfapi_adb *adb;
uint32_t old_lifetime;
int use_ip0 = 0;
struct rfapi_rib_key rk;
if (advertise_tunnel)
*advertise_tunnel = 0;
rfapi_rib_key_init(pfx_ip, prd, pfx_eth, &rk);
/* find prefix in advertised prefixes list */
if (RFAPI_0_PREFIX (pfx_ip) && RFAPI_HOST_PREFIX (pfx_ip))
{
@ -585,7 +579,7 @@ rfapiApDelete (
assert (pfx_eth);
rc =
skiplist_search (rfd->advertised.ip0_by_ether, pfx_eth,
skiplist_search (rfd->advertised.ip0_by_ether, &rk,
(void **) &adb);
}
@ -594,7 +588,7 @@ rfapiApDelete (
/* find prefix in advertised prefixes list */
rc =
skiplist_search (rfd->advertised.ipN_by_prefix, pfx_ip,
skiplist_search (rfd->advertised.ipN_by_prefix, &rk,
(void **) &adb);
}
@ -607,11 +601,11 @@ rfapiApDelete (
if (use_ip0)
{
rc = skiplist_delete (rfd->advertised.ip0_by_ether, pfx_eth, NULL);
rc = skiplist_delete (rfd->advertised.ip0_by_ether, &rk, NULL);
}
else
{
rc = skiplist_delete (rfd->advertised.ipN_by_prefix, pfx_ip, NULL);
rc = skiplist_delete (rfd->advertised.ipN_by_prefix, &rk, NULL);
}
assert (!rc);

View File

@ -93,6 +93,7 @@ rfapiApDelete (
struct rfapi_descriptor *rfd,
struct prefix *pfx_ip,
struct prefix *pfx_eth,
struct prefix_rd *prd,
int *advertise_tunnel); /* out */

View File

@ -34,21 +34,6 @@
#include "rfapi.h"
/*
* RFAPI Advertisement Data Block
*
* Holds NVE prefix advertisement information
*/
struct rfapi_adb
{
struct prefix prefix_ip;
struct prefix prefix_eth; /* now redundant with l2o */
struct prefix_rd prd;
uint32_t lifetime;
uint8_t cost;
struct rfapi_l2address_option l2o;
};
/*
* Lists of rfapi_adb. Each rfapi_adb is referenced twice:
*
@ -62,7 +47,6 @@ struct rfapi_advertised_prefixes
struct skiplist *by_lifetime; /* all */
};
struct rfapi_descriptor
{
struct route_node *un_node; /* backref to un table */
@ -378,9 +362,6 @@ rfp_cost_to_localpref (uint8_t cost);
extern int
rfapi_set_autord_from_vn (struct prefix_rd *rd, struct rfapi_ip_addr *vn);
extern void
rfapiAdbFree (struct rfapi_adb *adb);
extern struct rfapi_nexthop *
rfapi_nexthop_new (struct rfapi_nexthop *copyme);

View File

@ -405,10 +405,26 @@ rfapiRibStartTimer (
assert (ri->timer);
}
extern void
rfapi_rib_key_init (struct prefix *prefix, /* may be NULL */
struct prefix_rd *rd, /* may be NULL */
struct prefix *aux, /* may be NULL */
struct rfapi_rib_key *rk)
{
memset((void *)rk, 0, sizeof(struct rfapi_rib_key));
if (prefix)
rk->vn = *prefix;
if (rd)
rk->rd = *rd;
if (aux)
rk->aux_prefix = *aux;
}
/*
* Compares two <struct rfapi_rib_key>s
*/
static int
int
rfapi_rib_key_cmp (void *k1, void *k2)
{
struct rfapi_rib_key *a = (struct rfapi_rib_key *) k1;

View File

@ -45,6 +45,27 @@ struct rfapi_rib_key
*/
struct prefix aux_prefix;
};
#include "rfapi.h"
/*
* RFAPI Advertisement Data Block
*
* Holds NVE prefix advertisement information
*/
struct rfapi_adb
{
union {
struct {
struct prefix prefix_ip;
struct prefix_rd prd;
struct prefix prefix_eth;
} s; /* mainly for legacy use */
struct rfapi_rib_key key;
} u;
uint32_t lifetime;
uint8_t cost;
struct rfapi_l2address_option l2o;
};
struct rfapi_info
{
@ -151,4 +172,16 @@ rfapiRibCheckCounts (
#define RFAPI_RIB_CHECK_COUNTS(checkstats, offset)
#endif
extern void
rfapi_rib_key_init (struct prefix *prefix, /* may be NULL */
struct prefix_rd *rd, /* may be NULL */
struct prefix *aux, /* may be NULL */
struct rfapi_rib_key *rk);
extern int
rfapi_rib_key_cmp (void *k1, void *k2);
extern void
rfapiAdbFree (struct rfapi_adb *adb);
#endif /* QUAGGA_HGP_RFAPI_RIB_H */

View File

@ -1846,14 +1846,14 @@ rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd)
{
/* group like family prefixes together in output */
if (family != adb->prefix_ip.family)
if (family != adb->u.s.prefix_ip.family)
continue;
prefix2str (&adb->prefix_ip, buf, BUFSIZ);
prefix2str (&adb->u.s.prefix_ip, buf, BUFSIZ);
buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */
vty_out (vty, " Adv Pfx: %s%s", buf, HVTY_NEWLINE);
rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->prefix_ip);
rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->u.s.prefix_ip);
}
}
for (rc =
@ -1864,14 +1864,14 @@ rfapiPrintDescriptor (struct vty *vty, struct rfapi_descriptor *rfd)
&cursor))
{
prefix2str (&adb->prefix_eth, buf, BUFSIZ);
prefix2str (&adb->u.s.prefix_eth, buf, BUFSIZ);
buf[BUFSIZ - 1] = 0; /* guarantee NUL-terminated */
vty_out (vty, " Adv Pfx: %s%s", buf, HVTY_NEWLINE);
/* TBD update the following function to print ethernet info */
/* Also need to pass/use rd */
rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->prefix_ip);
rfapiPrintAdvertisedInfo (vty, rfd, SAFI_MPLS_VPN, &adb->u.s.prefix_ip);
}
vty_out (vty, "%s", HVTY_NEWLINE);
}
@ -3363,7 +3363,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda)
if (pPrefix)
{
if (!prefix_same (pPrefix, &adb->prefix_ip))
if (!prefix_same (pPrefix, &adb->u.s.prefix_ip))
{
#if DEBUG_L2_EXTRA
vnc_zlog_debug_verbose ("%s: adb=%p, prefix doesn't match, skipping",
@ -3376,7 +3376,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda)
{
if (memcmp
(cda->l2o.o.macaddr.octet,
adb->prefix_eth.u.prefix_eth.octet, ETHER_ADDR_LEN))
adb->u.s.prefix_eth.u.prefix_eth.octet, ETHER_ADDR_LEN))
{
#if DEBUG_L2_EXTRA
vnc_zlog_debug_verbose ("%s: adb=%p, macaddr doesn't match, skipping",
@ -3418,24 +3418,23 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda)
this_advertisement_prefix_count = 1;
rfapiQprefix2Rprefix (&adb->prefix_ip, &rp);
rfapiQprefix2Rprefix (&adb->u.s.prefix_ip, &rp);
/* if mac addr present in advert, make l2o vn option */
if (adb->prefix_eth.family == AF_ETHERNET)
if (adb->u.s.prefix_eth.family == AF_ETHERNET)
{
memset (&vn1, 0, sizeof (vn1));
memset (&vn2, 0, sizeof (vn2));
vn1.type = RFAPI_VN_OPTION_TYPE_L2ADDR;
vn1.v.l2addr.macaddr = adb->prefix_eth.u.prefix_eth;
vn1.v.l2addr.macaddr = adb->u.s.prefix_eth.u.prefix_eth;
/*
* use saved RD value instead of trying to invert
* complex L2-style RD computation in rfapi_register()
*/
vn2.type = RFAPI_VN_OPTION_TYPE_INTERNAL_RD;
vn2.v.internal_rd = adb->prd;
vn2.v.internal_rd = adb->u.s.prd;
vn1.next = &vn2;
@ -3487,7 +3486,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda)
if (CHECK_FLAG (cda->l2o.flags, RFAPI_L2O_MACADDR))
{
if (memcmp (cda->l2o.o.macaddr.octet,
adb->prefix_eth.u.prefix_eth.octet,
adb->u.s.prefix_eth.u.prefix_eth.octet,
ETHER_ADDR_LEN))
{
@ -3514,7 +3513,7 @@ rfapiDeleteLocalPrefixes (struct rfapi_local_reg_delete_arg *cda)
struct rfapi_vn_option vn;
rfapiQprefix2Rprefix (&adb->prefix_ip, &rp);
rfapiQprefix2Rprefix (&adb->u.s.prefix_ip, &rp);
memset (&vn, 0, sizeof (vn));
vn.type = RFAPI_VN_OPTION_TYPE_L2ADDR;