diff options
| -rw-r--r-- | bgpd/Makefile.am | 2 | ||||
| -rw-r--r-- | bgpd/bgp_attr.c | 3 | ||||
| -rw-r--r-- | bgpd/bgp_network.c | 4 | ||||
| -rw-r--r-- | bgpd/bgp_vty.c | 50 | ||||
| -rw-r--r-- | bgpd/bgpd.c | 97 | ||||
| -rw-r--r-- | bgpd/bgpd.h | 7 | ||||
| -rw-r--r-- | doc/user/overview.rst | 28 | ||||
| -rw-r--r-- | lib/subdir.am | 2 | ||||
| -rw-r--r-- | lib/vrf.c | 2 | ||||
| -rw-r--r-- | ospf6d/subdir.am | 2 | ||||
| -rw-r--r-- | ospfd/subdir.am | 2 | ||||
| -rw-r--r-- | ripd/subdir.am | 2 | ||||
| -rw-r--r-- | zebra/redistribute.c | 33 | ||||
| -rw-r--r-- | zebra/subdir.am | 2 | ||||
| -rw-r--r-- | zebra/zebra_ns.c | 35 | ||||
| -rw-r--r-- | zebra/zebra_ns.h | 1 | ||||
| -rw-r--r-- | zebra/zebra_static.c | 32 | ||||
| -rw-r--r-- | zebra/zebra_static.h | 9 | ||||
| -rw-r--r-- | zebra/zebra_vrf.c | 25 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 255 |
20 files changed, 450 insertions, 143 deletions
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 8a410adca1..6761389100 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -116,7 +116,7 @@ module_LTLIBRARIES += bgpd_snmp.la endif bgpd_snmp_la_SOURCES = bgp_snmp.c -bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99 bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index e714e17bde..2c52b57b36 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1177,7 +1177,6 @@ static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer, * not right. * So do the checks later, i.e. here */ - struct bgp *bgp = peer->bgp; struct aspath *aspath; /* Confederation sanity check. */ @@ -1192,7 +1191,7 @@ static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer, } /* First AS check for EBGP. */ - if (bgp != NULL && bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) { + if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) { if (peer->sort == BGP_PEER_EBGP && !aspath_firstas_check(attr->aspath, peer->as)) { zlog_err("%s incorrect first AS (must be %u)", diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 37d06c1e53..84a959d0e8 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -723,7 +723,9 @@ int bgp_socket(struct bgp *bgp, unsigned short port, const char *address) if (bgpd_privs.change(ZPRIVS_RAISE)) zlog_err("Can't raise privileges"); sock = vrf_socket(ainfo->ai_family, ainfo->ai_socktype, - ainfo->ai_protocol, bgp->vrf_id, NULL); + ainfo->ai_protocol, bgp->vrf_id, + (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ? + bgp->name : NULL)); if (bgpd_privs.change(ZPRIVS_LOWER)) zlog_err("Can't lower privileges"); if (sock < 0) { diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 257adda3f3..833de64c94 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1991,7 +1991,11 @@ DEFUN (no_bgp_fast_external_failover, } /* "bgp enforce-first-as" configuration. */ -DEFUN (bgp_enforce_first_as, +#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180517 +CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands") +#endif + +DEFUN_DEPRECATED (bgp_enforce_first_as, bgp_enforce_first_as_cmd, "bgp enforce-first-as", BGP_STR @@ -1999,12 +2003,11 @@ DEFUN (bgp_enforce_first_as, { VTY_DECLVAR_CONTEXT(bgp, bgp); bgp_flag_set(bgp, BGP_FLAG_ENFORCE_FIRST_AS); - bgp_clear_star_soft_in(vty, bgp->name); return CMD_SUCCESS; } -DEFUN (no_bgp_enforce_first_as, +DEFUN_DEPRECATED (no_bgp_enforce_first_as, no_bgp_enforce_first_as_cmd, "no bgp enforce-first-as", NO_STR @@ -2013,7 +2016,6 @@ DEFUN (no_bgp_enforce_first_as, { VTY_DECLVAR_CONTEXT(bgp, bgp); bgp_flag_unset(bgp, BGP_FLAG_ENFORCE_FIRST_AS); - bgp_clear_star_soft_in(vty, bgp->name); return CMD_SUCCESS; } @@ -3449,7 +3451,7 @@ ALIAS_HIDDEN(no_neighbor_set_peer_group, no_neighbor_set_peer_group_hidden_cmd, "Peer-group name\n") static int peer_flag_modify_vty(struct vty *vty, const char *ip_str, - uint16_t flag, int set) + uint32_t flag, int set) { int ret; struct peer *peer; @@ -3481,13 +3483,13 @@ static int peer_flag_modify_vty(struct vty *vty, const char *ip_str, return bgp_vty_return(vty, ret); } -static int peer_flag_set_vty(struct vty *vty, const char *ip_str, uint16_t flag) +static int peer_flag_set_vty(struct vty *vty, const char *ip_str, uint32_t flag) { return peer_flag_modify_vty(vty, ip_str, flag, 1); } static int peer_flag_unset_vty(struct vty *vty, const char *ip_str, - uint16_t flag) + uint32_t flag) { return peer_flag_modify_vty(vty, ip_str, flag, 0); } @@ -4584,6 +4586,36 @@ DEFUN (no_neighbor_disable_connected_check, PEER_FLAG_DISABLE_CONNECTED_CHECK); } + +/* enforce-first-as */ +DEFUN (neighbor_enforce_first_as, + neighbor_enforce_first_as_cmd, + "neighbor <A.B.C.D|X:X::X:X|WORD> enforce-first-as", + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Enforce the first AS for EBGP routes\n") +{ + int idx_peer = 1; + + return peer_flag_set_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_ENFORCE_FIRST_AS); +} + +DEFUN (no_neighbor_enforce_first_as, + no_neighbor_enforce_first_as_cmd, + "no neighbor <A.B.C.D|X:X::X:X|WORD> enforce-first-as", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Enforce the first AS for EBGP routes\n") +{ + int idx_peer = 2; + + return peer_flag_unset_vty(vty, argv[idx_peer]->arg, + PEER_FLAG_ENFORCE_FIRST_AS); +} + + DEFUN (neighbor_description, neighbor_description_cmd, "neighbor <A.B.C.D|X:X::X:X|WORD> description LINE...", @@ -12984,6 +13016,10 @@ void bgp_vty_init(void) install_element(BGP_NODE, &neighbor_disable_connected_check_cmd); install_element(BGP_NODE, &no_neighbor_disable_connected_check_cmd); + /* "neighbor enforce-first-as" commands. */ + install_element(BGP_NODE, &neighbor_enforce_first_as_cmd); + install_element(BGP_NODE, &no_neighbor_enforce_first_as_cmd); + /* "neighbor description" commands. */ install_element(BGP_NODE, &neighbor_description_cmd); install_element(BGP_NODE, &no_neighbor_description_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 69297cd3e4..cc09d4991d 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -109,12 +109,7 @@ extern struct zclient *zclient; static int bgp_check_main_socket(bool create, struct bgp *bgp) { static int bgp_server_main_created; - struct listnode *bgpnode, *nbgpnode; - struct bgp *bgp_temp; - if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF && - vrf_is_mapped_on_netns(bgp->vrf_id)) - return 0; if (create == true) { if (bgp_server_main_created) return 0; @@ -125,18 +120,6 @@ static int bgp_check_main_socket(bool create, struct bgp *bgp) } if (!bgp_server_main_created) return 0; - /* only delete socket on some cases */ - for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp_temp)) { - /* do not count with current bgp */ - if (bgp_temp == bgp) - continue; - /* if other instance non VRF, do not delete socket */ - if (bgp_temp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) - return 0; - /* vrf lite, do not delete socket */ - if (!vrf_is_mapped_on_netns(bgp_temp->vrf_id)) - return 0; - } bgp_close(); bgp_server_main_created = 0; return 0; @@ -1391,6 +1374,12 @@ void bgp_peer_conf_if_to_su_update(struct peer *peer) if (!peer->conf_if) return; + /* + * Our peer structure is stored in the bgp->peerhash + * release it before we modify anything. + */ + hash_release(peer->bgp->peerhash, peer); + prev_family = peer->su.sa.sa_family; if ((ifp = if_lookup_by_name(peer->conf_if, peer->bgp->vrf_id))) { peer->ifp = ifp; @@ -1429,8 +1418,9 @@ void bgp_peer_conf_if_to_su_update(struct peer *peer) memset(&peer->su.sin6.sin6_addr, 0, sizeof(struct in6_addr)); } - /* Since our su changed we need to del/add peer to the peerhash */ - hash_release(peer->bgp->peerhash, peer); + /* + * Since our su changed we need to del/add peer to the peerhash + */ hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); } @@ -3079,17 +3069,16 @@ int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, vrf_id_t old_vrf_id, /* Create BGP server socket, if listen mode not disabled */ if (!bgp || bgp_option_check(BGP_OPT_NO_LISTEN)) return 0; - if (bgp->name && bgp->inst_type == BGP_INSTANCE_TYPE_VRF && vrf) { + if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) { /* * suppress vrf socket */ if (create == FALSE) { - if (vrf_is_mapped_on_netns(vrf->vrf_id)) - bgp_close_vrf_socket(bgp); - else - ret = bgp_check_main_socket(create, bgp); - return ret; + bgp_close_vrf_socket(bgp); + return 0; } + if (vrf == NULL) + return BGP_ERR_INVALID_VALUE; /* do nothing * if vrf_id did not change */ @@ -3104,21 +3093,12 @@ int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, vrf_id_t old_vrf_id, */ if (vrf->vrf_id == VRF_UNKNOWN) return 0; - /* if BGP VRF instance requested - * if backend is NETNS, create BGP server socket in the NETNS - */ - if (vrf_is_mapped_on_netns(bgp->vrf_id)) { - ret = bgp_socket(bgp, bm->port, bm->address); - if (ret < 0) - return BGP_ERR_INVALID_VALUE; - return 0; - } - } - /* if BGP VRF instance requested or VRF lite backend - * if BGP non VRF instance, create it - * if not already done - */ - return bgp_check_main_socket(create, bgp); + ret = bgp_socket(bgp, bm->port, bm->address); + if (ret < 0) + return BGP_ERR_INVALID_VALUE; + return 0; + } else + return bgp_check_main_socket(create, bgp); } /* Called from VTY commands. */ @@ -3495,16 +3475,7 @@ struct peer *peer_lookup(struct bgp *bgp, union sockunion *su) struct listnode *bgpnode, *nbgpnode; for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) { - /* Skip VRFs Lite only, this function will not be - * invoked without an instance - * when examining VRFs. - */ - if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF) - && !vrf_is_mapped_on_netns(bgp->vrf_id)) - continue; - peer = hash_lookup(bgp->peerhash, &tmp_peer); - if (peer) break; } @@ -3805,6 +3776,7 @@ static const struct peer_flag_action peer_flag_action_list[] = { {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset}, {PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset}, {PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset}, + {PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in}, {0, 0, 0}}; static const struct peer_flag_action peer_af_flag_action_list[] = { @@ -6747,6 +6719,14 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, } } + /* enforce-first-as */ + if (CHECK_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) { + if (!peer_group_active(peer) + || !CHECK_FLAG(g_peer->flags, PEER_FLAG_ENFORCE_FIRST_AS)) { + vty_out(vty, " neighbor %s enforce-first-as\n", addr); + } + } + /* update-source */ if (peer->update_if) { if (!peer_group_active(peer) || !g_peer->update_if @@ -7296,6 +7276,12 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, vty_endframe(vty, " exit-address-family\n"); } +/* clang-format off */ +#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180517 +CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write") +#endif +/* clang-format on */ + int bgp_config_write(struct vty *vty) { int write = 0; @@ -7331,6 +7317,15 @@ int bgp_config_write(struct vty *vty) if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO)) continue; + /* Migrate deprecated 'bgp enforce-first-as' + * config to 'neighbor * enforce-first-as' configs + */ + if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) { + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) + peer_flag_set(peer, PEER_FLAG_ENFORCE_FIRST_AS); + bgp_flag_unset(bgp, BGP_FLAG_ENFORCE_FIRST_AS); + } + /* Router bgp ASN */ vty_out(vty, "router bgp %u", bgp->as); @@ -7429,10 +7424,6 @@ int bgp_config_write(struct vty *vty) vty_out(vty, "\n"); } - /* BGP enforce-first-as. */ - if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) - vty_out(vty, " bgp enforce-first-as\n"); - /* BGP deterministic-med. */ if (!!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) != DFLT_BGP_DETERMINISTIC_MED) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 4c87ac0b6f..a685411f6e 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -832,13 +832,14 @@ struct peer { #define PEER_FLAG_DISABLE_CONNECTED_CHECK (1 << 6) /* disable-connected-check */ #define PEER_FLAG_LOCAL_AS_NO_PREPEND (1 << 7) /* local-as no-prepend */ #define PEER_FLAG_LOCAL_AS_REPLACE_AS (1 << 8) /* local-as no-prepend replace-as */ -#define PEER_FLAG_DELETE (1 << 9) /* mark the peer for deleting */ -#define PEER_FLAG_CONFIG_NODE (1 << 10) /* the node to update configs on */ +#define PEER_FLAG_DELETE (1 << 9) /* mark the peer for deleting */ +#define PEER_FLAG_CONFIG_NODE (1 << 10) /* the node to update configs on */ #define PEER_FLAG_LONESOUL (1 << 11) #define PEER_FLAG_DYNAMIC_NEIGHBOR (1 << 12) /* dynamic neighbor */ #define PEER_FLAG_CAPABILITY_ENHE (1 << 13) /* Extended next-hop (rfc 5549)*/ #define PEER_FLAG_IFPEER_V6ONLY (1 << 14) /* if-based peer is v6 only */ -#define PEER_FLAG_IS_RFAPI_HD (1 << 15) /* attached to rfapi HD */ +#define PEER_FLAG_IS_RFAPI_HD (1 << 15) /* attached to rfapi HD */ +#define PEER_FLAG_ENFORCE_FIRST_AS (1 << 16) /* enforce-first-as */ /* outgoing message sent in CEASE_ADMIN_SHUTDOWN notify */ char *tx_shutdown_message; diff --git a/doc/user/overview.rst b/doc/user/overview.rst index eb24970bee..0d630ce1a8 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -214,6 +214,34 @@ FRR implements the following RFCs: - :rfc:`3137` :t:`OSPF Stub Router Advertisement, A. Retana, L. Nguyen, R. White, A. Zinin, D. McPherson. June 2001` +- :rfc:`4447` + :t:`Pseudowire Setup and Maintenance Using the Label Distribution Protocol + (LDP), L. Martini, E. Rosen, N. El-Aawar, T. Smith, and G. Heron. April + 2006.` +- :rfc:`4762` + :t:`Virtual Private LAN Service (VPLS) Using Label Distribution Protocol + (LDP) Signaling, M. Lasserre and V. Kompella. January 2007.` +- :rfc:`5036` + :t:`LDP Specification, L. Andersson, I. Minei, and B. Thomas. October 2007.` +- :rfc:`5561` + :t:`LDP Capabilities, B. Thomas, K. Raza, S. Aggarwal, R. Aggarwal, and + JL. Le Roux. July 2009.` +- :rfc:`5918` + :t:`Label Distribution Protocol (LDP) 'Typed Wildcard' Forward Equivalence + Class (FEC), R. Asati, I. Minei, and B. Thomas. August 2010.` +- :rfc:`5919` + :t:`Signaling LDP Label Advertisement Completion, R. Asati, P. Mohapatra, + E. Chen, and B. Thomas. August 2010.` +- :rfc:`6667` + :t:`LDP 'Typed Wildcard' Forwarding Equivalence Class (FEC) for PWid and + Generalized PWid FEC Elements, K. Raza, S. Boutros, and C. Pignataro. July + 2012.` +- :rfc:`6720` + :t:`The Generalized TTL Security Mechanism (GTSM) for the Label Distribution + Protocol (LDP), C. Pignataro and R. Asati. August 2012.` +- :rfc:`7552` + :t:`Updates to LDP for IPv6, R. Asati, C. Pignataro, K. Raza, V. Manral, + and R. Papneja. June 2015.` **When SNMP support is enabled, the following RFCs are also supported:** diff --git a/lib/subdir.am b/lib/subdir.am index c5719786d6..1c3d31b927 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -190,7 +190,7 @@ if SNMP lib_LTLIBRARIES += lib/libfrrsnmp.la endif -lib_libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +lib_libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99 lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0 lib_libfrrsnmp_la_LIBADD = lib/libfrr.la $(SNMP_LIBS) lib_libfrrsnmp_la_SOURCES = \ @@ -856,7 +856,7 @@ int vrf_bind(vrf_id_t vrf_id, int fd, char *name) if (vrf_is_mapped_on_netns(vrf_id)) return fd; #ifdef SO_BINDTODEVICE - ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)); + ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1); if (ret < 0) zlog_debug("bind to interface %s failed, errno=%d", name, errno); diff --git a/ospf6d/subdir.am b/ospf6d/subdir.am index 76a64cd637..8a6c4a5ccf 100644 --- a/ospf6d/subdir.am +++ b/ospf6d/subdir.am @@ -61,6 +61,6 @@ ospf6d_ospf6d_SOURCES = \ # end ospf6d_ospf6d_snmp_la_SOURCES = ospf6d/ospf6_snmp.c -ospf6d_ospf6d_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +ospf6d_ospf6d_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99 ospf6d_ospf6d_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic ospf6d_ospf6d_snmp_la_LIBADD = lib/libfrrsnmp.la diff --git a/ospfd/subdir.am b/ospfd/subdir.am index 9f04260366..f2e292e186 100644 --- a/ospfd/subdir.am +++ b/ospfd/subdir.am @@ -89,7 +89,7 @@ ospfd_ospfd_LDADD = ospfd/libfrrospf.a lib/libfrr.la @LIBCAP@ @LIBM@ ospfd_ospfd_SOURCES = ospfd/ospf_main.c ospfd_ospfd_snmp_la_SOURCES = ospfd/ospf_snmp.c -ospfd_ospfd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +ospfd_ospfd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99 ospfd_ospfd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic ospfd_ospfd_snmp_la_LIBADD = lib/libfrrsnmp.la diff --git a/ripd/subdir.am b/ripd/subdir.am index 7a8f2185ba..1c5167ef4a 100644 --- a/ripd/subdir.am +++ b/ripd/subdir.am @@ -35,7 +35,7 @@ ripd_ripd_SOURCES = \ # end ripd_ripd_snmp_la_SOURCES = ripd/rip_snmp.c -ripd_ripd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +ripd_ripd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99 ripd_ripd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic ripd_ripd_snmp_la_LIBADD = lib/libfrrsnmp.la diff --git a/zebra/redistribute.c b/zebra/redistribute.c index b1387815ba..be53b74b3f 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -120,7 +120,7 @@ static void zebra_redistribute(struct zserv *client, int type, if (IS_ZEBRA_DEBUG_EVENT) zlog_debug( - "%s: client %s %s(%d) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d", + "%s: client %s %s(%u) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d", __func__, zebra_route_string(client->proto), prefix2str(dst_p, buf, sizeof(buf)), @@ -192,7 +192,7 @@ void redistribute_update(struct prefix *p, struct prefix *src_p, if (send_redistribute) { if (IS_ZEBRA_DEBUG_EVENT) { zlog_debug( - "%s: client %s %s(%d), type=%d, distance=%d, metric=%d", + "%s: client %s %s(%u), type=%d, distance=%d, metric=%d", __func__, zebra_route_string(client->proto), prefix2str(p, buf, sizeof(buf)), @@ -270,7 +270,7 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS) if (IS_ZEBRA_DEBUG_EVENT) zlog_debug( - "%s: client proto %s afi=%d, wants %s, vrf %d, instance=%d", + "%s: client proto %s afi=%d, wants %s, vrf %u, instance=%d", __func__, zebra_route_string(client->proto), afi, zebra_route_string(type), zvrf_id(zvrf), instance); @@ -298,7 +298,7 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS) if (!vrf_bitmap_check(client->redist[afi][type], zvrf_id(zvrf))) { if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s: setting vrf %d redist bitmap", + zlog_debug("%s: setting vrf %u redist bitmap", __func__, zvrf_id(zvrf)); vrf_bitmap_set(client->redist[afi][type], zvrf_id(zvrf)); @@ -365,7 +365,8 @@ void zebra_interface_up_update(struct interface *ifp) struct zserv *client; if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("MESSAGE: ZEBRA_INTERFACE_UP %s", ifp->name); + zlog_debug("MESSAGE: ZEBRA_INTERFACE_UP %s(%u)", + ifp->name, ifp->vrf_id); if (ifp->ptm_status || !ifp->ptm_enable) { for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) @@ -384,7 +385,8 @@ void zebra_interface_down_update(struct interface *ifp) struct zserv *client; if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("MESSAGE: ZEBRA_INTERFACE_DOWN %s", ifp->name); + zlog_debug("MESSAGE: ZEBRA_INTERFACE_DOWN %s(%u)", + ifp->name, ifp->vrf_id); for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp); @@ -398,7 +400,7 @@ void zebra_interface_add_update(struct interface *ifp) struct zserv *client; if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s[%d]", ifp->name, + zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s(%u)", ifp->name, ifp->vrf_id); for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) @@ -415,7 +417,8 @@ void zebra_interface_delete_update(struct interface *ifp) struct zserv *client; if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s", ifp->name); + zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s(%u)", + ifp->name, ifp->vrf_id); for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { client->ifdel_cnt++; @@ -435,8 +438,9 @@ void zebra_interface_address_add_update(struct interface *ifp, char buf[PREFIX_STRLEN]; p = ifc->address; - zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s on %s", - prefix2str(p, buf, sizeof(buf)), ifc->ifp->name); + zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADDRESS_ADD %s on %s(%u)", + prefix2str(p, buf, sizeof(buf)), ifp->name, + ifp->vrf_id); } if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) @@ -467,8 +471,9 @@ void zebra_interface_address_delete_update(struct interface *ifp, char buf[PREFIX_STRLEN]; p = ifc->address; - zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s on %s", - prefix2str(p, buf, sizeof(buf)), ifc->ifp->name); + zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADDRESS_DELETE %s on %s(%u)", + prefix2str(p, buf, sizeof(buf)), + ifp->name, ifp->vrf_id); } zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 0); @@ -768,8 +773,8 @@ void zebra_interface_parameters_update(struct interface *ifp) struct zserv *client; if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s", - ifp->name); + zlog_debug("MESSAGE: ZEBRA_INTERFACE_LINK_PARAMS %s(%u)", + ifp->name, ifp->vrf_id); for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) if (client->ifinfo) diff --git a/zebra/subdir.am b/zebra/subdir.am index 45e285a9e7..d3abcef6d5 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -127,7 +127,7 @@ zebra_zebra_irdp_la_SOURCES = \ zebra_zebra_irdp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic zebra_zebra_snmp_la_SOURCES = zebra/zebra_snmp.c -zebra_zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) +zebra_zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99 zebra_zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic zebra_zebra_snmp_la_LIBADD = lib/libfrrsnmp.la 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 <ip$ipv4|ipv6$ipv6> 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(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(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); + 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); |
