Skip to content

Commit

Permalink
Merge pull request #2897 from donaldsharp/zebra_rnh_fixup
Browse files Browse the repository at this point in the history
zebra: When registering a nexthop, we do not always need to re-eval
  • Loading branch information
rwestphal committed Aug 25, 2018
2 parents 6033e33 + 74f0a94 commit 955cb66
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 10 deletions.
92 changes: 90 additions & 2 deletions staticd/static_zebra.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "log.h" #include "log.h"
#include "nexthop.h" #include "nexthop.h"
#include "nexthop_group.h" #include "nexthop_group.h"
#include "hash.h"


#include "static_vrf.h" #include "static_vrf.h"
#include "static_routes.h" #include "static_routes.h"
Expand All @@ -43,6 +44,7 @@


/* Zebra structure to hold current status. */ /* Zebra structure to hold current status. */
struct zclient *zclient; struct zclient *zclient;
static struct hash *static_nht_hash;


static struct interface *zebra_interface_if_lookup(struct stream *s) static struct interface *zebra_interface_if_lookup(struct stream *s)
{ {
Expand Down Expand Up @@ -176,10 +178,16 @@ static void zebra_connected(struct zclient *zclient)
zclient_send_reg_requests(zclient, VRF_DEFAULT); zclient_send_reg_requests(zclient, VRF_DEFAULT);
} }


struct static_nht_data {
struct prefix *nh;
uint32_t refcount;
uint8_t nh_num;
};


static int static_zebra_nexthop_update(int command, struct zclient *zclient, static int static_zebra_nexthop_update(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id) zebra_size_t length, vrf_id_t vrf_id)
{ {
struct static_nht_data *nhtd, lookup;
struct zapi_route nhr; struct zapi_route nhr;
afi_t afi = AFI_IP; afi_t afi = AFI_IP;


Expand All @@ -191,6 +199,14 @@ static int static_zebra_nexthop_update(int command, struct zclient *zclient,
if (nhr.prefix.family == AF_INET6) if (nhr.prefix.family == AF_INET6)
afi = AFI_IP6; afi = AFI_IP6;


memset(&lookup, 0, sizeof(lookup));
lookup.nh = &nhr.prefix;

nhtd = hash_lookup(static_nht_hash, &lookup);
if (nhtd)
nhtd->nh_num = nhr.nexthop_num;


static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id); static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id);
return 1; return 1;
} }
Expand All @@ -200,10 +216,50 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap)
mpls_enabled = cap->mpls_enabled; mpls_enabled = cap->mpls_enabled;
} }


static unsigned int static_nht_hash_key(void *data)
{
struct static_nht_data *nhtd = data;

return prefix_hash_key(nhtd->nh);
}

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;

return prefix_same(nhtd1->nh, nhtd2->nh);
}

static void *static_nht_hash_alloc(void *data)
{
struct static_nht_data *copy = data;
struct static_nht_data *new;

new = XMALLOC(MTYPE_TMP, sizeof(*new));

new->nh = prefix_new();
prefix_copy(new->nh, copy->nh);
new->refcount = 0;
new->nh_num = 0;

return new;
}

static void static_nht_hash_free(void *data)
{
struct static_nht_data *nhtd = data;

prefix_free(nhtd->nh);
XFREE(MTYPE_TMP, nhtd);
}

void static_zebra_nht_register(struct static_route *si, bool reg) void static_zebra_nht_register(struct static_route *si, bool reg)
{ {
struct static_nht_data *nhtd, lookup;
uint32_t cmd; uint32_t cmd;
struct prefix p; struct prefix p;
afi_t afi = AFI_IP;


cmd = (reg) ? cmd = (reg) ?
ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER; ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
Expand All @@ -224,20 +280,48 @@ void static_zebra_nht_register(struct static_route *si, bool reg)
p.family = AF_INET; p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN; p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = si->addr.ipv4; p.u.prefix4 = si->addr.ipv4;
afi = AFI_IP;
break; break;
case STATIC_IPV6_GATEWAY: case STATIC_IPV6_GATEWAY:
case STATIC_IPV6_GATEWAY_IFNAME: case STATIC_IPV6_GATEWAY_IFNAME:
p.family = AF_INET6; p.family = AF_INET6;
p.prefixlen = IPV6_MAX_BITLEN; p.prefixlen = IPV6_MAX_BITLEN;
p.u.prefix6 = si->addr.ipv6; p.u.prefix6 = si->addr.ipv6;
afi = AFI_IP6;
break; break;
} }


memset(&lookup, 0, sizeof(lookup));
lookup.nh = &p;

si->nh_registered = reg;

if (reg) {
nhtd = hash_get(static_nht_hash, &lookup,
static_nht_hash_alloc);
nhtd->refcount++;

if (nhtd->refcount > 1) {
static_nht_update(nhtd->nh, nhtd->nh_num,
afi, si->nh_vrf_id);
return;
}
} else {
nhtd = hash_lookup(static_nht_hash, &lookup);
if (!nhtd)
return;

nhtd->refcount--;
if (nhtd->refcount >= 1)
return;

hash_release(static_nht_hash, nhtd);
static_nht_hash_free(nhtd);
}

