]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: add table keyword to route configuration vty command
authorPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 28 Mar 2018 09:31:22 +0000 (11:31 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 1 Jun 2018 13:24:13 +0000 (15:24 +0200)
Add the table keyword for all ip route/ip mroute/ipv6 route commands
that are available. Also, the main structure is being added a table
identifier.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
zebra/zebra_static.c
zebra/zebra_static.h
zebra/zebra_vty.c

index 24160655d7a1fed5a6e482692fece341d096bce8..84d6edec3ad8d91c2da0f07884f0c0f9846ba9ce 100644 (file)
@@ -395,7 +395,8 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
                     const char *ifname, enum static_blackhole_type bh_type,
                     route_tag_t tag, uint8_t distance, struct zebra_vrf *zvrf,
                     struct zebra_vrf *nh_zvrf,
-                    struct static_nh_label *snh_label)
+                    struct static_nh_label *snh_label,
+                    uint32_t table_id)
 {
        struct route_node *rn;
        struct static_route *si;
@@ -445,7 +446,7 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
        if (update)
                static_delete_route(afi, safi, type, p, src_p, gate, ifname,
                                    update->tag, update->distance, zvrf,
-                                   &update->snh_label);
+                                   &update->snh_label, table_id);
 
        /* Make new static route structure. */
        si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route));
@@ -457,6 +458,7 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
        si->vrf_id = zvrf_id(zvrf);
        si->nh_vrf_id = zvrf_id(nh_zvrf);
        strcpy(si->nh_vrfname, nh_zvrf->vrf->name);
+       si->table_id = table_id;
 
        if (ifname)
                strlcpy(si->ifname, ifname, sizeof(si->ifname));
@@ -528,7 +530,8 @@ int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
                        struct prefix_ipv6 *src_p, union g_addr *gate,
                        const char *ifname, route_tag_t tag, uint8_t distance,
                        struct zebra_vrf *zvrf,
-                       struct static_nh_label *snh_label)
+                       struct static_nh_label *snh_label,
+                       uint32_t table_id)
 {
        struct route_node *rn;
        struct static_route *si;
@@ -554,6 +557,7 @@ int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
                                && IPV6_ADDR_SAME(gate, &si->addr.ipv6))))
                    && (!strcmp(ifname ? ifname : "", si->ifname))
                    && (!tag || (tag == si->tag))
+                   && (table_id == si->table_id)
                    && (!snh_label->num_labels
                        || !memcmp(&si->snh_label, snh_label,
                                   sizeof(struct static_nh_label))))
index 341905f422b7119c6fae213e1222b08dd9efb4fe..7dc47d6190d5227c559a4e9138546ec005bb3200 100644 (file)
@@ -77,6 +77,9 @@ struct static_route {
 
        /* Label information */
        struct static_nh_label snh_label;
+
+       /* Table Information */
+       uint32_t table_id;
 };
 
 extern void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
@@ -92,14 +95,16 @@ extern int static_add_route(afi_t, safi_t safi, uint8_t type, struct prefix *p,
                            enum static_blackhole_type bh_type, route_tag_t tag,
                            uint8_t distance, struct zebra_vrf *zvrf,
                            struct zebra_vrf *nh_zvrf,
-                           struct static_nh_label *snh_label);
+                           struct static_nh_label *snh_label,
+                           uint32_t table_id);
 
 extern int static_delete_route(afi_t, safi_t safi, uint8_t type,
                               struct prefix *p, struct prefix_ipv6 *src_p,
                               union g_addr *gate, const char *ifname,
                               route_tag_t tag, uint8_t distance,
                               struct zebra_vrf *zvrf,
-                              struct static_nh_label *snh_label);
+                              struct static_nh_label *snh_label,
+                              uint32_t table_id);
 
 extern void static_ifindex_update(struct interface *ifp, bool up);
 
