From 002930f7bb68850dbff4e4d71b54ca7814f4cb86 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Tue, 5 Oct 2021 15:32:23 -0400 Subject: [PATCH] zebra: add installed nexthop-group id value In some cases, zebra may install a nexthop-group id that is different from the id of the nhe struct attached to a route-entry. This happens for a singleton recursive nexthop, for example, where a route is installed with the resolving nexthop's id. The installed value is the most useful value - that corresponds to information in the kernel on linux/netlink platforms that support nhgs. Display both values if they differ in ascii output, and include both values in the json form. Signed-off-by: Mark Stapp --- zebra/rib.h | 5 ++++- zebra/zebra_dplane.c | 2 ++ zebra/zebra_rib.c | 23 +++++++++++++++-------- zebra/zebra_vty.c | 13 ++++++++++++- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/zebra/rib.h b/zebra/rib.h index 076608bb0f..fa8193bedf 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -108,8 +108,11 @@ struct route_entry { struct nexthop_group fib_ng; struct nexthop_group fib_backup_ng; - /* Nexthop group hash entry ID */ + /* Nexthop group hash entry IDs. The "installed" id is the id + * used in linux/netlink, if available. + */ uint32_t nhe_id; + uint32_t nhe_installed_id; /* Tag */ route_tag_t tag; diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 4000272544..bf34fb54a9 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -2448,6 +2448,8 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op, ret = ENOENT; goto done; } + + re->nhe_installed_id = nhe->id; } #endif /* HAVE_NETLINK */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 3df70a3b56..625c966301 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -305,35 +305,41 @@ static void route_entry_attach_ref(struct route_entry *re, { re->nhe = new; re->nhe_id = new->id; + re->nhe_installed_id = 0; zebra_nhg_increment_ref(new); } +/* Replace (if 'new_nhghe') or clear (if that's NULL) an re's nhe. */ int route_entry_update_nhe(struct route_entry *re, struct nhg_hash_entry *new_nhghe) { - struct nhg_hash_entry *old; int ret = 0; + struct nhg_hash_entry *old_nhg = NULL; if (new_nhghe == NULL) { - if (re->nhe) - zebra_nhg_decrement_ref(re->nhe); + old_nhg = re->nhe; + + re->nhe_id = 0; + re->nhe_installed_id = 0; re->nhe = NULL; goto done; } if ((re->nhe_id != 0) && re->nhe && (re->nhe != new_nhghe)) { - old = re->nhe; + /* Capture previous nhg, if any */ + old_nhg = re->nhe; route_entry_attach_ref(re, new_nhghe); - - if (old) - zebra_nhg_decrement_ref(old); } else if (!re->nhe) /* This is the first time it's being attached */ route_entry_attach_ref(re, new_nhghe); done: + /* Detach / deref previous nhg */ + if (old_nhg) + zebra_nhg_decrement_ref(old_nhg); + return ret; } @@ -3093,7 +3099,8 @@ void rib_unlink(struct route_node *rn, struct route_entry *re) if (re->nhe && re->nhe_id) { assert(re->nhe->id == re->nhe_id); - zebra_nhg_decrement_ref(re->nhe); + + route_entry_update_nhe(re, NULL); } else if (re->nhe && re->nhe->nhg.nexthop) nexthops_free(re->nhe->nhg.nexthop); diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index a3faa3d3e2..298697907b 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -540,8 +540,14 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, vty_out(vty, " Last update %s ago\n", buf); - if (show_ng) + if (show_ng) { vty_out(vty, " Nexthop Group ID: %u\n", re->nhe_id); + if (re->nhe_installed_id != 0 + && re->nhe_id != re->nhe_installed_id) + vty_out(vty, + " Installed Nexthop Group ID: %u\n", + re->nhe_installed_id); + } for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) { /* Use helper to format each nexthop */ @@ -977,6 +983,11 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, &(re->nhe->nhg))); json_object_int_add(json_route, "nexthopGroupId", re->nhe_id); + if (re->nhe_installed_id != 0) + json_object_int_add(json_route, + "installedNexthopGroupId", + re->nhe_installed_id); + json_object_string_add(json_route, "uptime", up_str); for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {