]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: fix show ip route output
authorChristophe Gouault <christophe.gouault@6wind.com>
Thu, 20 Aug 2020 09:15:33 +0000 (11:15 +0200)
committerIgor Ryzhov <iryzhov@nfware.com>
Tue, 6 Oct 2020 12:54:25 +0000 (15:54 +0300)
Variable "show ip route" commands invoke the same helper
(do_show_ip_route), potentially several times.

When asking to dump a non-default vrf, all vrfs or all tables, the
output is messy, the header summarizing abbreviations is repeated
several times, excess line feeds appear, the default table of default
VRF is concatenated to the previous table output...

Normalize the output:

- whatever the case, display the common header at most once, if there
  is at least an entry to dump.

- when using a "vrf all" or "table all" command, prepend a line with
  the VRF and table (even for the default vrf or table).

- when dumping a specific vrf or table, prepend a line with the VRF
  and table.

Example (vrf all)
=================

router# show ip route vrf all
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued route, r - rejected route

VRF main:
C>* 10.0.2.0/24 is directly connected, mgmt0, 00:24:09
K>* 10.0.2.2/32 [0/100] is directly connected, mgmt0, 00:24:09
C>* 10.125.0.0/24 is directly connected, ntfp2, 00:00:26

VRF private:
S>* 1.1.1.0/24 [1/0] via 10.125.0.2, loop0, 00:00:29
C>* 10.125.0.0/24 is directly connected, loop0, 00:00:42

Example (main vrf)
==================

router# show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued route, r - rejected route

C>* 10.0.2.0/24 is directly connected, mgmt0, 00:24:41
K>* 10.0.2.2/32 [0/100] is directly connected, mgmt0, 00:24:41
C>* 10.125.0.0/24 is directly connected, ntfp2, 00:00:58

Example (specific vrf)
======================

router# show ip route vrf private
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued route, r - rejected route

VRF private:
S>* 1.1.1.0/24 [1/0] via 10.125.0.2, loop0, 00:01:23
C>* 10.125.0.0/24 is directly connected, loop0, 00:01:36

Example (all tables)
====================

router# show ip route table all
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued route, r - rejected route

VRF main table 200:
S>* 4.4.4.4/32 [1/0] via 10.125.0.3, ntfp2, 00:01:51

VRF main table 254:
C>* 10.0.2.0/24 is directly connected, mgmt0, 00:25:34
K>* 10.0.2.2/32 [0/100] is directly connected, mgmt0, 00:25:34
C>* 10.125.0.0/24 is directly connected, ntfp2, 00:01:51

Example (all vrf, all table)
============================

router# show ip route table all vrf all
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued route, r - rejected route

VRF main table 200:
S>* 4.4.4.4/32 [1/0] via 10.125.0.3, ntfp2, 00:02:15

VRF main table 254:
C>* 10.0.2.0/24 is directly connected, mgmt0, 00:25:58
K>* 10.0.2.2/32 [0/100] is directly connected, mgmt0, 00:25:58
C>* 10.125.0.0/24 is directly connected, ntfp2, 00:02:15

VRF private table 200:
S>* 2.2.2.0/24 [1/0] via 10.125.0.2, loop0, 00:02:18

VRF private table 254:
S>* 1.1.1.0/24 [1/0] via 10.125.0.2, loop0, 00:02:18
C>* 10.125.0.0/24 is directly connected, loop0, 00:02:31

Example (specific table)
========================

router# show ip route table 200
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
       F - PBR, f - OpenFabric,
       > - selected route, * - FIB route, q - queued route, r - rejected route

VRF main table 200:
S>* 4.4.4.4/32 [1/0] via 10.125.0.3, ntfp2, 00:05:26

Signed-off-by: Christophe Gouault <christophe.gouault@6wind.com>
zebra/zebra_vty.c

index b6d0b26125cb00f732efa1add1bb53e7cc63c61b..04581be19b1dd86b2277c0eba8215702038325e1 100644 (file)
 
 extern int allow_delete;
 
+/* context to manage dumps in multiple tables or vrfs */
+struct route_show_ctx {
+       bool multi;       /* dump multiple tables or vrf */
+       bool header_done; /* common header already displayed */
+};
+
 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
                            safi_t safi, bool use_fib, bool use_json,
                            route_tag_t tag,
                            const struct prefix *longer_prefix_p,
                            bool supernets_only, int type,
