diff options
Diffstat (limited to 'zebra/zebra_vty.c')
| -rw-r--r-- | zebra/zebra_vty.c | 224 |
1 files changed, 159 insertions, 65 deletions
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index b18871dd2a..bc9dada255 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -71,6 +71,12 @@ static void vty_show_ip_route_summary(struct vty *vty, static void vty_show_ip_route_summary_prefix(struct vty *vty, struct route_table *table, bool use_json); +/* Helper api to format a nexthop in the 'detailed' output path. */ +static void show_nexthop_detail_helper(struct vty *vty, + const struct route_entry *re, + const struct nexthop *nexthop, + bool is_backup); + DEFUN (ip_multicast_mode, ip_multicast_mode_cmd, @@ -166,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 ' '; @@ -190,19 +209,51 @@ static char re_status_output_char(const struct route_entry *re, } /* - * TODO -- Show backup nexthop info + * Show backup nexthop info, in the 'detailed' output path */ static void show_nh_backup_helper(struct vty *vty, - const struct nhg_hash_entry *nhe, + const struct route_entry *re, const struct nexthop *nexthop) { + const struct nexthop *start, *backup, *temp; + int i, idx; + /* Double-check that there _is_ a backup */ - if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_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->nhe->nhg.nexthop == NULL) return; - /* Locate the backup nexthop */ + /* Locate the backup nexthop(s) */ + start = re->nhe->backup_info->nhe->nhg.nexthop; + for (i = 0; i < nexthop->backup_num; i++) { + /* Format the backup(s) (indented) */ + backup = start; + for (idx = 0; idx < nexthop->backup_idx[i]; idx++) { + backup = backup->next; + if (backup == NULL) + break; + } - /* Format the backup (indented) */ + /* It's possible for backups to be recursive too, + * so walk the recursive resolution list if present. + */ + temp = backup; + while (backup) { + vty_out(vty, " "); + show_nexthop_detail_helper(vty, re, backup, + true /*backup*/); + vty_out(vty, "\n"); + + if (backup->resolved && temp == backup) + backup = backup->resolved; + else + backup = nexthop_next(backup); + + if (backup == temp->next) + break; + } + } } @@ -212,14 +263,20 @@ static void show_nh_backup_helper(struct vty *vty, */ static void show_nexthop_detail_helper(struct vty *vty, const struct route_entry *re, - const struct nexthop *nexthop) + const struct nexthop *nexthop, + bool is_backup) { char addrstr[32]; char buf[MPLS_LABEL_STRLEN]; + int i; - vty_out(vty, " %c%s", - re_status_output_char(re, nexthop), - nexthop->rparent ? " " : ""); + if (is_backup) + vty_out(vty, " b%s", + nexthop->rparent ? " " : ""); + else + vty_out(vty, " %c%s", + re_status_output_char(re, nexthop, false), + nexthop->rparent ? " " : ""); switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: @@ -333,6 +390,13 @@ static void show_nexthop_detail_helper(struct vty *vty, if (nexthop->weight) vty_out(vty, ", weight %u", nexthop->weight); + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + vty_out(vty, ", backup %d", nexthop->backup_idx[0]); + + for (i = 1; i < nexthop->backup_num; i++) + vty_out(vty, ",%d", nexthop->backup_idx[i]); + } } /* New RIB. Detailed information for IPv4 route. */ @@ -403,12 +467,13 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) { /* Use helper to format each nexthop */ - show_nexthop_detail_helper(vty, re, nexthop); + show_nexthop_detail_helper(vty, re, nexthop, + false /*not backup*/); vty_out(vty, "\n"); - /* Include backup info, if present */ + /* Include backup(s), if present */ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) - show_nh_backup_helper(vty, re->nhe, nexthop); + show_nh_backup_helper(vty, re, nexthop); } vty_out(vty, "\n"); } @@ -422,6 +487,7 @@ static void show_route_nexthop_helper(struct vty *vty, const struct nexthop *nexthop) { char buf[MPLS_LABEL_STRLEN]; + int i; switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: @@ -519,8 +585,12 @@ static void show_route_nexthop_helper(struct vty *vty, if (nexthop->weight) vty_out(vty, ", weight %u", nexthop->weight); - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) - vty_out(vty, ", backup %d", nexthop->backup_idx); + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { + vty_out(vty, ", backup %d", nexthop->backup_idx[0]); + + for (i = 1; i < nexthop->backup_num; i++) + vty_out(vty, ",%d", nexthop->backup_idx[i]); + } } /* @@ -534,6 +604,8 @@ static void show_nexthop_json_helper(json_object *json_nexthop, char buf[SRCDEST2STR_BUFFER]; struct vrf *vrf = NULL; json_object *json_labels = NULL; + json_object *json_backups = NULL; + int i; json_object_int_add(json_nexthop, "flags", nexthop->flags); @@ -645,9 +717,17 @@ static void show_nexthop_json_helper(json_object *json_nexthop, json_object_boolean_true_add(json_nexthop, "recursive"); - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) - json_object_int_add(json_nexthop, "backupIndex", - nexthop->backup_idx); + 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_nexthop, "backupIndex", + json_backups); + } switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: @@ -705,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; @@ -791,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); @@ -804,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)) { @@ -824,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 @@ -1206,7 +1309,7 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe) if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) vty_out(vty, " [backup %d]", - nexthop->backup_idx); + nexthop->backup_idx[0]); vty_out(vty, "\n"); continue; @@ -1214,22 +1317,13 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe) /* TODO -- print more useful backup info */ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { - struct nexthop *backup; int i; - i = 0; - for (ALL_NEXTHOPS(nhe->backup_info->nhe->nhg, backup)) { - if (i == nexthop->backup_idx) - break; - i++; - } + vty_out(vty, "[backup"); + for (i = 0; i < nexthop->backup_num; i++) + vty_out(vty, " %d", nexthop->backup_idx[i]); - /* TODO */ - if (backup) - vty_out(vty, " [backup %d]", - nexthop->backup_idx); - else - vty_out(vty, " [backup INVALID]"); + vty_out(vty, "]"); } vty_out(vty, "\n"); |
