zebra: improve vty, simplify some primary/backup code

Improve vty output for routes and lsps with backups, including
json. Simplify or correct some code that uses both primary and
backup nexthops in dplane, nht.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
This commit is contained in:
Mark Stapp 2020-07-17 13:10:29 -04:00
parent 7483dcbe29
commit 3c0e16228d
5 changed files with 155 additions and 77 deletions

View File

@ -2001,10 +2001,19 @@ int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
break;
}
/* Need to copy flags too */
/* Need to copy flags and backup info too */
new_nhlfe->flags = nhlfe->flags;
new_nhlfe->nexthop->flags = nhlfe->nexthop->flags;
if (CHECK_FLAG(new_nhlfe->nexthop->flags,
NEXTHOP_FLAG_HAS_BACKUP)) {
new_nhlfe->nexthop->backup_num =
nhlfe->nexthop->backup_num;
memcpy(new_nhlfe->nexthop->backup_idx,
nhlfe->nexthop->backup_idx,
new_nhlfe->nexthop->backup_num);
}
if (nhlfe == lsp->best_nhlfe)
ctx->u.lsp.best_nhlfe = new_nhlfe;
}
@ -2104,8 +2113,9 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
if (re) {
nhg = rib_get_fib_nhg(re);
copy_nexthops(&(ctx->u.pw.nhg.nexthop),
nhg->nexthop, NULL);
if (nhg && nhg->nexthop)
copy_nexthops(&(ctx->u.pw.nhg.nexthop),
nhg->nexthop, NULL);
}
route_unlock_node(rn);
}
@ -2461,6 +2471,7 @@ dplane_route_notif_update(struct route_node *rn,
enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE;
struct zebra_dplane_ctx *new_ctx = NULL;
struct nexthop *nexthop;
struct nexthop_group *nhg;
if (rn == NULL || re == NULL)
goto done;
@ -2482,13 +2493,16 @@ dplane_route_notif_update(struct route_node *rn,
nexthops_free(new_ctx->u.rinfo.zd_ng.nexthop);
new_ctx->u.rinfo.zd_ng.nexthop = NULL;
copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop),
(rib_get_fib_nhg(re))->nexthop, NULL);
/* Check for backup nexthops also */
if (re->fib_backup_ng.nexthop) {
nhg = rib_get_fib_nhg(re);
if (nhg && nhg->nexthop)
copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop),
re->fib_backup_ng.nexthop, NULL);
nhg->nexthop, NULL);
/* Check for installed backup nexthops also */
nhg = rib_get_fib_backup_nhg(re);
if (nhg && nhg->nexthop) {
copy_nexthops(&(new_ctx->u.rinfo.zd_ng.nexthop),
nhg->nexthop, NULL);
}
for (ALL_NEXTHOPS(new_ctx->u.rinfo.zd_ng, nexthop))
@ -4028,19 +4042,19 @@ bool dplane_is_in_shutdown(void)
*/
void zebra_dplane_pre_finish(void)
{
struct zebra_dplane_provider *dp;
struct zebra_dplane_provider *prov;
if (IS_ZEBRA_DEBUG_DPLANE)
zlog_debug("Zebra dataplane pre-fini called");
zlog_debug("Zebra dataplane pre-finish called");
zdplane_info.dg_is_shutdown = true;
/* Notify provider(s) of pending shutdown. */
TAILQ_FOREACH(dp, &zdplane_info.dg_providers_q, dp_prov_link) {
if (dp->dp_fini == NULL)
TAILQ_FOREACH(prov, &zdplane_info.dg_providers_q, dp_prov_link) {
if (prov->dp_fini == NULL)
continue;
dp->dp_fini(dp, true);
prov->dp_fini(prov, true /* early */);
}
}
@ -4362,7 +4376,10 @@ void zebra_dplane_shutdown(void)
zdplane_info.dg_pthread = NULL;
zdplane_info.dg_master = NULL;
/* Notify provider(s) of final shutdown. */
/* Notify provider(s) of final shutdown.
* Note that this call is in the main pthread, so providers must
* be prepared for that.
*/
TAILQ_FOREACH(dp, &zdplane_info.dg_providers_q, dp_prov_link) {
if (dp->dp_fini == NULL)
continue;

View File

@ -120,7 +120,8 @@ static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp,
enum lsp_types_t type);
static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf,
mpls_label_t in_label);
static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty);
static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty,
const char *indent);
static void lsp_print(struct vty *vty, zebra_lsp_t *lsp);
static void *slsp_alloc(void *p);
static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
@ -1506,7 +1507,9 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe)
{
char buf[BUFSIZ];
json_object *json_nhlfe = NULL;
json_object *json_backups = NULL;
struct nexthop *nexthop = nhlfe->nexthop;
int i;
json_nhlfe = json_object_new_object();
json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type));
@ -1537,13 +1540,27 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe)
default:
break;
}
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
json_backups = json_object_new_array();
for (i = 0; i < nexthop->backup_num; i++) {
json_object_array_add(
json_backups,
json_object_new_int(nexthop->backup_idx[i]));
}
json_object_object_add(json_nhlfe, "backupIndex",
json_backups);
}
return json_nhlfe;
}
/*
* Print the NHLFE for a LSP forwarding entry.
*/
static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty)
static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty,
const char *indent)
{
struct nexthop *nexthop;
char buf[MPLS_LABEL_STRLEN];
@ -1558,6 +1575,10 @@ static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty)
nexthop->nh_label->label,
buf, sizeof(buf), 0),
nhlfe->distance);
if (indent)
vty_out(vty, "%s", indent);
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
@ -1602,9 +1623,9 @@ static void lsp_print(struct vty *vty, zebra_lsp_t *lsp)
: "");
frr_each(nhlfe_list, &lsp->nhlfe_list, nhlfe) {
nhlfe_print(nhlfe, vty);
nhlfe_print(nhlfe, vty, NULL);
if (nhlfe->nexthop &&
if (nhlfe->nexthop == NULL ||
!CHECK_FLAG(nhlfe->nexthop->flags,
NEXTHOP_FLAG_HAS_BACKUP))
continue;
@ -1622,7 +1643,7 @@ static void lsp_print(struct vty *vty, zebra_lsp_t *lsp)
if (backup) {
vty_out(vty, " [backup %d]", i);
nhlfe_print(backup, vty);
nhlfe_print(backup, vty, " ");
}
}
}
@ -1646,6 +1667,19 @@ static json_object *lsp_json(zebra_lsp_t *lsp)
json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe));
json_object_object_add(json, "nexthops", json_nhlfe_list);
json_nhlfe_list = NULL;
frr_each(nhlfe_list, &lsp->backup_nhlfe_list, nhlfe) {
if (json_nhlfe_list == NULL)
json_nhlfe_list = json_object_new_array();
json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe));
}
if (json_nhlfe_list)
json_object_object_add(json, "backupNexthops", json_nhlfe_list);
return json;
}

