diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 4526a14870..25e68cc081 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -55,10 +55,15 @@ static struct zebra_ns *dzns; static inline int zebra_ns_table_entry_compare(const struct zebra_ns_table *e1, const struct zebra_ns_table *e2) { - if (e1->tableid == e2->tableid) - return (e1->afi - e2->afi); - - return e1->tableid - e2->tableid; + if (e1->tableid < e2->tableid) + return -1; + if (e1->tableid > e2->tableid) + return 1; + if (e1->ns_id < e2->ns_id) + return -1; + if (e1->ns_id > e2->ns_id) + return 1; + return (e1->afi - e2->afi); } static int logicalrouter_config_write(struct vty *vty); @@ -177,6 +182,7 @@ struct route_table *zebra_ns_find_table(struct zebra_ns *zns, uint32_t tableid, memset(&finder, 0, sizeof(finder)); finder.afi = afi; finder.tableid = tableid; + finder.ns_id = zns->ns_id; znst = RB_FIND(zebra_ns_table_head, &zns->ns_tables, &finder); if (znst) @@ -193,9 +199,11 @@ unsigned long zebra_ns_score_proto(uint8_t proto, unsigned short instance) zns = zebra_ns_lookup(NS_DEFAULT); - RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables) + RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables) { + if (znst->ns_id != NS_DEFAULT) + continue; cnt += rib_score_proto_table(proto, instance, znst->table); - + } return cnt; } @@ -206,8 +214,11 @@ void zebra_ns_sweep_route(void) zns = zebra_ns_lookup(NS_DEFAULT); - RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables) + RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables) { + if (znst->ns_id != NS_DEFAULT) + continue; rib_sweep_table(znst->table); + } } struct route_table *zebra_ns_get_table(struct zebra_ns *zns, @@ -221,6 +232,7 @@ struct route_table *zebra_ns_get_table(struct zebra_ns *zns, memset(&finder, 0, sizeof(finder)); finder.afi = afi; finder.tableid = tableid; + finder.ns_id = zns->ns_id; znst = RB_FIND(zebra_ns_table_head, &zns->ns_tables, &finder); if (znst) @@ -229,6 +241,7 @@ struct route_table *zebra_ns_get_table(struct zebra_ns *zns, znst = XCALLOC(MTYPE_ZEBRA_NS, sizeof(*znst)); znst->tableid = tableid; znst->afi = afi; + znst->ns_id = zns->ns_id; znst->table = (afi == AFI_IP6) ? srcdest_table_init() : route_table_init(); @@ -257,7 +270,7 @@ static void zebra_ns_free_table(struct zebra_ns_table *znst) int zebra_ns_disable(ns_id_t ns_id, void **info) { - struct zebra_ns_table *znst; + struct zebra_ns_table *znst, *tmp; struct zebra_ns *zns = (struct zebra_ns *)(*info); hash_clean(zns->rules_hash, zebra_pbr_rules_free); @@ -271,9 +284,9 @@ int zebra_ns_disable(ns_id_t ns_id, void **info) zebra_pbr_iptable_free); hash_free(zns->iptable_hash); - while (!RB_EMPTY(zebra_ns_table_head, &zns->ns_tables)) { - znst = RB_ROOT(zebra_ns_table_head, &zns->ns_tables); - + RB_FOREACH_SAFE (znst, zebra_ns_table_head, &zns->ns_tables, tmp) { + if (znst->ns_id != ns_id) + continue; RB_REMOVE(zebra_ns_table_head, &zns->ns_tables, znst); zebra_ns_free_table(znst); } diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index c93db2a764..ed70a34c0b 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -43,6 +43,7 @@ struct zebra_ns_table { uint32_t tableid; afi_t afi; + ns_id_t ns_id; struct route_table *table; }; diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 24160655d7..67b2954f35 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -49,7 +49,9 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p, struct vrf *nh_vrf; /* Lookup table. */ - table = zebra_vrf_table(afi, safi, si->vrf_id); + table = zebra_vrf_table_with_table_id(afi, safi, + si->vrf_id, + si->table_id); if (!table) return; @@ -170,10 +172,20 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p, re->metric = 0; re->mtu = 0; re->vrf_id = si->vrf_id; - re->table = - (si->vrf_id != VRF_DEFAULT) + if (!vrf_is_backend_netns()) { + re->table = + (si->vrf_id != VRF_DEFAULT) ? (zebra_vrf_lookup_by_id(si->vrf_id))->table_id : zebrad.rtm_table_default; + } else { + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(si->vrf_id); + + if (zvrf->table_id != RT_TABLE_MAIN || + zvrf->table_id != zebrad.rtm_table_default) + re->table = zvrf->table_id; + else + re->table = zebrad.rtm_table_default; + } re->nexthop_num = 0; re->tag = si->tag; @@ -290,7 +302,9 @@ void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, struct prefix nh_p; /* Lookup table. */ - table = zebra_vrf_table(afi, safi, si->vrf_id); + table = zebra_vrf_table_with_table_id(afi, safi, + si->vrf_id, + si->table_id); if (!table) return; @@ -395,7 +409,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 +460,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 +472,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 +544,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 +571,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)))) diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 341905f422..7dc47d6190 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -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); diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 46443dec4f..d443f725b0 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -328,7 +328,9 @@ int zebra_vrf_has_config(struct zebra_vrf *zvrf) } /* Lookup the routing table in a VRF based on both VRF-Id and table-id. - * NOTE: Table-id is relevant only in the Default VRF. + * NOTE: Table-id is relevant on two modes: + * - case VRF backend is default : on default VRF only + * - case VRF backend is netns : on all VRFs */ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, vrf_id_t vrf_id, @@ -346,6 +348,13 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, else table = zebra_vrf_other_route_table(afi, table_id, vrf_id); + } else if (vrf_is_backend_netns()) { + if (table_id == RT_TABLE_MAIN + || table_id == zebrad.rtm_table_default) + table = zebra_vrf_table(afi, safi, vrf_id); + else + table = zebra_vrf_other_route_table(afi, table_id, + vrf_id); } else table = zebra_vrf_table(afi, safi, vrf_id); @@ -434,7 +443,8 @@ struct zebra_vrf *zebra_vrf_alloc(void) zebra_vxlan_init_tables(zvrf); zebra_mpls_init_tables(zvrf); zebra_pw_init(zvrf); - + zvrf->table_id = RT_TABLE_MAIN; + /* by default table ID is default one */ return zvrf; } @@ -501,9 +511,16 @@ struct route_table *zebra_vrf_other_route_table(afi_t afi, uint32_t table_id, if (afi >= AFI_MAX) return NULL; - if ((vrf_id == VRF_DEFAULT) && (table_id != RT_TABLE_MAIN) + if ((table_id != RT_TABLE_MAIN) && (table_id != zebrad.rtm_table_default)) { - return zebra_ns_get_table(zns, zvrf, table_id, afi); + if (zvrf->table_id == RT_TABLE_MAIN || + zvrf->table_id == zebrad.rtm_table_default) { + /* this VRF use default table + * so in all cases, it does not use specific table + * so it is possible to configure tables in this VRF + */ + return zebra_ns_get_table(zns, zvrf, table_id, afi); + } } return zvrf->table[afi][SAFI_UNICAST]; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index a094ca585e..f7548f618f 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -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,24 @@ 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); + } + if (table_str) { + /* table configured. check consistent with vrf config + */ + if (zvrf->table_id != RT_TABLE_MAIN && + zvrf->table_id != zebrad.rtm_table_default) { + if (vty) + vty_out(vty, + "%% Table %s overlaps vrf table %u\n", + table_str, zvrf->table_id); + else + zlog_warn( + "%s: Table %s overlaps vrf table %u", + __PRETTY_FUNCTION__, + table_str, zvrf->table_id); + return CMD_WARNING_CONFIG_FAILED; + } } /* Administrative distance. */ @@ -410,6 +437,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 +516,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 +564,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 +587,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 +613,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 +637,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, @@ -713,6 +744,7 @@ DEFPY(ip_route_blackhole, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |table (1-4294967295) \ }]", NO_STR IP_STR "Establish static routes\n" @@ -725,11 +757,18 @@ DEFPY(ip_route_blackhole, "Tag value\n" "Distance value for this route\n" VRF_CMD_HELP_STR - MPLS_LABEL_HELPSTR) + MPLS_LABEL_HELPSTR + "Table to configure\n" + "The table number to configure\n") { + if (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } 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, table_str); } DEFPY(ip_route_blackhole_vrf, @@ -741,6 +780,7 @@ DEFPY(ip_route_blackhole_vrf, tag (1-4294967295) \ |(1-255)$distance \ |label WORD \ + |table (1-4294967295) \ }]", NO_STR IP_STR "Establish static routes\n" @@ -752,11 +792,18 @@ DEFPY(ip_route_blackhole_vrf, "Set tag for this route\n" "Tag value\n" "Distance value for this route\n" - MPLS_LABEL_HELPSTR) + MPLS_LABEL_HELPSTR + "Table to configure\n" + "The table number to configure\n") { VTY_DECLVAR_CONTEXT(vrf, vrf); struct zebra_vrf *zvrf = vrf->info; + if (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } /* * Coverity is complaining that prefix could * be dereferenced, but we know that prefix will @@ -765,7 +812,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, @@ -779,6 +826,7 @@ DEFPY(ip_route_address_interface, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |table (1-4294967295) \ |nexthop-vrf NAME \ }]", NO_STR IP_STR @@ -794,6 +842,8 @@ DEFPY(ip_route_address_interface, "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; @@ -811,6 +861,12 @@ DEFPY(ip_route_address_interface, return CMD_WARNING_CONFIG_FAILED; } + if (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (nexthop_vrf) nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf); else @@ -823,7 +879,8 @@ 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, + table_str); } DEFPY(ip_route_address_interface_vrf, @@ -836,6 +893,7 @@ DEFPY(ip_route_address_interface_vrf, tag (1-4294967295) \ |(1-255)$distance \ |label WORD \ + |table (1-4294967295) \ |nexthop-vrf NAME \ }]", NO_STR IP_STR @@ -850,6 +908,8 @@ DEFPY(ip_route_address_interface_vrf, "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); @@ -857,6 +917,12 @@ DEFPY(ip_route_address_interface_vrf, struct zebra_vrf *zvrf = vrf->info; struct zebra_vrf *nh_zvrf; + if (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; @@ -874,7 +940,8 @@ 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, + table_str); } DEFPY(ip_route, @@ -887,6 +954,7 @@ DEFPY(ip_route, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |table (1-4294967295) \ |nexthop-vrf NAME \ }]", NO_STR IP_STR @@ -901,12 +969,20 @@ DEFPY(ip_route, "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 (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; @@ -931,7 +1007,8 @@ 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, + table_str); } DEFPY(ip_route_vrf, @@ -943,6 +1020,7 @@ DEFPY(ip_route_vrf, tag (1-4294967295) \ |(1-255)$distance \ |label WORD \ + |table (1-4294967295) \ |nexthop-vrf NAME \ }]", NO_STR IP_STR @@ -956,13 +1034,21 @@ DEFPY(ip_route_vrf, "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); struct zebra_vrf *zvrf = vrf->info; struct zebra_vrf *nh_zvrf; - const char *flag = NULL; + + if (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (ifname && !strncasecmp(ifname, "Null0", 5)) { flag = "Null0"; ifname = NULL; @@ -980,7 +1066,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. */ @@ -1696,6 +1783,35 @@ DEFPY (show_route_table, return CMD_SUCCESS; } +DEFPY (show_route_table_vrf, + show_route_table_vrf_cmd, + "show route table (1-4294967295)$table vrf NAME$vrf_name [json$json]", + SHOW_STR + IP_STR + IP6_STR + "IP routing table\n" + "Table to display\n" + "The table number to display, if available\n" + VRF_CMD_HELP_STR + JSON_STR) +{ + afi_t afi = ipv4 ? AFI_IP : AFI_IP6; + struct zebra_vrf *zvrf; + struct route_table *t; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (vrf_name) + VRF_GET_ID(vrf_id, vrf_name); + zvrf = zebra_vrf_lookup_by_id(vrf_id); + + t = zebra_ns_find_table(zvrf->zns, table, afi); + if (t) + do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false, + 0, 0, !!json); + + return CMD_SUCCESS; +} + DEFUN (show_ip_nht, show_ip_nht_cmd, "show ip nht [vrf NAME]", @@ -2258,6 +2374,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"); @@ -2324,6 +2442,11 @@ int static_config(struct vty *vty, struct zebra_vrf *zvrf, afi_t afi, vty_out(vty, " nexthop-vrf %s", si->nh_vrfname); } + /* table ID from VRF overrides configured + */ + if (si->table_id && zvrf->table_id == RT_TABLE_MAIN) + vty_out(vty, " table %u", si->table_id); + vty_out(vty, "\n"); write = 1; @@ -2340,6 +2463,7 @@ DEFPY(ipv6_route_blackhole, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |table (1-4294967295) \ }]", NO_STR IPV6_STR @@ -2354,11 +2478,19 @@ DEFPY(ipv6_route_blackhole, "Tag value\n" "Distance value for this prefix\n" VRF_CMD_HELP_STR - MPLS_LABEL_HELPSTR) + MPLS_LABEL_HELPSTR + "Table to configure\n" + "The table number to configure\n") { + if (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } + 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, table_str); } DEFPY(ipv6_route_blackhole_vrf, @@ -2369,6 +2501,7 @@ DEFPY(ipv6_route_blackhole_vrf, tag (1-4294967295) \ |(1-255)$distance \ |label WORD \ + |table (1-4294967295) \ }]", NO_STR IPV6_STR @@ -2382,11 +2515,18 @@ DEFPY(ipv6_route_blackhole_vrf, "Set tag for this route\n" "Tag value\n" "Distance value for this prefix\n" - MPLS_LABEL_HELPSTR) + MPLS_LABEL_HELPSTR + "Table to configure\n" + "The table number to configure\n") { VTY_DECLVAR_CONTEXT(vrf, vrf); struct zebra_vrf *zvrf = vrf->info; + if (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } /* * Coverity is complaining that prefix could * be dereferenced, but we know that prefix will @@ -2395,7 +2535,8 @@ 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, + table_str); } DEFPY(ipv6_route_address_interface, @@ -2408,6 +2549,7 @@ DEFPY(ipv6_route_address_interface, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |table (1-4294967295) \ |nexthop-vrf NAME \ }]", NO_STR @@ -2423,11 +2565,19 @@ DEFPY(ipv6_route_address_interface, "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; + if (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } + zvrf = zebra_vty_get_unknown_vrf(vty, vrf); if (!zvrf) { vty_out(vty, "%% vrf %s is not defined\n", vrf); @@ -2446,7 +2596,8 @@ 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, + table_str); } DEFPY(ipv6_route_address_interface_vrf, @@ -2458,6 +2609,7 @@ DEFPY(ipv6_route_address_interface_vrf, tag (1-4294967295) \ |(1-255)$distance \ |label WORD \ + |table (1-4294967295) \ |nexthop-vrf NAME \ }]", NO_STR @@ -2472,12 +2624,20 @@ DEFPY(ipv6_route_address_interface_vrf, "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 (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (nexthop_vrf) nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf); else @@ -2490,7 +2650,8 @@ 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, + table_str); } DEFPY(ipv6_route, @@ -2502,6 +2663,7 @@ DEFPY(ipv6_route, |(1-255)$distance \ |vrf NAME \ |label WORD \ + |table (1-4294967295) \ |nexthop-vrf NAME \ }]", NO_STR @@ -2517,11 +2679,19 @@ DEFPY(ipv6_route, "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; + if (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } + zvrf = zebra_vty_get_unknown_vrf(vty, vrf); if (!zvrf) { vty_out(vty, "%% vrf %s is not defined\n", vrf); @@ -2540,7 +2710,8 @@ 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, + table_str); } DEFPY(ipv6_route_vrf, @@ -2551,6 +2722,7 @@ DEFPY(ipv6_route_vrf, tag (1-4294967295) \ |(1-255)$distance \ |label WORD \ + |table (1-4294967295) \ |nexthop-vrf NAME \ }]", NO_STR @@ -2565,12 +2737,20 @@ DEFPY(ipv6_route_vrf, "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 (table_str && !vrf_is_backend_netns()) { + vty_out(vty, + "%% table param only available when running on netns-based vrfs\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (nexthop_vrf) nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf); else @@ -2583,7 +2763,8 @@ 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, + table_str); } /* @@ -2687,6 +2868,9 @@ DEFUN (show_vrf, struct vrf *vrf; struct zebra_vrf *zvrf; + if (vrf_is_backend_netns()) + vty_out(vty, "netns-based vrfs\n"); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { if (!(zvrf = vrf->info)) continue; @@ -3734,11 +3918,13 @@ void zebra_vty_init(void) 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_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); @@ -3750,6 +3936,8 @@ void zebra_vty_init(void) install_element(VIEW_NODE, &show_vrf_vni_cmd); install_element(VIEW_NODE, &show_route_cmd); install_element(VIEW_NODE, &show_route_table_cmd); + if (vrf_is_backend_netns()) + install_element(VIEW_NODE, &show_route_table_vrf_cmd); install_element(VIEW_NODE, &show_route_detail_cmd); install_element(VIEW_NODE, &show_route_summary_cmd); install_element(VIEW_NODE, &show_ip_nht_cmd); @@ -3760,11 +3948,14 @@ 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_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);