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

View File

@ -35,6 +35,7 @@
#include "nexthop.h"
#include "nexthop_group.h"
#include "hash.h"
#include "jhash.h"
#include "static_vrf.h"
#include "static_routes.h"
@ -180,6 +181,9 @@ static void zebra_connected(struct zclient *zclient)
struct static_nht_data {
struct prefix *nh;
vrf_id_t nh_vrf_id;
uint32_t refcount;
uint8_t nh_num;
};
@ -201,13 +205,18 @@ static int static_zebra_nexthop_update(int command, struct zclient *zclient,
memset(&lookup, 0, sizeof(lookup));
lookup.nh = &nhr.prefix;
lookup.nh_vrf_id = vrf_id;
nhtd = hash_lookup(static_nht_hash, &lookup);
if (nhtd)
if (nhtd) {
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;
}
@ -219,8 +228,10 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap)
static unsigned int static_nht_hash_key(void *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)
@ -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 *nhtd2 = d2;
if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id)
return 0;
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);
new->refcount = 0;
new->nh_num = 0;
new->nh_vrf_id = copy->nh_vrf_id;
return new;
}
@ -293,6 +308,7 @@ void static_zebra_nht_register(struct static_route *si, bool reg)
memset(&lookup, 0, sizeof(lookup));
lookup.nh = &p;
lookup.nh_vrf_id = si->nh_vrf_id;
si->nh_registered = reg;