View File

@ -1951,8 +1951,11 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
goto done_with_match;
}
/* Examine installed nexthops */
nhg = &match->nhe->nhg;
/* Examine installed nexthops; note that there
* may not be any installed primary nexthops if
* only backups are installed.
*/
nhg = rib_get_fib_nhg(match);
for (ALL_NEXTHOPS_PTR(nhg, newhop)) {
if (!nexthop_valid_resolve(nexthop, newhop))
continue;
@ -1973,8 +1976,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
* dedicated fib list.
*/
nhg = rib_get_fib_backup_nhg(match);
if (nhg == NULL ||
nhg == zebra_nhg_get_backup_nhg(match->nhe))
if (nhg == NULL || nhg->nexthop == NULL)
goto done_with_match;
for (ALL_NEXTHOPS_PTR(nhg, newhop)) {

View File

@ -1040,22 +1040,10 @@ static bool compare_valid_nexthops(struct route_entry *r1,
* 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;
nh1 = nhg1->nexthop;
nh2 = nhg2->nexthop;
while (1) {
/* Find each backup list's next valid nexthop */
@ -1180,9 +1168,6 @@ static int send_client(struct rnh *rnh, struct zserv *client,
}
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)) {

View File

@ -172,11 +172,24 @@ DEFUN (show_ip_rpf_addr,
}
static char re_status_output_char(const struct route_entry *re,
const struct nexthop *nhop)
const struct nexthop *nhop,
bool is_fib)
{
if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
if (!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE) &&
!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE))
bool star_p = false;
if (nhop &&
!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE) &&
!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE)) {
/* More-specific test for 'fib' output */
if (is_fib) {
star_p = !!CHECK_FLAG(nhop->flags,
NEXTHOP_FLAG_FIB);
} else
star_p = true;
}
if (star_p)
return '*';
else
return ' ';
@ -207,7 +220,8 @@ static void show_nh_backup_helper(struct vty *vty,
/* Double-check that there _is_ a backup */
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP) ||
re->nhe->backup_info == NULL || re->nhe->backup_info->nhe == NULL)
re->nhe->backup_info == NULL || re->nhe->backup_info->nhe == NULL ||
re->nhe->backup_info->nhe->nhg.nexthop == NULL)
return;
/* Locate the backup nexthop(s) */
@ -221,6 +235,9 @@ static void show_nh_backup_helper(struct vty *vty,
break;
}
/* It's possible for backups to be recursive too,
* so walk the recursive resolution list if present.
*/
temp = backup;
while (backup) {
vty_out(vty, " ");
@ -258,7 +275,7 @@ static void show_nexthop_detail_helper(struct vty *vty,
nexthop->rparent ? " " : "");
else
vty_out(vty, " %c%s",
re_status_output_char(re, nexthop),
re_status_output_char(re, nexthop, false),
nexthop->rparent ? " " : "");
switch (nexthop->type) {
@ -768,18 +785,19 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
struct route_entry *re, json_object *json,
bool is_fib)
{
struct nexthop *nexthop;
const struct nexthop *nexthop;
int len = 0;
char buf[SRCDEST2STR_BUFFER];
json_object *json_nexthops = NULL;
json_object *json_nexthop = NULL;
json_object *json_route = NULL;
time_t uptime;
struct vrf *vrf = NULL;
rib_dest_t *dest = rib_dest_from_rnode(rn);
struct nexthop_group *nhg;
const struct vrf *vrf = NULL;
const rib_dest_t *dest = rib_dest_from_rnode(rn);
const struct nexthop_group *nhg;
char up_str[MONOTIME_STRLEN];
bool first_p;
bool first_p = true;
bool nhg_from_backup = false;
uptime = monotime(NULL);
uptime -= re->uptime;
@ -854,9 +872,11 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
json_nexthop = json_object_new_object();
show_nexthop_json_helper(json_nexthop,
nexthop, re);
show_nexthop_json_helper(json_nexthop, nexthop, re);
json_object_array_add(json_nexthops, json_nexthop);
json_object_array_add(json_nexthops,
json_nexthop);
}
json_object_object_add(json_route, "nexthops", json_nexthops);
@ -867,7 +887,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
else
nhg = zebra_nhg_get_backup_nhg(re->nhe);
if (nhg) {
if (nhg && nhg->nexthop) {
json_nexthops = json_object_new_array();
for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
@ -887,42 +907,62 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
return;
}
/* Prefix information, and first nexthop. If we're showing 'fib',
* and there are no installed primary nexthops, see if there are any
* backup nexthops and start with those.
*/
if (is_fib && nhg->nexthop == NULL) {
nhg = rib_get_fib_backup_nhg(re);
nhg_from_backup = true;
}
len = vty_out(vty, "%c", zebra_route_char(re->type));
if (re->instance)
len += vty_out(vty, "[%d]", re->instance);
if (nhg_from_backup && nhg->nexthop) {
len += vty_out(
vty, "%cb%c %s",
CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) ? '>' : ' ',
re_status_output_char(re, nhg->nexthop, is_fib),
srcdest_rnode2str(rn, buf, sizeof(buf)));
} else {
len += vty_out(
vty, "%c%c %s",
CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) ? '>' : ' ',
re_status_output_char(re, nhg->nexthop, is_fib),
srcdest_rnode2str(rn, buf, sizeof(buf)));
}
/* Distance and metric display. */
if (((re->type == ZEBRA_ROUTE_CONNECT) &&
(re->distance || re->metric)) ||
(re->type != ZEBRA_ROUTE_CONNECT))
len += vty_out(vty, " [%u/%u]", re->distance,
re->metric);
/* Nexthop information. */
first_p = true;
for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
if (first_p) {
first_p = false;
/* Prefix information. */
len = vty_out(vty, "%c", zebra_route_char(re->type));
if (re->instance)
len += vty_out(vty, "[%d]", re->instance);
len += vty_out(
vty, "%c%c %s",
CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
? '>'
: ' ',
re_status_output_char(re, nexthop),
srcdest_rnode2str(rn, buf, sizeof(buf)));
/* Distance and metric display. */
if (((re->type == ZEBRA_ROUTE_CONNECT) &&
(re->distance || re->metric)) ||
(re->type != ZEBRA_ROUTE_CONNECT))
len += vty_out(vty, " [%u/%u]", re->distance,
re->metric);
} else if (nhg_from_backup) {
vty_out(vty, " b%c%*c",
re_status_output_char(re, nexthop, is_fib),
len - 3 + (2 * nexthop_level(nexthop)), ' ');
} else {
vty_out(vty, " %c%*c",
re_status_output_char(re, nexthop),
re_status_output_char(re, nexthop, is_fib),
len - 3 + (2 * nexthop_level(nexthop)), ' ');
}
show_route_nexthop_helper(vty, re, nexthop);
vty_out(vty, ", %s\n", up_str);
}
/* Check for backup info if present */
/* If we only had backup nexthops, we're done */
if (nhg_from_backup)
return;
/* Check for backup nexthop info if present */
if (is_fib)
nhg = rib_get_fib_backup_nhg(re);
else