summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_rnh.c
diff options
context:
space:
mode:
authorMark Stapp <mjs@voltanet.io>2020-05-27 18:53:20 +0200
committerMark Stapp <mjs@voltanet.io>2020-07-07 19:14:01 +0200
commitcadd02e1666ccc9f46ae39868cb34c33a3d0c80c (patch)
treed83ee29601a24b4e4ecbb10901f75ad30e510a0b /zebra/zebra_rnh.c
parentzebra: improve logic handling backup nexthop installation (diff)
downloadfrr-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.c156
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