-                           unsigned short ospf_instance_id, uint32_t tableid);
+                           unsigned short ospf_instance_id, uint32_t tableid,
+                           struct route_show_ctx *ctx);
 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
                                     int mcast, bool use_fib, bool show_ng);
 static void vty_show_ip_route_summary(struct vty *vty,
@@ -140,8 +147,12 @@ DEFUN (show_ip_rpf,
        JSON_STR)
 {
        bool uj = use_json(argc, argv);
+       struct route_show_ctx ctx = {
+               .multi = false,
+       };
+
        return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
-                               false, uj, 0, NULL, false, 0, 0, 0);
+                               false, uj, 0, NULL, false, 0, 0, 0, &ctx);
 }
 
 DEFUN (show_ip_rpf_addr,
@@ -1038,7 +1049,7 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
                                 const struct prefix *longer_prefix_p,
                                 bool supernets_only, int type,
                                 unsigned short ospf_instance_id, bool use_json,
-                                uint32_t tableid)
+                                uint32_t tableid, struct route_show_ctx *ctx)
 {
        struct route_node *rn;
        struct route_entry *re;
@@ -1049,6 +1060,17 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
        uint32_t addr;
        char buf[BUFSIZ];
 
+       /*
+        * ctx->multi indicates if we are dumping multiple tables or vrfs.
+        * if set:
+        *   => display the common header at most once
+        *   => add newline at each call except first
+        *   => always display the VRF and table
+        * else:
+        *   => display the common header if at least one entry is found
+        *   => display the VRF and table if specific
+        */
+
        if (use_json)
                json = json_object_new_object();
 
@@ -1092,23 +1114,30 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
                        if (use_json) {
                                if (!json_prefix)
                                        json_prefix = json_object_new_array();
-                       } else {
-                               if (first) {
+                       } else if (first) {
+                               if (!ctx->header_done) {
                                        if (afi == AFI_IP)
                                                vty_out(vty,
                                                        SHOW_ROUTE_V4_HEADER);
                                        else
                                                vty_out(vty,
                                                        SHOW_ROUTE_V6_HEADER);
-
-                                       if (tableid && tableid != RT_TABLE_MAIN)
-                                               vty_out(vty, "\nVRF %s table %u:\n",
-                                                       zvrf_name(zvrf), tableid);
-                                       else if (zvrf_id(zvrf) != VRF_DEFAULT)
-                                               vty_out(vty, "\nVRF %s:\n",
+                               }
+                               if (ctx->multi && ctx->header_done)
+                                       vty_out(vty, "\n");
+                               if (ctx->multi || zvrf_id(zvrf) != VRF_DEFAULT
+                                   || tableid) {
+                                       if (!tableid)
+                                               vty_out(vty, "VRF %s:\n",
                                                        zvrf_name(zvrf));
-                                       first = 0;
+                                       else
+                                               vty_out(vty,
+                                                       "VRF %s table %u:\n",
+                                                       zvrf_name(zvrf),
+                                                       tableid);
                                }
+                               ctx->header_done = true;
+                               first = 0;
                        }
 
                        vty_show_ip_route(vty, rn, re, json_prefix, use_fib);
@@ -1133,7 +1162,8 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
                                 route_tag_t tag,
                                 const struct prefix *longer_prefix_p,
                                 bool supernets_only, int type,
-                                unsigned short ospf_instance_id)
+                                unsigned short ospf_instance_id,
+                                struct route_show_ctx *ctx)
 {
        struct zebra_router_table *zrt;
        struct rib_table_info *info;
@@ -1148,11 +1178,10 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
                    zrt->safi != SAFI_UNICAST)
                        continue;
 
-               do_show_ip_route(vty, zvrf_name(zvrf), afi,
-                                SAFI_UNICAST, use_fib, use_json,
-                                tag, longer_prefix_p,
-                                supernets_only, type,
-                                ospf_instance_id, zrt->tableid);
+               do_show_ip_route(vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
+                                use_fib, use_json, tag, longer_prefix_p,
+                                supernets_only, type, ospf_instance_id,
+                                zrt->tableid, ctx);
        }
 }
 
@@ -1161,7 +1190,8 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
                            route_tag_t tag,
                            const struct prefix *longer_prefix_p,
                            bool supernets_only, int type,
-                           unsigned short ospf_instance_id, uint32_t tableid)
+                           unsigned short ospf_instance_id, uint32_t tableid,
+                           struct route_show_ctx *ctx)
 {
        struct route_table *table;
        struct zebra_vrf *zvrf = NULL;
@@ -1194,7 +1224,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
 
        do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
                             longer_prefix_p, supernets_only, type,
-                            ospf_instance_id, use_json, tableid);
+                            ospf_instance_id, use_json, tableid, ctx);
 
        return CMD_SUCCESS;
 }
@@ -1671,6 +1701,9 @@ DEFPY (show_route,
        struct vrf *vrf;
        int type = 0;
        struct zebra_vrf *zvrf;
+       struct route_show_ctx ctx = {
+               .multi = vrf_all || table_all,
+       };
 
        if (!vrf_is_backend_netns()) {
                if ((vrf_all || vrf_name) && (table || table_all)) {
@@ -1698,17 +1731,18 @@ DEFPY (show_route,
                                continue;
 
                        if (table_all)
-                               do_show_ip_route_all(vty, zvrf, afi,
-                                                    !!fib, !!json,
-                                                    tag, prefix_str ? prefix : NULL,
+                               do_show_ip_route_all(vty, zvrf, afi, !!fib,
+                                                    !!json, tag,
+                                                    prefix_str ? prefix : NULL,
                                                     !!supernets_only, type,
-                                                    ospf_instance_id);
+                                                    ospf_instance_id, &ctx);
                        else
                                do_show_ip_route(vty, zvrf_name(zvrf), afi,
-                                                SAFI_UNICAST, !!fib, !!json, tag,
+                                                SAFI_UNICAST, !!fib, !!json,
+                                                tag,
                                                 prefix_str ? prefix : NULL,
                                                 !!supernets_only, type,
-                                                ospf_instance_id, table);
+                                                ospf_instance_id, table, &ctx);
                }
        } else {
                vrf_id_t vrf_id = VRF_DEFAULT;
@@ -1722,15 +1756,16 @@ DEFPY (show_route,
                        return CMD_SUCCESS;
 
                if (table_all)
-                       do_show_ip_route_all(vty, zvrf, afi,
-                                            !!fib, !!json,
-                                            tag, prefix_str ? prefix : NULL,
+                       do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag,
+                                            prefix_str ? prefix : NULL,
                                             !!supernets_only, type,
-                                            ospf_instance_id);
+                                            ospf_instance_id, &ctx);
                else
-                       do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib,
-                                        !!json, tag, prefix_str ? prefix : NULL,
-                                        !!supernets_only, type, ospf_instance_id, table);
+                       do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST,
+                                        !!fib, !!json, tag,
+                                        prefix_str ? prefix : NULL,
+                                        !!supernets_only, type,
+                                        ospf_instance_id, table, &ctx);
        }
 
        return CMD_SUCCESS;