index a094ca585e8d07dc3e6f326b967216f0ce76750b..4c2d6002b915a9213083c634d0cb0c4437394f23 100644 (file)
@@ -92,6 +92,7 @@ struct static_hold_route {
        char *tag_str;
        char *distance_str;
        char *label_str;
+       char *table_str;
 
        /* processed & masked destination, used for config display */
        struct prefix dest;
@@ -193,6 +194,11 @@ static int static_list_compare(void *arg1, void *arg2)
        if (ret)
                return ret;
 
+       ret = static_list_compare_helper(shr1->table_str,
+                                        shr2->table_str);
+       if (ret)
+               return ret;
+
        return static_list_compare_helper(shr1->label_str, shr2->label_str);
 }
 
@@ -203,7 +209,8 @@ static int zebra_static_route_holdem(
        safi_t safi, const char *negate, struct prefix *dest,
        const char *dest_str, const char *mask_str, const char *src_str,
        const char *gate_str, const char *ifname, const char *flag_str,
-       const char *tag_str, const char *distance_str, const char *label_str)
+       const char *tag_str, const char *distance_str, const char *label_str,
+       const char *table_str)
 {
        struct static_hold_route *shr, *lookup;
        struct listnode *node;
@@ -236,6 +243,8 @@ static int zebra_static_route_holdem(
                shr->distance_str = XSTRDUP(MTYPE_STATIC_ROUTE, distance_str);
        if (label_str)
                shr->label_str = XSTRDUP(MTYPE_STATIC_ROUTE, label_str);
+       if (table_str)
+               shr->table_str = XSTRDUP(MTYPE_STATIC_ROUTE, table_str);
 
        for (ALL_LIST_ELEMENTS_RO(static_list, node, lookup)) {
                if (static_list_compare(shr, lookup) == 0)
@@ -272,7 +281,7 @@ static int zebra_static_route_leak(
        afi_t afi, safi_t safi, const char *negate, const char *dest_str,
        const char *mask_str, const char *src_str, const char *gate_str,
        const char *ifname, const char *flag_str, const char *tag_str,
-       const char *distance_str, const char *label_str)
+       const char *distance_str, const char *label_str, const char *table_str)
 {
        int ret;
        uint8_t distance;
@@ -285,6 +294,7 @@ static int zebra_static_route_leak(
        route_tag_t tag = 0;
        uint8_t type;
        struct static_nh_label snh_label;
+       uint32_t table_id = 0;
 
        ret = str2prefix(dest_str, &p);
        if (ret <= 0) {
@@ -343,7 +353,7 @@ static int zebra_static_route_leak(
                return zebra_static_route_holdem(
                        zvrf, nh_zvrf, afi, safi, negate, &p, dest_str,
                        mask_str, src_str, gate_str, ifname, flag_str, tag_str,
-                       distance_str, label_str);
+                       distance_str, label_str, table_str);
        }
 
        /* Administrative distance. */
@@ -410,6 +420,9 @@ static int zebra_static_route_leak(
                        return CMD_WARNING_CONFIG_FAILED;
                }
        }
+       /* TableID */
+       if (table_str)
+               table_id = atol(table_str);
 
        /* Null0 static route.  */
        if (ifname != NULL) {
@@ -486,12 +499,12 @@ static int zebra_static_route_leak(
        if (!negate) {
                static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
                                 bh_type, tag, distance, zvrf, nh_zvrf,
-                                &snh_label);
+                                &snh_label, table_id);
                /* Mark as having FRR configuration */
                vrf_set_user_cfged(zvrf->vrf);
        } else {
                static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
-                                   tag, distance, zvrf, &snh_label);
+                                   tag, distance, zvrf, &snh_label, table_id);
                /* If no other FRR config for this VRF, mark accordingly. */
                if (!zebra_vrf_has_config(zvrf))
                        vrf_reset_user_cfged(zvrf->vrf);
@@ -534,7 +547,7 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
                              const char *gate_str, const char *ifname,
                              const char *flag_str, const char *tag_str,
                              const char *distance_str, const char *vrf_name,
-                             const char *label_str)
+                             const char *label_str, const char *table_str)
 {
        struct zebra_vrf *zvrf;
 
@@ -557,7 +570,8 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
        }
        return zebra_static_route_leak(
                vty, zvrf, zvrf, afi, safi, negate, dest_str, mask_str, src_str,
-               gate_str, ifname, flag_str, tag_str, distance_str, label_str);
+               gate_str, ifname, flag_str, tag_str, distance_str, label_str,
+               table_str);
 }
 
 void static_config_install_delayed_routes(struct zebra_vrf *zvrf)
