forked from Mirror/frr
zebra: include backup nexthops in nexthop-tracking
Include backup nexthops when examining routes that resolve NHT requests. Include installed backups when sending nexthops in zapi messages to client daemons. Signed-off-by: Mark Stapp <mjs@voltanet.io>
This commit is contained in:
parent
9959f1daba
commit
cadd02e166
|
@ -419,7 +419,7 @@ static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf,
|
||||||
at_least_one++; /* at least one valid NH */
|
at_least_one++; /* at least one valid NH */
|
||||||
else {
|
else {
|
||||||
SET_FLAG(nexthop->flags,
|
SET_FLAG(nexthop->flags,
|
||||||
NEXTHOP_FLAG_RNH_FILTERED);
|
NEXTHOP_FLAG_RNH_FILTERED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,12 +458,12 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||||
|
|
||||||
if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
|
if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
|
||||||
char buf[PREFIX_STRLEN];
|
char buf[PREFIX_STRLEN];
|
||||||
char buf1[PREFIX_STRLEN];
|
char buf1[SRCDEST2STR_BUFFER];
|
||||||
|
|
||||||
zlog_debug("%s: %u:%s Resolved Import Entry to %s", __func__,
|
zlog_debug("%s: %u:%s Resolved Import Entry to %s", __func__,
|
||||||
rnh->vrf_id,
|
rnh->vrf_id,
|
||||||
prefix2str(&rnh->node->p, buf, sizeof(buf)),
|
prefix2str(&rnh->node->p, buf, sizeof(buf)),
|
||||||
srcdest_rnode2str(rn, buf1, sizeof(buf)));
|
srcdest_rnode2str(rn, buf1, sizeof(buf1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Identify appropriate route entry. */
|
/* Identify appropriate route entry. */
|
||||||
|
@ -974,12 +974,131 @@ static void copy_state(struct rnh *rnh, const struct route_entry *re,
|
||||||
state->vrf_id = re->vrf_id;
|
state->vrf_id = re->vrf_id;
|
||||||
state->status = re->status;
|
state->status = re->status;
|
||||||
|
|
||||||
state->nhe = zebra_nhg_alloc();
|
state->nhe = zebra_nhe_copy(re->nhe, 0);
|
||||||
|
|
||||||
|
/* Copy the 'fib' nexthops also, if present - we want to capture
|
||||||
|
* the true installed nexthops.
|
||||||
|
*/
|
||||||
|
if (re->fib_ng.nexthop)
|
||||||
|
nexthop_group_copy(&state->fib_ng, &re->fib_ng);
|
||||||
|
if (re->fib_backup_ng.nexthop)
|
||||||
|
nexthop_group_copy(&state->fib_backup_ng, &re->fib_backup_ng);
|
||||||
|
|
||||||
nexthop_group_copy(&(state->nhe->nhg), &(re->nhe->nhg));
|
|
||||||
rnh->state = state;
|
rnh->state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compare two route_entries' nexthops.
|
||||||
|
*/
|
||||||
|
static bool compare_valid_nexthops(struct route_entry *r1,
|
||||||
|
struct route_entry *r2)
|
||||||
|
{
|
||||||
|
bool matched_p = false;
|
||||||
|
struct nexthop_group *nhg1, *nhg2;
|
||||||
|
struct nexthop *nh1, *nh2;
|
||||||
|
|
||||||
|
/* Account for backup nexthops and for the 'fib' nexthop lists,
|
||||||
|
* if present.
|
||||||
|
*/
|
||||||
|
nhg1 = rib_get_fib_nhg(r1);
|
||||||
|
nhg2 = rib_get_fib_nhg(r2);
|
||||||
|
|
||||||
|
nh1 = nhg1->nexthop;
|
||||||
|
nh2 = nhg2->nexthop;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
/* Find each list's next valid nexthop */
|
||||||
|
while ((nh1 != NULL) && !rnh_nexthop_valid(r1, nh1))
|
||||||
|
nh1 = nexthop_next(nh1);
|
||||||
|
|
||||||
|
while ((nh2 != NULL) && !rnh_nexthop_valid(r2, nh2))
|
||||||
|
nh2 = nexthop_next(nh2);
|
||||||
|
|
||||||
|
if (nh1 && nh2) {
|
||||||
|
/* Any difference is a no-match */
|
||||||
|
if (nexthop_cmp(nh1, nh2) != 0) {
|
||||||
|
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
|
||||||
|
zlog_debug("%s: nh1, nh2 differ",
|
||||||
|
__func__);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
nh1 = nexthop_next(nh1);
|
||||||
|
nh2 = nexthop_next(nh2);
|
||||||
|
} else if (nh1 || nh2) {
|
||||||
|
/* One list has more valid nexthops than the other */
|
||||||
|
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
|
||||||
|
zlog_debug("%s: nh1 %s, nh2 %s", __func__,
|
||||||
|
nh1 ? "non-NULL" : "NULL",
|
||||||
|
nh2 ? "non-NULL" : "NULL");
|
||||||
|
goto done;
|
||||||
|
} else
|
||||||
|
break; /* Done with both lists */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The test for the backups is slightly different: the only installed
|
||||||
|
* backups will be in the 'fib' list.
|
||||||
|
*/
|
||||||
|
nhg1 = rib_get_fib_backup_nhg(r1);
|
||||||
|
if (nhg1 == zebra_nhg_get_backup_nhg(r1->nhe))
|
||||||
|
nhg1 = NULL;
|
||||||
|
|
||||||
|
nhg2 = rib_get_fib_backup_nhg(r2);
|
||||||
|
if (nhg2 == zebra_nhg_get_backup_nhg(r2->nhe))
|
||||||
|
nhg2 = NULL;
|
||||||
|
|
||||||
|
if (nhg1)
|
||||||
|
nh1 = nhg1->nexthop;
|
||||||
|
else
|
||||||
|
nh1 = NULL;
|
||||||
|
|
||||||
|
if (nhg2)
|
||||||
|
nh2 = nhg2->nexthop;
|
||||||
|
else
|
||||||
|
nh2 = NULL;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
/* Find each backup list's next valid nexthop */
|
||||||
|
while ((nh1 != NULL) && !rnh_nexthop_valid(r1, nh1))
|
||||||
|
nh1 = nexthop_next(nh1);
|
||||||
|
|
||||||
|
while ((nh2 != NULL) && !rnh_nexthop_valid(r2, nh2))
|
||||||
|
nh2 = nexthop_next(nh2);
|
||||||
|
|
||||||
|
if (nh1 && nh2) {
|
||||||
|
/* Any difference is a no-match */
|
||||||
|
if (nexthop_cmp(nh1, nh2) != 0) {
|
||||||
|
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
|
||||||
|
zlog_debug("%s: backup nh1, nh2 differ",
|
||||||
|
__func__);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
nh1 = nexthop_next(nh1);
|
||||||
|
nh2 = nexthop_next(nh2);
|
||||||
|
} else if (nh1 || nh2) {
|
||||||
|
/* One list has more valid nexthops than the other */
|
||||||
|
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
|
||||||
|
zlog_debug("%s: backup nh1 %s, nh2 %s",
|
||||||
|
__func__,
|
||||||
|
nh1 ? "non-NULL" : "NULL",
|
||||||
|
nh2 ? "non-NULL" : "NULL");
|
||||||
|
goto done;
|
||||||
|
} else
|
||||||
|
break; /* Done with both lists */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Well, it's a match */
|
||||||
|
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
|
||||||
|
zlog_debug("%s: matched", __func__);
|
||||||
|
|
||||||
|
matched_p = true;
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
return matched_p;
|
||||||
|
}
|
||||||
|
|
||||||
static int compare_state(struct route_entry *r1, struct route_entry *r2)
|
static int compare_state(struct route_entry *r1, struct route_entry *r2)
|
||||||
{
|
{
|
||||||
if (!r1 && !r2)
|
if (!r1 && !r2)
|
||||||
|
@ -994,12 +1113,7 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2)
|
||||||
if (r1->metric != r2->metric)
|
if (r1->metric != r2->metric)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (nexthop_group_nexthop_num(&(r1->nhe->nhg))
|
if (!compare_valid_nexthops(r1, r2))
|
||||||
!= nexthop_group_nexthop_num(&(r2->nhe->nhg)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (nexthop_group_hash(&(r1->nhe->nhg)) !=
|
|
||||||
nexthop_group_hash(&(r2->nhe->nhg)))
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1044,6 +1158,7 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
||||||
}
|
}
|
||||||
if (re) {
|
if (re) {
|
||||||
struct zapi_nexthop znh;
|
struct zapi_nexthop znh;
|
||||||
|
struct nexthop_group *nhg;
|
||||||
|
|
||||||
stream_putc(s, re->type);
|
stream_putc(s, re->type);
|
||||||
stream_putw(s, re->instance);
|
stream_putw(s, re->instance);
|
||||||
|
@ -1052,7 +1167,9 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
||||||
num = 0;
|
num = 0;
|
||||||
nump = stream_get_endp(s);
|
nump = stream_get_endp(s);
|
||||||
stream_putc(s, 0);
|
stream_putc(s, 0);
|
||||||
for (ALL_NEXTHOPS(re->nhe->nhg, nh))
|
|
||||||
|
nhg = rib_get_fib_nhg(re);
|
||||||
|
for (ALL_NEXTHOPS_PTR(nhg, nh))
|
||||||
if (rnh_nexthop_valid(re, nh)) {
|
if (rnh_nexthop_valid(re, nh)) {
|
||||||
zapi_nexthop_from_nexthop(&znh, nh);
|
zapi_nexthop_from_nexthop(&znh, nh);
|
||||||
ret = zapi_nexthop_encode(s, &znh, 0/*flags*/);
|
ret = zapi_nexthop_encode(s, &znh, 0/*flags*/);
|
||||||
|
@ -1061,6 +1178,21 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
||||||
|
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nhg = rib_get_fib_backup_nhg(re);
|
||||||
|
if (nhg == zebra_nhg_get_backup_nhg(re->nhe))
|
||||||
|
nhg = NULL;
|
||||||
|
|
||||||
|
if (nhg) {
|
||||||
|
for (ALL_NEXTHOPS_PTR(nhg, nh))
|
||||||
|
if (rnh_nexthop_valid(re, nh)) {
|
||||||
|
zapi_nexthop_from_nexthop(&znh, nh);
|
||||||
|
zapi_nexthop_encode(s, &znh,
|
||||||
|
0 /* flags */);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stream_putc_at(s, nump, num);
|
stream_putc_at(s, nump, num);
|
||||||
} else {
|
} else {
|
||||||
stream_putc(s, 0); // type
|
stream_putc(s, 0); // type
|
||||||
|
|
Loading…
Reference in a new issue