if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0) if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0)
zlog_warn("%s: Failure to send nexthop to zebra", zlog_warn("%s: Failure to send nexthop to zebra",
__PRETTY_FUNCTION__); __PRETTY_FUNCTION__);

si->nh_registered = reg;
} }


extern void static_zebra_route_add(struct route_node *rn, extern void static_zebra_route_add(struct route_node *rn,
Expand Down Expand Up @@ -373,4 +457,8 @@ void static_zebra_init(void)
zclient->interface_address_delete = interface_address_delete; zclient->interface_address_delete = interface_address_delete;
zclient->route_notify_owner = route_notify_owner; zclient->route_notify_owner = route_notify_owner;
zclient->nexthop_update = static_zebra_nexthop_update; zclient->nexthop_update = static_zebra_nexthop_update;

static_nht_hash = hash_create(static_nht_hash_key,
static_nht_hash_cmp,
"Static Nexthop Tracking hash");
} }
10 changes: 8 additions & 2 deletions zebra/zapi_msg.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1022,6 +1022,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
unsigned short l = 0; unsigned short l = 0;
uint8_t flags = 0; uint8_t flags = 0;
uint16_t type = cmd2type[hdr->command]; uint16_t type = cmd2type[hdr->command];
bool exist;


if (IS_ZEBRA_DEBUG_NHT) if (IS_ZEBRA_DEBUG_NHT)
zlog_debug( zlog_debug(
Expand Down Expand Up @@ -1064,7 +1065,10 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
p.family); p.family);
return; return;
} }
rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type); rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type, &exist);
if (!rnh)
return;

if (type == RNH_NEXTHOP_TYPE) { if (type == RNH_NEXTHOP_TYPE) {
if (flags if (flags
&& !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
Expand All @@ -1084,7 +1088,9 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)


zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf));
/* Anything not AF_INET/INET6 has been filtered out above */ /* Anything not AF_INET/INET6 has been filtered out above */
zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p); if (!exist)
zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type,
&p);
} }


stream_failure: stream_failure:
Expand Down
22 changes: 17 additions & 5 deletions zebra/zebra_rnh.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ char *rnh_str(struct rnh *rnh, char *buf, int size)
return buf; return buf;
} }


struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
bool *exists)
{ {
struct route_table *table; struct route_table *table;
struct route_node *rn; struct route_node *rn;
Expand All @@ -119,6 +120,7 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
prefix2str(p, buf, sizeof(buf)); prefix2str(p, buf, sizeof(buf));
zlog_warn("%u: Add RNH %s type %d - table not found", vrfid, zlog_warn("%u: Add RNH %s type %d - table not found", vrfid,
buf, type); buf, type);
exists = false;
return NULL; return NULL;
} }


Expand All @@ -136,7 +138,9 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
route_lock_node(rn); route_lock_node(rn);
rn->info = rnh; rn->info = rnh;
rnh->node = rn; rnh->node = rn;
} *exists = false;
} else
*exists = true;


route_unlock_node(rn); route_unlock_node(rn);
return (rn->info); return (rn->info);
Expand Down Expand Up @@ -190,6 +194,14 @@ void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
route_unlock_node(rn); route_unlock_node(rn);
} }


/*
* This code will send to the registering client
* the looked up rnh.
* For a rnh that was created, there is no data
* so it will send an empty nexthop group
* If rnh exists then we know it has been evaluated
* and as such it will have a resolved rnh.
*/
void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
rnh_type_t type, vrf_id_t vrf_id) rnh_type_t type, vrf_id_t vrf_id)
{ {
Expand All @@ -201,8 +213,7 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
} }
if (!listnode_lookup(rnh->client_list, client)) { if (!listnode_lookup(rnh->client_list, client)) {
listnode_add(rnh->client_list, client); listnode_add(rnh->client_list, client);
send_client(rnh, client, type, send_client(rnh, client, type, vrf_id);
vrf_id); // Pending: check if its needed
} }
} }


Expand Down Expand Up @@ -247,9 +258,10 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
{ {
struct prefix nh; struct prefix nh;
struct rnh *rnh; struct rnh *rnh;
bool exists;


addr2hostprefix(pw->af, &pw->nexthop, &nh); addr2hostprefix(pw->af, &pw->nexthop, &nh);
rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE); rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists);
if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) { if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) {
listnode_add(rnh->zebra_pseudowire_list, pw); listnode_add(rnh->zebra_pseudowire_list, pw);
pw->rnh = rnh; pw->rnh = rnh;
Expand Down
2 changes: 1 addition & 1 deletion zebra/zebra_rnh.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ static inline int rnh_resolve_via_default(int family)
} }


extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
rnh_type_t type); rnh_type_t type, bool *exists);
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
rnh_type_t type); rnh_type_t type);
extern void zebra_free_rnh(struct rnh *rnh); extern void zebra_free_rnh(struct rnh *rnh);
Expand Down

0 comments on commit 955cb66

Please sign in to comment.