diff options
author | Mark Stapp <mjs@voltanet.io> | 2020-05-27 18:53:20 +0200 |
---|---|---|
committer | Mark Stapp <mjs@voltanet.io> | 2020-07-07 19:14:01 +0200 |
commit | cadd02e1666ccc9f46ae39868cb34c33a3d0c80c (patch) | |
tree | d83ee29601a24b4e4ecbb10901f75ad30e510a0b /zebra/zebra_rnh.c | |
parent | zebra: improve logic handling backup nexthop installation (diff) | |
download | frr-cadd02e1666ccc9f46ae39868cb34c33a3d0c80c.tar.xz frr-cadd02e1666ccc9f46ae39868cb34c33a3d0c80c.zip |
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>
Diffstat (limited to '')
-rw-r--r-- | zebra/zebra_rnh.c | 156 |
1 files changed, 144 insertions, 12 deletions
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 20af96a55..d1a5cf2a9 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -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 */ else { 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) { 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 |