staticd: Fix mixup in vrf translations

When we store the nexthop for ref-counting, keep
track of the nexthop vrf_id as well.  This will allow
us to track the nexthop per vrf!

Additionally when we get the callback from zebra about
a nexthop update, iterate over all static routes to
see if the nexthop we are getting a callback is
one we are concerned about.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2018-08-28 22:45:06 -04:00 committed by Philippe Guibert
parent 533ab00846
commit 31e2232baa
2 changed files with 55 additions and 33 deletions

View File

@ -29,8 +29,8 @@
#include "static_zebra.h" #include "static_zebra.h"
#include "static_nht.h" #include "static_nht.h"
void static_nht_update(struct prefix *p, uint32_t nh_num, void static_nht_update(struct prefix *p, uint32_t nh_num, afi_t afi,
afi_t afi, vrf_id_t vrf_id) vrf_id_t nh_vrf_id)
{ {
struct route_table *stable; struct route_table *stable;
struct static_route *si; struct static_route *si;
@ -40,41 +40,47 @@ void static_nht_update(struct prefix *p, uint32_t nh_num,
bool orig; bool orig;
bool reinstall; bool reinstall;
vrf = vrf_lookup_by_id(vrf_id); RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
svrf = vrf->info;
if (!svrf)
continue;
if (!vrf || !vrf->info) stable = static_vrf_static_table(afi, SAFI_UNICAST, svrf);
return; if (!stable)
continue;
svrf = vrf->info; for (rn = route_top(stable); rn; rn = route_next(rn)) {
stable = static_vrf_static_table(afi, SAFI_UNICAST, svrf); reinstall = false;
if (!stable) for (si = rn->info; si; si = si->next) {
return; if (si->nh_vrf_id != nh_vrf_id)
continue;
for (rn = route_top(stable); rn; rn = route_next(rn)) { if (si->type != STATIC_IPV4_GATEWAY
reinstall = false; && si->type != STATIC_IPV4_GATEWAY_IFNAME
for (si = rn->info; si; si = si->next) { && si->type != STATIC_IPV6_GATEWAY
if (si->type != STATIC_IPV4_GATEWAY && && si->type != STATIC_IPV6_GATEWAY_IFNAME)
si->type != STATIC_IPV4_GATEWAY_IFNAME && continue;
si->type != STATIC_IPV6_GATEWAY &&
si->type != STATIC_IPV6_GATEWAY_IFNAME)
continue;
orig = si->nh_valid; orig = si->nh_valid;
if (p->family == AF_INET && if (p->family == AF_INET
p->u.prefix4.s_addr == si->addr.ipv4.s_addr) && p->u.prefix4.s_addr
si->nh_valid = !!nh_num; == si->addr.ipv4.s_addr)
si->nh_valid = !!nh_num;
if (p->family == AF_INET6 && if (p->family == AF_INET6
memcmp(&p->u.prefix6, &si->addr.ipv6, 16) == 0) && memcmp(&p->u.prefix6, &si->addr.ipv6, 16)
si->nh_valid = !!nh_num; == 0)
si->nh_valid = !!nh_num;
if (orig != si->nh_valid) if (orig != si->nh_valid)
reinstall = true; reinstall = true;
if (reinstall) { if (reinstall) {
static_zebra_route_add(rn, si, vrf_id, static_zebra_route_add(
SAFI_UNICAST, true); rn, si, vrf->vrf_id,
reinstall = false; SAFI_UNICAST, true);
reinstall = false;
}
} }
} }
} }

View File

@ -35,6 +35,7 @@
#include "nexthop.h" #include "nexthop.h"
#include "nexthop_group.h" #include "nexthop_group.h"
#include "hash.h" #include "hash.h"
#include "jhash.h"
#include "static_vrf.h" #include "static_vrf.h"
#include "static_routes.h" #include "static_routes.h"
@ -180,6 +181,9 @@ static void zebra_connected(struct zclient *zclient)
struct static_nht_data { struct static_nht_data {
struct prefix *nh; struct prefix *nh;
vrf_id_t nh_vrf_id;
uint32_t refcount; uint32_t refcount;
uint8_t nh_num; uint8_t nh_num;
}; };
@ -201,13 +205,18 @@ static int static_zebra_nexthop_update(int command, struct zclient *zclient,
memset(&lookup, 0, sizeof(lookup)); memset(&lookup, 0, sizeof(lookup));
lookup.nh = &nhr.prefix; lookup.nh = &nhr.prefix;
lookup.nh_vrf_id = vrf_id;
nhtd = hash_lookup(static_nht_hash, &lookup); nhtd = hash_lookup(static_nht_hash, &lookup);
if (nhtd)
if (nhtd) {
nhtd->nh_num = nhr.nexthop_num; nhtd->nh_num = nhr.nexthop_num;
static_nht_update(&nhr.prefix, nhr.nexthop_num, afi,
nhtd->nh_vrf_id);
} else
zlog_err("No nhtd?");
static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id);
return 1; return 1;
} }
@ -219,8 +228,10 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap)
static unsigned int static_nht_hash_key(void *data) static unsigned int static_nht_hash_key(void *data)
{ {
struct static_nht_data *nhtd = data; struct static_nht_data *nhtd = data;
unsigned int key = 0;
return prefix_hash_key(nhtd->nh); key = prefix_hash_key(nhtd->nh);
return jhash_1word(nhtd->nh_vrf_id, key);
} }
static int static_nht_hash_cmp(const void *d1, const void *d2) static int static_nht_hash_cmp(const void *d1, const void *d2)
@ -228,6 +239,9 @@ static int static_nht_hash_cmp(const void *d1, const void *d2)
const struct static_nht_data *nhtd1 = d1; const struct static_nht_data *nhtd1 = d1;
const struct static_nht_data *nhtd2 = d2; const struct static_nht_data *nhtd2 = d2;
if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id)
return 0;
return prefix_same(nhtd1->nh, nhtd2->nh); return prefix_same(nhtd1->nh, nhtd2->nh);
} }
@ -242,6 +256,7 @@ static void *static_nht_hash_alloc(void *data)
prefix_copy(new->nh, copy->nh); prefix_copy(new->nh, copy->nh);
new->refcount = 0; new->refcount = 0;
new->nh_num = 0; new->nh_num = 0;
new->nh_vrf_id = copy->nh_vrf_id;
return new; return new;
} }
@ -293,6 +308,7 @@ void static_zebra_nht_register(struct static_route *si, bool reg)
memset(&lookup, 0, sizeof(lookup)); memset(&lookup, 0, sizeof(lookup));
lookup.nh = &p; lookup.nh = &p;
lookup.nh_vrf_id = si->nh_vrf_id;
si->nh_registered = reg; si->nh_registered = reg;