mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 21:47:15 +02:00
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
|
@ -458,12 +458,12 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi,
|
|||
|
||||
if (IS_ZEBRA_DEBUG_NHT_DETAILED) {
|
||||
char buf[PREFIX_STRLEN];
|
||||
char buf1[PREFIX_STRLEN];
|
||||
char buf1[SRCDEST2STR_BUFFER];
|
||||
|
||||
zlog_debug("%s: %u:%s Resolved Import Entry to %s", __func__,
|
||||
rnh->vrf_id,
|
||||
prefix2str(&rnh->node->p, buf, sizeof(buf)),
|
||||
srcdest_rnode2str(rn, buf1, sizeof(buf)));
|
||||
srcdest_rnode2str(rn, buf1, sizeof(buf1)));
|
||||
}
|
||||
|
||||
/* 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->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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
if (!r1 && !r2)
|
||||
|
@ -994,12 +1113,7 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2)
|
|||
if (r1->metric != r2->metric)
|
||||
return 1;
|
||||
|
||||
if (nexthop_group_nexthop_num(&(r1->nhe->nhg))
|
||||
!= nexthop_group_nexthop_num(&(r2->nhe->nhg)))
|
||||
return 1;
|
||||
|
||||
if (nexthop_group_hash(&(r1->nhe->nhg)) !=
|
||||
nexthop_group_hash(&(r2->nhe->nhg)))
|
||||
if (!compare_valid_nexthops(r1, r2))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -1044,6 +1158,7 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
|||
}
|
||||
if (re) {
|
||||
struct zapi_nexthop znh;
|
||||
struct nexthop_group *nhg;
|
||||
|
||||
stream_putc(s, re->type);
|
||||
stream_putw(s, re->instance);
|
||||
|
@ -1052,7 +1167,9 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
|||
num = 0;
|
||||
nump = stream_get_endp(s);
|
||||
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)) {
|
||||
zapi_nexthop_from_nexthop(&znh, nh);
|
||||
ret = zapi_nexthop_encode(s, &znh, 0/*flags*/);
|
||||
|
@ -1061,6 +1178,21 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
|||
|
||||
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);
|
||||
} else {
|
||||
stream_putc(s, 0); // type
|
||||
|
|
Loading…
Reference in a new issue