@@ -582,7 +596,7 @@ void static_config_install_delayed_routes(struct zebra_vrf *zvrf)
                        NULL, ozvrf, nh_zvrf, shr->afi, shr->safi, NULL,
                        shr->dest_str, shr->mask_str, shr->src_str,
                        shr->gate_str, shr->ifname, shr->flag_str, shr->tag_str,
-                       shr->distance_str, shr->label_str);
+                       shr->distance_str, shr->label_str, shr->table_str);
 
                if (installed != CMD_SUCCESS)
                        zlog_debug(
@@ -606,7 +620,7 @@ DEFPY (ip_mroute_dist,
 {
        return zebra_static_route(vty, AFI_IP, SAFI_MULTICAST, no, prefix_str,
                                  NULL, NULL, gate_str, ifname, NULL, NULL,
-                                 distance_str, NULL, NULL);
+                                 distance_str, NULL, NULL, NULL);
 }
 
 DEFUN (ip_multicast_mode,
@@ -729,7 +743,40 @@ DEFPY(ip_route_blackhole,
 {
        return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
                                  mask_str, NULL, NULL, NULL, flag, tag_str,
-                                 distance_str, vrf, label);
+                                 distance_str, vrf, label, NULL);
+}
+
+/* Static route configuration.  */
+DEFPY(ip_route_blackhole_namespace,
+      ip_route_blackhole_namespace_cmd,
+      "[no] ip route\
+       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>                        \
+       <reject|blackhole>$flag                                               \
+       [{                                                                    \
+         tag (1-4294967295)                                                  \
+         |(1-255)$distance                                                   \
+         |vrf NAME                                                           \
+         |label WORD                                                         \
+         |table (1-4294967295)                                               \
+          }]",
+      NO_STR IP_STR
+      "Establish static routes\n"
+      "IP destination prefix (e.g. 10.0.0.0/8)\n"
+      "IP destination prefix\n"
+      "IP destination prefix mask\n"
+      "Emit an ICMP unreachable when matched\n"
+      "Silently discard pkts when matched\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this route\n"
+      VRF_CMD_HELP_STR
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n")
+{
+       return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
+                                 mask_str, NULL, NULL, NULL, flag, tag_str,
+                                 distance_str, vrf, label, table_str);
 }
 
 DEFPY(ip_route_blackhole_vrf,
@@ -757,6 +804,45 @@ DEFPY(ip_route_blackhole_vrf,
        VTY_DECLVAR_CONTEXT(vrf, vrf);
        struct zebra_vrf *zvrf = vrf->info;
 
+       /*
+        * Coverity is complaining that prefix could
+        * be dereferenced, but we know that prefix will
+        * valid.  Add an assert to make it happy
+        */
+       assert(prefix);
+       return zebra_static_route_leak(vty, zvrf, zvrf, AFI_IP, SAFI_UNICAST,
+                              no, prefix, mask_str, NULL, NULL, NULL,
+                              flag, tag_str, distance_str, label, NULL);
+}
+
+DEFPY(ip_route_blackhole_namespace_vrf,
+      ip_route_blackhole_namespace_vrf_cmd,
+      "[no] ip route\
+       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>                        \
+       <reject|blackhole>$flag                                               \
+       [{                                                                    \
+         tag (1-4294967295)                                                  \
+         |(1-255)$distance                                                   \
+         |label WORD                                                         \
+         |table (1-4294967295)                                               \
+          }]",
+      NO_STR IP_STR
+      "Establish static routes\n"
+      "IP destination prefix (e.g. 10.0.0.0/8)\n"
+      "IP destination prefix\n"
+      "IP destination prefix mask\n"
+      "Emit an ICMP unreachable when matched\n"
+      "Silently discard pkts when matched\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this route\n"
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n")
+{
+       VTY_DECLVAR_CONTEXT(vrf, vrf);
+       struct zebra_vrf *zvrf = vrf->info;
+
        /*
         * Coverity is complaining that prefix could
         * be dereferenced, but we know that prefix will
@@ -765,7 +851,7 @@ DEFPY(ip_route_blackhole_vrf,
        assert(prefix);
        return zebra_static_route_leak(vty, zvrf, zvrf, AFI_IP, SAFI_UNICAST,
                                       no, prefix, mask_str, NULL, NULL, NULL,
-                                      flag, tag_str, distance_str, label);
+                                      flag, tag_str, distance_str, label, table_str);
 }
 
 DEFPY(ip_route_address_interface,
@@ -823,7 +909,70 @@ DEFPY(ip_route_address_interface,
 
        return zebra_static_route_leak(
                vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
-               NULL, gate_str, ifname, flag, tag_str, distance_str, label);
+               NULL, gate_str, ifname, flag, tag_str, distance_str, label,
+               NULL);
+}
+
+DEFPY(ip_route_address_interface_namespace,
+      ip_route_address_interface_namespace_cmd,
+      "[no] ip route\
+       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+       A.B.C.D$gate                                   \
+       INTERFACE$ifname                               \
+       [{                                             \
+         tag (1-4294967295)                           \
+         |(1-255)$distance                            \
+         |vrf NAME                                    \
+         |label WORD                                  \
+         |table (1-4294967295)                        \
+         |nexthop-vrf NAME                            \
+          }]",
+      NO_STR IP_STR
+      "Establish static routes\n"
+      "IP destination prefix (e.g. 10.0.0.0/8)\n"
+      "IP destination prefix\n"
+      "IP destination prefix mask\n"
+      "IP gateway address\n"
+      "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
+      null route.\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this route\n"
+      VRF_CMD_HELP_STR
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n"
+      VRF_CMD_HELP_STR)
+{
+       struct zebra_vrf *zvrf;
+       struct zebra_vrf *nh_zvrf;
+
+       const char *flag = NULL;
+       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
+               flag = "Null0";
+               ifname = NULL;
+       }
+
+       zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
+       if (!zvrf) {
+               vty_out(vty, "%% vrf %s is not defined\n", vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       if (nexthop_vrf)
+               nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
+       else
+               nh_zvrf = zvrf;
+
+       if (!nh_zvrf) {
+               vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       return zebra_static_route_leak(
+               vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
+               NULL, gate_str, ifname, flag, tag_str, distance_str, label,
+               table_str);
 }
 
 DEFPY(ip_route_address_interface_vrf,
@@ -874,7 +1023,63 @@ DEFPY(ip_route_address_interface_vrf,
 
        return zebra_static_route_leak(
                vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
-               NULL, gate_str, ifname, flag, tag_str, distance_str, label);
+               NULL, gate_str, ifname, flag, tag_str, distance_str, label,
+               NULL);
+}
+
+DEFPY(ip_route_address_interface_namespace_vrf,
+      ip_route_address_interface_namespace_vrf_cmd,
+      "[no] ip route\
+       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+       A.B.C.D$gate                                   \
+       INTERFACE$ifname                               \
+       [{                                             \
+         tag (1-4294967295)                           \
+         |(1-255)$distance                            \
+         |label WORD                                  \
+         |table (1-4294967295)                        \
+         |nexthop-vrf NAME                            \
+          }]",
+      NO_STR IP_STR
+      "Establish static routes\n"
+      "IP destination prefix (e.g. 10.0.0.0/8)\n"
+      "IP destination prefix\n"
+      "IP destination prefix mask\n"
+      "IP gateway address\n"
+      "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
+      null route.\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this route\n"
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n"
+      VRF_CMD_HELP_STR)
+{
+       VTY_DECLVAR_CONTEXT(vrf, vrf);
+       const char *flag = NULL;
+       struct zebra_vrf *zvrf = vrf->info;
+       struct zebra_vrf *nh_zvrf;
+
+       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
+               flag = "Null0";
+               ifname = NULL;
+       }
+
+       if (nexthop_vrf)
+               nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
+       else
+               nh_zvrf = zvrf;
+
+       if (!nh_zvrf) {
+               vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       return zebra_static_route_leak(
+               vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
+               NULL, gate_str, ifname, flag, tag_str, distance_str, label,
+               table_str);
 }
 
 DEFPY(ip_route,
@@ -931,7 +1136,119 @@ DEFPY(ip_route,
 
        return zebra_static_route_leak(
                vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
-               NULL, gate_str, ifname, flag, tag_str, distance_str, label);
+               NULL, gate_str, ifname, flag, tag_str, distance_str, label,
+               NULL);
+}
+
+DEFPY(ip_route_namespace,
+      ip_route_namespace_cmd,
+      "[no] ip route\
+       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+       <A.B.C.D$gate|INTERFACE$ifname>                \
+       [{                                             \
+         tag (1-4294967295)                           \
+         |(1-255)$distance                            \
+         |vrf NAME                                    \
+         |label WORD                                  \
+         |table (1-4294967295)                        \
+         |nexthop-vrf NAME                            \
+          }]",
+      NO_STR IP_STR
+      "Establish static routes\n"
+      "IP destination prefix (e.g. 10.0.0.0/8)\n"
+      "IP destination prefix\n"
+      "IP destination prefix mask\n"
+      "IP gateway address\n"
+      "IP gateway interface name\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this route\n"
+      VRF_CMD_HELP_STR
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n"
+      VRF_CMD_HELP_STR)
+{
+       struct zebra_vrf *zvrf;
+       struct zebra_vrf *nh_zvrf;
+       const char *flag = NULL;
+
+       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
+               flag = "Null0";
+               ifname = NULL;
+       }
+
+       zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
+       if (!zvrf) {
+               vty_out(vty, "%% vrf %s is not defined\n", vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       if (nexthop_vrf)
+               nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
+       else
+               nh_zvrf = zvrf;
+
+       if (!nh_zvrf) {
+               vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+
+       return zebra_static_route_leak(
+               vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
+               NULL, gate_str, ifname, flag, tag_str, distance_str, label,
+               table_str);
+}
+
+DEFPY(ip_route_namespace_vrf,
+      ip_route_namespace_vrf_cmd,
+      "[no] ip route\
+       <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+       <A.B.C.D$gate|INTERFACE$ifname>                \
+       [{                                             \
+         tag (1-4294967295)                           \
+         |(1-255)$distance                            \
+         |label WORD                                  \
+         |nexthop-vrf NAME                            \
+          }]",
+      NO_STR IP_STR
+      "Establish static routes\n"
+      "IP destination prefix (e.g. 10.0.0.0/8)\n"
+      "IP destination prefix\n"
+      "IP destination prefix mask\n"
+      "IP gateway address\n"
+      "IP gateway interface name\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this route\n"
+      MPLS_LABEL_HELPSTR
+      VRF_CMD_HELP_STR)
+{
+       VTY_DECLVAR_CONTEXT(vrf, vrf);
+       struct zebra_vrf *zvrf = vrf->info;
+       struct zebra_vrf *nh_zvrf;
+
+       const char *flag = NULL;
+       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
+               flag = "Null0";
+               ifname = NULL;
+       }
+
+       if (nexthop_vrf)
+               nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
+       else
+               nh_zvrf = zvrf;
+
+       if (!nh_zvrf) {
+               vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       return zebra_static_route_leak(
+               vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
+               NULL, gate_str, ifname, flag, tag_str, distance_str, label,
+               NULL);
 }
 
 DEFPY(ip_route_vrf,
@@ -980,7 +1297,8 @@ DEFPY(ip_route_vrf,
 
        return zebra_static_route_leak(
                vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
-               NULL, gate_str, ifname, flag, tag_str, distance_str, label);
+               NULL, gate_str, ifname, flag, tag_str, distance_str, label,
+               NULL);
 }
 
 /* New RIB.  Detailed information for IPv4 route. */
@@ -2258,6 +2576,8 @@ int static_config(struct vty *vty, struct zebra_vrf *zvrf, afi_t afi,
                        vty_out(vty, "%s ", shr->distance_str);
                if (shr->label_str)
                        vty_out(vty, "label %s ", shr->label_str);
+               if (shr->table_str)
+                       vty_out(vty, "table %s ", shr->table_str);
                if (strcmp(shr->vrf_name, shr->nhvrf_name) != 0)
                        vty_out(vty, "nexthop-vrf %s", shr->nhvrf_name);
                vty_out(vty, "\n");
@@ -2358,7 +2678,40 @@ DEFPY(ipv6_route_blackhole,
 {
        return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
                                  NULL, from_str, NULL, NULL, flag, tag_str,
-                                 distance_str, vrf, label);
+                                 distance_str, vrf, label, NULL);
+}
+
+DEFPY(ipv6_route_blackhole_namespace,
+      ipv6_route_blackhole_namespace_cmd,
+      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+          <Null0|reject|blackhole>$flag                    \
+          [{                                               \
+            tag (1-4294967295)                             \
+            |(1-255)$distance                              \
+            |vrf NAME                                      \
+            |label WORD                                    \
+            |table (1-4294967295)                          \
+          }]",
+      NO_STR
+      IPV6_STR
+      "Establish static routes\n"
+      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+      "IPv6 source-dest route\n"
+      "IPv6 source prefix\n"
+      "Null interface\n"
+      "Emit an ICMP unreachable when matched\n"
+      "Silently discard pkts when matched\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this prefix\n"
+      VRF_CMD_HELP_STR
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n")
+{
+       return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
+                                 NULL, from_str, NULL, NULL, flag, tag_str,
+                                 distance_str, vrf, label, table_str);
 }
 
 DEFPY(ipv6_route_blackhole_vrf,
@@ -2395,7 +2748,49 @@ DEFPY(ipv6_route_blackhole_vrf,
        assert(prefix);
        return zebra_static_route_leak(
                vty, zvrf, zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
-               from_str, NULL, NULL, flag, tag_str, distance_str, label);
+               from_str, NULL, NULL, flag, tag_str, distance_str, label,
+               NULL);
+}
+
+DEFPY(ipv6_route_blackhole_namespace_vrf,
+      ipv6_route_blackhole_namespace_vrf_cmd,
+      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+          <Null0|reject|blackhole>$flag                    \
+          [{                                               \
+            tag (1-4294967295)                             \
+            |(1-255)$distance                              \
+            |label WORD                                    \
+            |table (1-4294967295)                          \
+          }]",
+      NO_STR
+      IPV6_STR
+      "Establish static routes\n"
+      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+      "IPv6 source-dest route\n"
+      "IPv6 source prefix\n"
+      "Null interface\n"
+      "Emit an ICMP unreachable when matched\n"
+      "Silently discard pkts when matched\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this prefix\n"
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n")
+{
+       VTY_DECLVAR_CONTEXT(vrf, vrf);
+       struct zebra_vrf *zvrf = vrf->info;
+
+       /*
+        * Coverity is complaining that prefix could
+        * be dereferenced, but we know that prefix will
+        * valid.  Add an assert to make it happy
+        */
+       assert(prefix);
+       return zebra_static_route_leak(
+               vty, zvrf, zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
+               from_str, NULL, NULL, flag, tag_str, distance_str, label,
+               table_str);
 }
 
 DEFPY(ipv6_route_address_interface,
@@ -2446,7 +2841,63 @@ DEFPY(ipv6_route_address_interface,
 
        return zebra_static_route_leak(
                vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
-               from_str, gate_str, ifname, NULL, tag_str, distance_str, label);
+               from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
+               NULL);
+}
+
+DEFPY(ipv6_route_address_interface_namespace,
+      ipv6_route_address_interface_namespace_cmd,
+      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+          X:X::X:X$gate                                    \
+          INTERFACE$ifname                                 \
+          [{                                               \
+            tag (1-4294967295)                             \
+            |(1-255)$distance                              \
+            |vrf NAME                                      \
+            |label WORD                                    \
+           |table (1-4294967295)                          \
+            |nexthop-vrf NAME                              \
+          }]",
+      NO_STR
+      IPV6_STR
+      "Establish static routes\n"
+      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+      "IPv6 source-dest route\n"
+      "IPv6 source prefix\n"
+      "IPv6 gateway address\n"
+      "IPv6 gateway interface name\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this prefix\n"
+      VRF_CMD_HELP_STR
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n"
+      VRF_CMD_HELP_STR)
+{
+       struct zebra_vrf *zvrf;
+       struct zebra_vrf *nh_zvrf;
+
+       zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
+       if (!zvrf) {
+               vty_out(vty, "%% vrf %s is not defined\n", vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       if (nexthop_vrf)
+               nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
+       else
+               nh_zvrf = zvrf;
+
+       if (!nh_zvrf) {
+               vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       return zebra_static_route_leak(
+               vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
+               from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
+               table_str);
 }
 
 DEFPY(ipv6_route_address_interface_vrf,
@@ -2490,7 +2941,56 @@ DEFPY(ipv6_route_address_interface_vrf,
 
        return zebra_static_route_leak(
                vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
-               from_str, gate_str, ifname, NULL, tag_str, distance_str, label);
+               from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
+               NULL);
+}
+
+DEFPY(ipv6_route_address_interface_namespace_vrf,
+      ipv6_route_address_interface_namespace_vrf_cmd,
+      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+          X:X::X:X$gate                                    \
+          INTERFACE$ifname                                 \
+          [{                                               \
+            tag (1-4294967295)                             \
+            |(1-255)$distance                              \
+            |label WORD                                    \
+           |table (1-4294967295)                          \
+            |nexthop-vrf NAME                              \
+          }]",
+      NO_STR
+      IPV6_STR
+      "Establish static routes\n"
+      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+      "IPv6 source-dest route\n"
+      "IPv6 source prefix\n"
+      "IPv6 gateway address\n"
+      "IPv6 gateway interface name\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this prefix\n"
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n"
+      VRF_CMD_HELP_STR)
+{
+       VTY_DECLVAR_CONTEXT(vrf, vrf);
+       struct zebra_vrf *zvrf = vrf->info;
+       struct zebra_vrf *nh_zvrf;
+
+       if (nexthop_vrf)
+               nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
+       else
+               nh_zvrf = zvrf;
+
+       if (!nh_zvrf) {
+               vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       return zebra_static_route_leak(
+               vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
+               from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
+               table_str);
 }
 
 DEFPY(ipv6_route,
@@ -2540,7 +3040,62 @@ DEFPY(ipv6_route,
 
        return zebra_static_route_leak(
                vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
-               from_str, gate_str, ifname, NULL, tag_str, distance_str, label);
+               from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
+               NULL);
+}
+
+DEFPY(ipv6_route_namespace,
+      ipv6_route_namespace_cmd,
+      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+          <X:X::X:X$gate|INTERFACE$ifname>                 \
+          [{                                               \
+            tag (1-4294967295)                             \
+            |(1-255)$distance                              \
+            |vrf NAME                                      \
+            |label WORD                                    \
+           |table (1-4294967295)                          \
+            |nexthop-vrf NAME                              \
+          }]",
+      NO_STR
+      IPV6_STR
+      "Establish static routes\n"
+      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+      "IPv6 source-dest route\n"
+      "IPv6 source prefix\n"
+      "IPv6 gateway address\n"
+      "IPv6 gateway interface name\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this prefix\n"
+      VRF_CMD_HELP_STR
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n"
+      VRF_CMD_HELP_STR)
+{
+       struct zebra_vrf *zvrf;
+       struct zebra_vrf *nh_zvrf;
+
+       zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
+       if (!zvrf) {
+               vty_out(vty, "%% vrf %s is not defined\n", vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       if (nexthop_vrf)
+               nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
+       else
+               nh_zvrf = zvrf;
+
+       if (!nh_zvrf) {
+               vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       return zebra_static_route_leak(
+               vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
+               from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
+               table_str);
 }
 
 DEFPY(ipv6_route_vrf,
@@ -2583,7 +3138,55 @@ DEFPY(ipv6_route_vrf,
 
        return zebra_static_route_leak(
                vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
-               from_str, gate_str, ifname, NULL, tag_str, distance_str, label);
+               from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
+               NULL);
+}
+
+DEFPY(ipv6_route_namespace_vrf,
+      ipv6_route_namespace_vrf_cmd,
+      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+          <X:X::X:X$gate|INTERFACE$ifname>                 \
+          [{                                               \
+            tag (1-4294967295)                             \
+            |(1-255)$distance                              \
+            |label WORD                                    \
+           |table (1-4294967295)                          \
+            |nexthop-vrf NAME                              \
+          }]",
+      NO_STR
+      IPV6_STR
+      "Establish static routes\n"
+      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+      "IPv6 source-dest route\n"
+      "IPv6 source prefix\n"
+      "IPv6 gateway address\n"
+      "IPv6 gateway interface name\n"
+      "Set tag for this route\n"
+      "Tag value\n"
+      "Distance value for this prefix\n"
+      MPLS_LABEL_HELPSTR
+      "Table to configure\n"
+      "The table number to configure\n"
+      VRF_CMD_HELP_STR)
+{
+       VTY_DECLVAR_CONTEXT(vrf, vrf);
+       struct zebra_vrf *zvrf = vrf->info;
+       struct zebra_vrf *nh_zvrf;
+
+       if (nexthop_vrf)
+               nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
+       else
+               nh_zvrf = zvrf;
+
+       if (!nh_zvrf) {
+               vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       return zebra_static_route_leak(
+               vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
+               from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
+               table_str);
 }
 
 /*
@@ -3733,12 +4336,26 @@ void zebra_vty_init(void)
        install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
        install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
        install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
-       install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
-       install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
-       install_element(CONFIG_NODE, &ip_route_address_interface_cmd);
-       install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
-       install_element(CONFIG_NODE, &ip_route_cmd);
-       install_element(VRF_NODE, &ip_route_vrf_cmd);
+       if (vrf_is_backend_netns()) {
+               install_element(CONFIG_NODE, &ip_route_blackhole_namespace_cmd);
+               install_element(CONFIG_NODE,
+                               &ip_route_address_interface_namespace_cmd);
+               install_element(CONFIG_NODE, &ip_route_namespace_cmd);
+               install_element(VRF_NODE,
+                               &ip_route_blackhole_namespace_vrf_cmd);
+               install_element(VRF_NODE,
+                               &ip_route_address_interface_namespace_vrf_cmd);
+               install_element(VRF_NODE, &ip_route_namespace_vrf_cmd);
+       } else {
+               install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
+               install_element(CONFIG_NODE,
+                               &ip_route_address_interface_cmd);
+               install_element(CONFIG_NODE, &ip_route_cmd);
+               install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
+               install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
+               install_element(VRF_NODE, &ip_route_vrf_cmd);
+       }
+
        install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
        install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
        install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
@@ -3760,12 +4377,30 @@ void zebra_vty_init(void)
        install_element(VIEW_NODE, &show_ip_rpf_cmd);
        install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
 
-       install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd);
-       install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
-       install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd);
-       install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd);
-       install_element(CONFIG_NODE, &ipv6_route_cmd);
-       install_element(VRF_NODE, &ipv6_route_vrf_cmd);
+       if (vrf_is_backend_netns()) {
+               install_element(CONFIG_NODE,
+                               &ipv6_route_blackhole_namespace_cmd);
+               install_element(CONFIG_NODE,
+                               &ipv6_route_address_interface_namespace_cmd);
+               install_element(CONFIG_NODE,
+                               &ipv6_route_namespace_cmd);
+               install_element(VRF_NODE,
+                               &ipv6_route_blackhole_namespace_vrf_cmd);
+
+               install_element(VRF_NODE,
+                     &ipv6_route_address_interface_namespace_vrf_cmd);
+               install_element(VRF_NODE, &ipv6_route_namespace_vrf_cmd);
+       } else {
+               install_element(CONFIG_NODE,
+                               &ipv6_route_blackhole_cmd);
+               install_element(CONFIG_NODE,
+                               &ipv6_route_address_interface_cmd);
+               install_element(CONFIG_NODE, &ipv6_route_cmd);
+               install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
+               install_element(VRF_NODE,
+                               &ipv6_route_address_interface_vrf_cmd);
+               install_element(VRF_NODE, &ipv6_route_vrf_cmd);
+       }
        install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
        install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
        install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);