From ce9ca0d849b0b00c81e910ee62fb83c9bd793d1b Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 21 Dec 2023 15:40:35 +0100 Subject: [PATCH 1/8] lib: add default support for uint8_t variable To support the various values of mpls configuration, as the value is encoded in a 8 bits value, define a new uint8_t type to record it. Signed-off-by: Philippe Guibert --- lib/defaults.c | 4 ++++ lib/defaults.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/lib/defaults.c b/lib/defaults.c index 04b5fd36f350..c5114f6721a1 100644 --- a/lib/defaults.c +++ b/lib/defaults.c @@ -166,6 +166,8 @@ static void frr_default_apply_one(struct frr_default *dflt, bool check) *dflt->dflt_ulong = dfltentry->val_ulong; if (dflt->dflt_float) *dflt->dflt_float = dfltentry->val_float; + if (dflt->dflt_uint8_t) + *dflt->dflt_uint8_t = dfltentry->val_uint8_t; if (dflt->save_bool) *dflt->save_bool = saveentry->val_bool; if (dflt->save_str) @@ -176,6 +178,8 @@ static void frr_default_apply_one(struct frr_default *dflt, bool check) *dflt->save_ulong = saveentry->val_ulong; if (dflt->save_float) *dflt->save_float = saveentry->val_float; + if (dflt->save_uint8_t) + *dflt->save_uint8_t = saveentry->val_uint8_t; } void frr_defaults_apply(void) diff --git a/lib/defaults.h b/lib/defaults.h index afb3223db354..b03f0c0fc127 100644 --- a/lib/defaults.h +++ b/lib/defaults.h @@ -38,6 +38,7 @@ struct frr_default_entry { long val_long; unsigned long val_ulong; float val_float; + uint8_t val_uint8_t; }; /* one struct frr_default exists for each malleable default value */ @@ -62,6 +63,7 @@ struct frr_default { long *dflt_long; unsigned long *dflt_ulong; float *dflt_float; + uint8_t *dflt_uint8_t; /* variable to use when comparing for config save */ bool *save_bool; @@ -69,6 +71,7 @@ struct frr_default { long *save_long; unsigned long *save_ulong; float *save_float; + uint8_t *save_uint8_t; struct frr_default_entry entries[]; }; @@ -113,6 +116,8 @@ struct frr_default { _FRR_CFG_DEFAULT(float, float, varname, ## __VA_ARGS__) #define FRR_CFG_DEFAULT_STR(varname, ...) \ _FRR_CFG_DEFAULT(const char *, str, varname, ## __VA_ARGS__) +#define FRR_CFG_DEFAULT_UINT8_T(varname, ...) \ + _FRR_CFG_DEFAULT(uint8_t, uint8_t, varname, ##__VA_ARGS__) /* daemons don't need to call any of these, libfrr handles that */ From 9266a5b26251d451360bf6290e772bfc544ba73e Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 19 Dec 2023 12:06:59 +0100 Subject: [PATCH 2/8] zebra: add json support for mpls config per interface Add 'mplsConfig' json option, that defines which MPLS configuration is applied to a given interface. > # show interface loop1 json > { > "loop1":{ > [..] > "mplsConfig":"mplsEnabled", > "mplsEnabled":false, > [..] Signed-off-by: Philippe Guibert --- zebra/interface.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/zebra/interface.c b/zebra/interface.c index b824977f9e13..ed65802cdff1 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -3024,6 +3024,13 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, json_object_string_add(json_if, "OsDescription", zebra_if->desc); + if (zebra_if->mpls_config == IF_ZEBRA_DATA_UNSPEC) + json_object_string_add(json_if, "mplsConfig", "unspecified"); + else if (zebra_if->mpls_config == IF_ZEBRA_DATA_ON) + json_object_string_add(json_if, "mplsConfig", "mplsEnabled"); + else if (zebra_if->mpls_config == IF_ZEBRA_DATA_OFF) + json_object_string_add(json_if, "mplsConfig", "mplsDisabled"); + json_object_boolean_add(json_if, "mplsEnabled", zebra_if->mpls); json_object_boolean_add(json_if, "linkDown", zebra_if->linkdown); json_object_boolean_add(json_if, "linkDownV6", zebra_if->linkdownv6); From 4b6a7ccc271dc1d9ff9443f164d5b3194572687b Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 19 Dec 2023 11:56:08 +0100 Subject: [PATCH 3/8] zebra: add default MPLS interface settings framework By default, MPLS configuration per interface is unspecified, but can not be changed by compilation. Add the framework to change the MPLS settings. Signed-off-by: Philippe Guibert --- zebra/interface.c | 5 ++++- zebra/subdir.am | 1 + zebra/zebra_cli.c | 12 +++++------- zebra/zebra_defaults.h | 32 ++++++++++++++++++++++++++++++++ zebra/zebra_nb_config.c | 3 ++- zebra/zebra_vrf.c | 1 + zebra/zebra_vrf.h | 5 ----- 7 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 zebra/zebra_defaults.h diff --git a/zebra/interface.c b/zebra/interface.c index ed65802cdff1..6a8bbadaa62e 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -36,6 +36,8 @@ #include "zebra/zebra_vxlan.h" #include "zebra/zebra_errors.h" #include "zebra/zebra_evpn_mh.h" +#include "zebra/zebra_cli.h" +#include "zebra/zebra_defaults.h" DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information"); @@ -121,7 +123,8 @@ static int if_zebra_new_hook(struct interface *ifp) zebra_if->ifp = ifp; zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC; - zebra_if->mpls_config = IF_ZEBRA_DATA_UNSPEC; + zebra_if->mpls_config = DFLT_ZEBRA_MPLS; + zebra_if->shutdown = IF_ZEBRA_DATA_UNSPEC; zebra_if->link_nsid = NS_UNKNOWN; diff --git a/zebra/subdir.am b/zebra/subdir.am index f7674473661c..ff470de99150 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -202,6 +202,7 @@ noinst_HEADERS += \ zebra/zserv.h \ zebra/dpdk/zebra_dplane_dpdk.h \ zebra/dpdk/zebra_dplane_dpdk_private.h \ + zebra/zebra_defaults.h \ # end zebra_zebra_irdp_la_SOURCES = \ diff --git a/zebra/zebra_cli.c b/zebra/zebra_cli.c index 3e03d7477575..d8839eeb1cf3 100644 --- a/zebra/zebra_cli.c +++ b/zebra/zebra_cli.c @@ -11,14 +11,11 @@ #include "zebra_cli.h" #include "zebra/zebra_cli_clippy.c" +#include "interface.h" +#include "zebra/zebra_defaults.h" #define EVPN_MH_VTY_STR "Multihoming\n" -FRR_CFG_DEFAULT_BOOL(ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT, - { .val_bool = true, .match_profile = "traditional", }, - { .val_bool = false }, -); - #if HAVE_BFDD == 0 DEFPY_YANG (zebra_ptm_enable, zebra_ptm_enable_cmd, @@ -139,9 +136,10 @@ static void lib_interface_zebra_mpls_cli_write(struct vty *vty, { bool mpls = yang_dnode_get_bool(dnode, NULL); - if (mpls) + if (mpls && ((SAVE_ZEBRA_MPLS != IF_ZEBRA_DATA_ON) || show_defaults)) vty_out(vty, " mpls enable\n"); - else + else if (mpls == false && + ((SAVE_ZEBRA_MPLS != IF_ZEBRA_DATA_OFF) || show_defaults)) vty_out(vty, " mpls disable\n"); } diff --git a/zebra/zebra_defaults.h b/zebra/zebra_defaults.h new file mode 100644 index 000000000000..adfa16413cab --- /dev/null +++ b/zebra/zebra_defaults.h @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Zebra defaults header message + */ + +#ifndef _ZEBRA_DEFAULTS_H_ +#define _ZEBRA_DEFAULTS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "defaults.h" +#include "zebra/interface.h" + +FRR_CFG_DEFAULT_BOOL(ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT, + { + .val_bool = true, + .match_profile = "traditional", + }, + { .val_bool = false }, + ); + +FRR_CFG_DEFAULT_UINT8_T(ZEBRA_MPLS, + { .val_uint8_t = IF_ZEBRA_DATA_UNSPEC }, + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZEBRA_DEFAULTS_H_ */ diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c index ae6232a1bbfb..795c23dabff9 100644 --- a/zebra/zebra_nb_config.c +++ b/zebra/zebra_nb_config.c @@ -29,6 +29,7 @@ #include "zebra/zebra_routemap.h" #include "zebra/zebra_rnh.h" #include "zebra/table_manager.h" +#include "zebra/zebra_defaults.h" /* * XPath: /frr-zebra:zebra/mcast-rpf-lookup @@ -1266,7 +1267,7 @@ int lib_interface_zebra_mpls_destroy(struct nb_cb_destroy_args *args) ifp = nb_running_get_entry(args->dnode, NULL, true); zif = ifp->info; - zif->mpls_config = IF_ZEBRA_DATA_UNSPEC; + zif->mpls_config = DFLT_ZEBRA_MPLS; /* keep the state as it is */ diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index e464e47b1f0c..af8f83db38da 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -33,6 +33,7 @@ #include "zebra/zebra_routemap.h" #include "zebra/zebra_vrf_clippy.c" #include "zebra/table_manager.h" +#include "zebra/zebra_defaults.h" static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, safi_t safi); diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 5cbfab1ddc0f..4da14e2dc9c2 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -19,11 +19,6 @@ extern "C" { #endif -FRR_CFG_DEFAULT_BOOL(ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT, - { .val_bool = true, .match_profile = "traditional", }, - { .val_bool = false }, -); - /* MPLS (Segment Routing) global block */ struct mpls_srgb { uint32_t start_label; From b8c24a69cd0aa2b1a67468c3648e217021f9e2bc Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 13 Jul 2023 10:11:49 +0200 Subject: [PATCH 4/8] zebra, yang, doc: add 'mpls auto' command There is not auto mode for mpls settings, so that when any labeled route or mpls entry is configured, then the used interface should automatically turn on its mpls settings. Add the following per interface command: > mpls auto Change the yang model to replace the mpls boolean value with an enumerate, which is mapped over the data values declared under zebra/interface.h. Signed-off-by: Philippe Guibert --- doc/user/zebra.rst | 6 ++++-- yang/frr-zebra.yang | 20 ++++++++++++++++++-- zebra/interface.c | 2 ++ zebra/interface.h | 8 ++++++++ zebra/zebra_cli.c | 12 ++++++++---- zebra/zebra_nb_config.c | 14 ++++++-------- 6 files changed, 46 insertions(+), 16 deletions(-) diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 72b4f2041852..f8099ab41904 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -170,13 +170,15 @@ Standard Commands Set description for the interface. -.. clicmd:: mpls +.. clicmd:: mpls Choose mpls kernel processing value on the interface, for linux. Interfaces configured with mpls will not automatically turn on if mpls kernel modules do not happen to be loaded. This command will fail on 3.X linux kernels and does not work on non-linux systems at all. 'enable' and 'disable' will respectively turn - on and off mpls on the given interface. + on and off mpls on the given interface. The 'auto' mode will enable mpls on the + given interface, if an mpls entry or a labeled route happens to be installed and + needs mpls processing to be turned on. .. clicmd:: multicast diff --git a/yang/frr-zebra.yang b/yang/frr-zebra.yang index 79c524a40a94..febcbc64bcaf 100644 --- a/yang/frr-zebra.yang +++ b/yang/frr-zebra.yang @@ -2043,9 +2043,25 @@ module frr-zebra { } leaf mpls { - type boolean; description - "Interface MPLS status."; + "Interface MPLS configuration status."; + type enumeration { + enum enable { + value 1; + description + "MPLS configuration is enabled."; + } + enum disable { + value 2; + description + "MPLS configuration is disabled."; + } + enum auto { + value 3; + description + "MPLS configuration is enabled when used."; + } + } } leaf bandwidth { diff --git a/zebra/interface.c b/zebra/interface.c index 6a8bbadaa62e..8b7c0d0a89c1 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -3033,6 +3033,8 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp, json_object_string_add(json_if, "mplsConfig", "mplsEnabled"); else if (zebra_if->mpls_config == IF_ZEBRA_DATA_OFF) json_object_string_add(json_if, "mplsConfig", "mplsDisabled"); + else if (zebra_if->mpls_config == IF_ZEBRA_DATA_AUTO) + json_object_string_add(json_if, "mplsConfig", "mplsAuto"); json_object_boolean_add(json_if, "mplsEnabled", zebra_if->mpls); json_object_boolean_add(json_if, "linkDown", zebra_if->linkdown); diff --git a/zebra/interface.h b/zebra/interface.h index 8d19c1838fbf..650279da02a1 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -26,6 +26,14 @@ extern "C" { #define IF_ZEBRA_DATA_UNSPEC 0 #define IF_ZEBRA_DATA_ON 1 #define IF_ZEBRA_DATA_OFF 2 +#define IF_ZEBRA_DATA_AUTO 3 + +enum if_zebra_data_mode { + IF_DATA_UNSPEC = IF_ZEBRA_DATA_UNSPEC, + IF_DATA_ON = IF_ZEBRA_DATA_ON, + IF_DATA_OFF = IF_ZEBRA_DATA_OFF, + IF_DATA_AUTO = IF_ZEBRA_DATA_AUTO +}; #define IF_VLAN_BITMAP_MAX 4096 diff --git a/zebra/zebra_cli.c b/zebra/zebra_cli.c index d8839eeb1cf3..37effaae7999 100644 --- a/zebra/zebra_cli.c +++ b/zebra/zebra_cli.c @@ -114,15 +114,16 @@ DEFPY_YANG_HIDDEN (multicast, DEFPY_YANG (mpls, mpls_cmd, - "[no] mpls ", + "[no] mpls $state", NO_STR MPLS_STR "Set mpls to be on for the interface\n" - "Set mpls to be off for the interface\n") + "Set mpls to be off for the interface\n" + "Set mpls to be auto for the interface\n") { if (!no) nb_cli_enqueue_change(vty, "./frr-zebra:zebra/mpls", - NB_OP_CREATE, on ? "true" : "false"); + NB_OP_CREATE, state); else nb_cli_enqueue_change(vty, "./frr-zebra:zebra/mpls", NB_OP_DESTROY, NULL); @@ -134,13 +135,16 @@ static void lib_interface_zebra_mpls_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults) { - bool mpls = yang_dnode_get_bool(dnode, NULL); + enum if_zebra_data_mode mpls = yang_dnode_get_enum(dnode, NULL); if (mpls && ((SAVE_ZEBRA_MPLS != IF_ZEBRA_DATA_ON) || show_defaults)) vty_out(vty, " mpls enable\n"); else if (mpls == false && ((SAVE_ZEBRA_MPLS != IF_ZEBRA_DATA_OFF) || show_defaults)) vty_out(vty, " mpls disable\n"); + else if (mpls == IF_DATA_AUTO && + ((SAVE_ZEBRA_MPLS != IF_ZEBRA_DATA_AUTO) || show_defaults)) + vty_out(vty, " mpls disable\n"); } DEFPY_YANG (linkdetect, diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c index 795c23dabff9..1b1813d76d73 100644 --- a/zebra/zebra_nb_config.c +++ b/zebra/zebra_nb_config.c @@ -1236,7 +1236,6 @@ int lib_interface_zebra_enabled_destroy(struct nb_cb_destroy_args *args) int lib_interface_zebra_mpls_modify(struct nb_cb_modify_args *args) { struct interface *ifp; - bool mpls; struct zebra_if *zif; if (args->event != NB_EV_APPLY) @@ -1244,15 +1243,14 @@ int lib_interface_zebra_mpls_modify(struct nb_cb_modify_args *args) ifp = nb_running_get_entry(args->dnode, NULL, true); zif = ifp->info; - mpls = yang_dnode_get_bool(args->dnode, NULL); + zif->mpls_config = yang_dnode_get_enum(args->dnode, NULL); - if (mpls) - zif->mpls_config = IF_ZEBRA_DATA_ON; - else - zif->mpls_config = IF_ZEBRA_DATA_OFF; - - dplane_intf_mpls_modify_state(ifp, mpls); + if (zif->mpls_config == IF_ZEBRA_DATA_ON || + zif->mpls_config == IF_ZEBRA_DATA_OFF) + dplane_intf_mpls_modify_state(ifp, zif->mpls_config == + IF_ZEBRA_DATA_ON); + /* if auto mode, then let us wait other events */ return NB_OK; } From 2822ddfbfabaa7f85e9785b6e58d84af8a858c8b Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Thu, 13 Jul 2023 10:47:29 +0200 Subject: [PATCH 5/8] zebra: add dynamic mpls activation upon routing events When a labeled route, or an MPLS entry is configured, the interface may not have properly enabled the interface with mpls. When the interface is in mpls auto mode, change the mpls interface value when a route or an mpls entry requests it to be turned on. Signed-off-by: Philippe Guibert --- zebra/interface.c | 40 ++++++++++++++++++++++++++++++++++++++++ zebra/interface.h | 8 ++++++++ zebra/zapi_msg.c | 10 ++++++++-- zebra/zebra_mpls.c | 4 ++++ zebra/zebra_nhg.c | 8 ++++++++ 5 files changed, 68 insertions(+), 2 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index 8b7c0d0a89c1..30767eff16ae 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -608,6 +608,10 @@ void if_add_update(struct interface *ifp) dplane_intf_mpls_modify_state(ifp, true); else if (if_data->mpls_config == IF_ZEBRA_DATA_OFF) dplane_intf_mpls_modify_state(ifp, false); + else if (if_data->mpls_config == IF_ZEBRA_DATA_AUTO && + if_data->mpls_dynamic != IF_ZEBRA_DATA_UNSPEC) + dplane_intf_mpls_modify_state(ifp, + if_data->mpls_dynamic); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( @@ -3934,6 +3938,42 @@ void if_ipv6_address_uninstall(struct interface *ifp, struct prefix *prefix) UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); } +static void mpls_auto_interface_data_internal(struct interface *ifp, bool mpls) +{ + struct zebra_if *zif; + uint8_t mpls_val; + + if (!ifp || !ifp->info) + return; + zif = ifp->info; + if (zif->mpls_config != IF_ZEBRA_DATA_AUTO) + return; + + if (zif->mpls == mpls) + return; + + if (mpls) + mpls_val = IF_ZEBRA_DATA_ON; + else + mpls_val = IF_ZEBRA_DATA_OFF; + + if (zif->mpls_dynamic == mpls_val) + return; + + zif->mpls_dynamic = mpls; + dplane_intf_mpls_modify_state(ifp, mpls); +} + +void mpls_auto_interface_data_on(struct interface *ifp) +{ + mpls_auto_interface_data_internal(ifp, true); +} + +void mpls_auto_interface_data_off(struct interface *ifp) +{ + mpls_auto_interface_data_internal(ifp, false); +} + /* Allocate and initialize interface vector. */ void zebra_if_init(void) { diff --git a/zebra/interface.h b/zebra/interface.h index 650279da02a1..7a9daf9a00b6 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -124,6 +124,12 @@ struct zebra_if { /* MPLS configuration */ uint8_t mpls_config; + /* MPLS dynamic configuration - when mpls_config is auto + * by default, set to IF_ZEBRA_DATA_UNSPEC + * when used, acceptable values: IF_ZEBRA_DATA_ON or IF_ZEBRA_DATA_OFF + */ + uint8_t mpls_dynamic; + /* Linkdown status */ bool linkdown, linkdownv6; @@ -346,6 +352,8 @@ extern void zebra_l2_map_slave_to_bond(struct zebra_if *zif, vrf_id_t vrf); extern void zebra_l2_unmap_slave_from_bond(struct zebra_if *zif); extern const char *zebra_protodown_rc_str(uint32_t protodown_rc, char *pd_buf, uint32_t pd_buf_len); +extern void mpls_auto_interface_data_off(struct interface *ifp); +extern void mpls_auto_interface_data_on(struct interface *ifp); void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx); #ifdef HAVE_PROC_NET_DEV diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index d585ef996bf0..612f47751ebd 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1754,6 +1754,7 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, char nhbuf[NEXTHOP_STRLEN]; char labelbuf[MPLS_LABEL_STRLEN]; struct zapi_nexthop *api_nh = &nhops[i]; + struct interface *ifp; /* Convert zapi nexthop */ nexthop = nexthop_from_zapi(api_nh, flags, p, backup_nh_num); @@ -1790,7 +1791,9 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, && api_nh->type != NEXTHOP_TYPE_IFINDEX && api_nh->type != NEXTHOP_TYPE_BLACKHOLE && api_nh->label_num > 0) { - + ifp = if_lookup_by_index(nexthop->ifindex, + nexthop->vrf_id); + mpls_auto_interface_data_on(ifp); /* If label type was passed, use it */ if (api_nh->label_type) label_type = api_nh->label_type; @@ -3203,16 +3206,19 @@ static void zread_vrf_label(ZAPI_HANDLER_ARGS) } } - if (really_remove) + if (really_remove) { mpls_lsp_uninstall(def_zvrf, ltype, zvrf->label[afi], NEXTHOP_TYPE_IFINDEX, NULL, ifp->ifindex, false /*backup*/); + mpls_auto_interface_data_off(ifp); + } } if (nlabel != MPLS_LABEL_NONE) { mpls_label_t out_label = MPLS_LABEL_IMPLICIT_NULL; mpls_lsp_install(def_zvrf, ltype, nlabel, 1, &out_label, NEXTHOP_TYPE_IFINDEX, NULL, ifp->ifindex); + mpls_auto_interface_data_on(ifp); } zvrf->label[afi] = nlabel; diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 4cc85d461f4a..4d0de3690554 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -3115,6 +3115,10 @@ lsp_add_nhlfe(struct zebra_lsp *lsp, enum lsp_types_t type, if (!nhlfe) return NULL; + if (num_out_labels) + mpls_auto_interface_data_on( + if_lookup_by_index(ifindex, vrf_id)); + if (IS_ZEBRA_DEBUG_MPLS) { char buf2[MPLS_LABEL_STRLEN]; diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 1246e4dba22b..816471f6130b 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -2363,6 +2363,14 @@ static int nexthop_active(struct nexthop *nexthop, struct nhg_hash_entry *nhe, * tree. */ + if (match && match->nhe->nhg.nexthop && + match->nhe->nhg.nexthop->ifindex != IFINDEX_INTERNAL && + nexthop->type != NEXTHOP_TYPE_BLACKHOLE && + nexthop->nh_label && nexthop->nh_label->num_labels) { + ifp = if_lookup_by_index(match->nhe->nhg.nexthop->ifindex, + nexthop->vrf_id); + mpls_auto_interface_data_on(ifp); + } /* If the candidate match's type is considered "connected", * we consider it first. */ From 14711ad88b7ebdec1219203adb6f04b381f6bc5c Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 4 Aug 2023 12:00:08 +0200 Subject: [PATCH 6/8] topotests: add static mpls routing auto mode There is no test that checks for the mpls auto mode configuration. New checks are added to the static mpls routing test: - check that a labeled route turns on mpls on the interface where the auto mode is set - check that a configured interface recovers the mpls setting Signed-off-by: Philippe Guibert --- .../static_routing_mpls/r1/zebra.conf | 6 + .../static_routing_mpls/r2/zebra.conf | 5 + .../test_static_routing_mpls.py | 105 +++++++++++++++++- 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/tests/topotests/static_routing_mpls/r1/zebra.conf b/tests/topotests/static_routing_mpls/r1/zebra.conf index 4e5d29af988c..a1e81c05bf17 100644 --- a/tests/topotests/static_routing_mpls/r1/zebra.conf +++ b/tests/topotests/static_routing_mpls/r1/zebra.conf @@ -13,4 +13,10 @@ int lo ! int r1-eth1 ip addr 192.168.2.1/24 + mpls auto ! +int r1-eth1.100 + ip address 172.31.100.1/24 + mpls auto +! + diff --git a/tests/topotests/static_routing_mpls/r2/zebra.conf b/tests/topotests/static_routing_mpls/r2/zebra.conf index 4e06ae520270..505b75bdea4f 100644 --- a/tests/topotests/static_routing_mpls/r2/zebra.conf +++ b/tests/topotests/static_routing_mpls/r2/zebra.conf @@ -3,6 +3,7 @@ ip forwarding ipv6 forwarding int r2-eth0 + mpls auto ip addr 192.168.2.2/24 ! int r2-eth1 @@ -16,3 +17,7 @@ int r2-eth2 int lo ip addr 192.0.2.2/32 ! +int r2-eth0.100 + ip address 172.31.100.2/24 + mpls auto +! diff --git a/tests/topotests/static_routing_mpls/test_static_routing_mpls.py b/tests/topotests/static_routing_mpls/test_static_routing_mpls.py index c1e249cc8f0f..da416b8882ca 100644 --- a/tests/topotests/static_routing_mpls/test_static_routing_mpls.py +++ b/tests/topotests/static_routing_mpls/test_static_routing_mpls.py @@ -39,6 +39,11 @@ ## ##################################################### +cmds_list_iface = [ + "ip link add link {0}-eth{1} name {0}-eth{1}.{3} type vlan id {3}", + "ip link set dev {0}-eth{1}.{3} up", +] + def build_topo(tgen): "Build function" @@ -65,7 +70,7 @@ def build_topo(tgen): ## Tests starting ## ##################################################### -def _populate_mpls_labels(): +def _populate_iface(): tgen = get_topogen() cmds_list = ["echo 100000 > /proc/sys/net/mpls/platform_labels"] for cmd in cmds_list: @@ -74,13 +79,26 @@ def _populate_mpls_labels(): output = tgen.net[host].cmd(cmd) logger.info("output: " + output) + # 1st interface -eth. + for cmd in cmds_list_iface: + input = cmd.format("r1", "1", "1", "100") + logger.info("input: " + cmd.format("r1", "1", "1", "100")) + output = tgen.net["r1"].cmd(cmd.format("r1", "1", "1", "100")) + logger.info("output: " + output) + + for cmd in cmds_list_iface: + input = cmd.format("r2", "0", "2", "100") + logger.info("input: " + cmd.format("r2", "0", "2", "100")) + output = tgen.net["r2"].cmd(cmd.format("r2", "0", "2", "100")) + logger.info("output: " + output) + def setup_module(module): "Setup topology" tgen = Topogen(build_topo, module.__name__) tgen.start_topology() - _populate_mpls_labels() + _populate_iface() # This is a sample of configuration loading. router_list = tgen.routers() @@ -134,6 +152,89 @@ def test_mpls_configured_on_interface(): assert _check_mpls_state(tgen.gears["r2"], "r2-eth2", False), assertmsg +def test_mpls_zebra_route_nexthop(): + "Test 'mpls' state is correctly configured with labeled routes configured" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + router = tgen.gears["r2"] + router.vtysh_cmd("config terminal\nmpls lsp 33 192.168.2.3 implicit-null") + + logger.info( + "r1, configuring a route with labeled nexthop address, checking that MPLS state is on on r1-eth1" + ) + router = tgen.gears["r1"] + router.vtysh_cmd( + "config terminal\nip route 192.0.2.3/32 192.168.2.2 label 33" + ) + assertmsg = "r1, interface r1-eth1, mpls operational state is off, not expected" + assert _check_mpls_state(tgen.gears["r1"], "r1-eth1"), assertmsg + # interface r1-eth1 should have mpls turned on + + logger.info( + "r2, configuring a route with labeled nexthop interface, checking that MPLS state is on on r2-eth0" + ) + router = tgen.gears["r2"] + router.vtysh_cmd( + "config terminal\nip route 192.0.2.100/32 192.168.2.1 r2-eth0 label 100" + ) + # interface r2-eth0 should have mpls turned on + assertmsg = "r2, interface r2-eth0, mpls operational state is off, not expected" + assert _check_mpls_state(tgen.gears["r2"], "r2-eth0"), assertmsg + + +def test_mpls_interface_configured_delete(): + "Test 'mpls' state is correctly set on a configured interface before and after deletion of that interface" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info( + "r1, configuring a route with labeled nexthop address, checking that MPLS is configured on r1-eth1.100" + ) + router = tgen.gears["r1"] + router.vtysh_cmd( + "config terminal\nip route 192.0.2.160/32 172.31.100.2 label 100" + ) + # interface r1-eth1.100 should have mpls turned on + assertmsg = "r1, interface r1-eth1.100, mpls operational state is off, not expected" + assert _check_mpls_state(tgen.gears["r1"], "r1-eth1.100"), assertmsg + + logger.info( + "r1, deleting r1-eth1.100, checking that MPLS is unconfigured on r1-eth1.200" + ) + tgen.net["r1"].cmd("ip link delete r1-eth1.100") + # interface r1-eth1.100 should be turned down + router.vtysh_cmd( + "config terminal\nno ip route 192.0.2.160/32 172.31.100.2 label 100" + ) + # static route is really removed to not conflict with mpls saved state + + # interface r1-eth1.100 should be turned off, and mpls should be on + assertmsg = "r1, interface r1-eth1.100, mpls operational state is on, not expected" + assert _check_mpls_state( + tgen.gears["r1"], "r1-eth1.100", configured=False + ), assertmsg + + logger.info( + "r1, re-creating r1-eth1.100, checking that MPLS is configured on r1-eth1.100" + ) + for cmd in cmds_list_iface: + input = cmd.format("r1", "1", "1", "100") + logger.info("input: " + cmd.format("r1", "1", "1", "100")) + output = tgen.net["r1"].cmd(cmd.format("r1", "1", "1", "100")) + logger.info("output: " + output) + + # interface r1-eth1.100 should be turned on, and mpls should be on + assertmsg = "r1, interface r1-eth1.100, mpls operational state is off, not expected" + assert _check_mpls_state(tgen.gears["r1"], "r1-eth1.100"), assertmsg + + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) From dbf2252954e4f9f9ec669051c231dbd5db5b0310 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 28 Jan 2019 16:07:00 +0100 Subject: [PATCH 7/8] ldpd, lib, zebra, topotests: add MPLS interface config from LDP When LDP is enabled per interface, MPLS is not turned on on each of those interfaces. Fix this by letting LDP configure the interface if the 'mpls auto' mode is configured. Create an IMSG to send interface config request from ldpe thread to main thread of ldp. Create a ZAPI message to set MPLS from ldp to zebra. Update the MPLS setting. Add a test that ensures that LDP properly configures the interface. Signed-off-by: Philippe Guibert --- ldpd/interface.c | 18 +++++++++ ldpd/ldp_zebra.c | 9 +++++ ldpd/ldpd.c | 10 +++++ ldpd/ldpd.h | 2 + ldpd/ldpe.h | 1 + lib/ldp_sync.h | 5 +++ lib/zclient.c | 45 +++++++++++++++++++++ lib/zclient.h | 7 ++++ tests/topotests/ldp_topo1/r1/zebra.conf | 1 + tests/topotests/ldp_topo1/r2/zebra.conf | 3 ++ tests/topotests/ldp_topo1/r3/zebra.conf | 2 + tests/topotests/ldp_topo1/r4/zebra.conf | 1 + tests/topotests/ldp_topo1/test_ldp_topo1.py | 34 +++++++++++++++- tests/topotests/lib/topogen.py | 6 ++- zebra/interface.c | 17 ++++++++ zebra/interface.h | 3 ++ zebra/zapi_msg.c | 1 + 17 files changed, 162 insertions(+), 3 deletions(-) diff --git a/ldpd/interface.c b/ldpd/interface.c index f0e70cbacce1..9fc8231069d4 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -8,6 +8,7 @@ */ #include +#include "privs.h" #include "ldpd.h" #include "ldpe.h" @@ -16,6 +17,8 @@ #include "sockopt.h" +extern struct zebra_privs_t ldpe_privs; + static __inline int iface_compare(const struct iface *, const struct iface *); static struct if_addr *if_addr_new(struct kaddr *); static struct if_addr *if_addr_lookup(struct if_addr_head *, struct kaddr *); @@ -93,6 +96,20 @@ ldpe_if_init(struct iface *iface) ldp_sync_fsm_init(iface, LDP_SYNC_STA_NOT_ACH); } +/* proc sys net mpls conf input set to 1 or 0 + * should be used from ldpe only + */ +void ldpe_interface_set_mpls(struct iface *iface, bool val) +{ + struct ldp_igp_configure_if_mpls config; + + config.ifindex = iface->ifindex; + config.enabled = val; + + ldpe_imsg_compose_parent(IMSG_LDP_CONFIGURE_IF_MPLS, getpid(), &config, + sizeof(config)); +} + void ldpe_if_exit(struct iface *iface) { @@ -277,6 +294,7 @@ if_start(struct iface *iface, int af) log_debug("%s: %s address-family %s", __func__, iface->name, af_name(af)); + ldpe_interface_set_mpls(iface, true); ia = iface_af_get(iface, af); gettimeofday(&now, NULL); diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index df682a1347be..dd7c92f9c766 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -124,6 +124,15 @@ ldp_sync_zebra_send_state_update(struct ldp_igp_sync_if_state *state) return 0; } +int ldp_sync_zebra_send_configure_if_mpls(struct ldp_igp_configure_if_mpls *config) +{ + if (zebra_send_interface_mpls_set(zclient, VRF_DEFAULT, config->ifindex, + config->enabled) <= 0) + return -1; + + return zclient_send_message(zclient); +} + static int ldp_sync_zebra_send_announce(void) { diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 492a36b3d6a1..fa08bd71ef33 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -610,6 +610,15 @@ static void main_dispatch_ldpe(struct event *thread) ldp_sync_zebra_send_state_update((struct ldp_igp_sync_if_state *)imsg.data); break; + case IMSG_LDP_CONFIGURE_IF_MPLS: + if (imsg.hdr.len != + IMSG_HEADER_SIZE + + sizeof(struct ldp_igp_configure_if_mpls)) + fatalx("IMSG_LDP_CONFIGURE_IF_MPLS imsg with wrong len"); + + ldp_sync_zebra_send_configure_if_mpls( + (struct ldp_igp_configure_if_mpls *)imsg.data); + break; default: log_debug("%s: error handling imsg %d", __func__, imsg.hdr.type); @@ -1524,6 +1533,7 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) if (if_lookup_name(xconf, iface->name) == NULL) { switch (ldpd_process) { case PROC_LDP_ENGINE: + ldpe_interface_set_mpls(iface, false); ldpe_if_exit(iface); break; case PROC_LDE_ENGINE: diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index ad831a6ea358..26bf38b83949 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -151,6 +151,7 @@ enum imsg_type { IMSG_RLFA_UNREG_ALL, IMSG_RLFA_LABELS, IMSG_AGENTX_ENABLED, + IMSG_LDP_CONFIGURE_IF_MPLS, }; struct ldpd_init { @@ -890,6 +891,7 @@ extern char ctl_sock_path[MAXPATHLEN]; void ldp_zebra_init(struct event_loop *m); void ldp_zebra_destroy(void); int ldp_sync_zebra_send_state_update(struct ldp_igp_sync_if_state *); +int ldp_sync_zebra_send_configure_if_mpls(struct ldp_igp_configure_if_mpls *); int ldp_zebra_send_rlfa_labels(struct zapi_rlfa_response * rlfa_labels); diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index f310ba5dd209..7ba26de193db 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -306,6 +306,7 @@ void ldpe_l2vpn_init(struct l2vpn *); void ldpe_l2vpn_exit(struct l2vpn *); void ldpe_l2vpn_pw_init(struct l2vpn_pw *); void ldpe_l2vpn_pw_exit(struct l2vpn_pw *); +extern void ldpe_interface_set_mpls(struct iface *iface, bool val); DECLARE_HOOK(ldp_nbr_state_change, (struct nbr * nbr, int old_state), (nbr, old_state)); diff --git a/lib/ldp_sync.h b/lib/ldp_sync.h index 3a6ae5b3575a..c01754655b00 100644 --- a/lib/ldp_sync.h +++ b/lib/ldp_sync.h @@ -56,6 +56,11 @@ struct ldp_igp_sync_if_state { bool sync_start; }; +struct ldp_igp_configure_if_mpls { + ifindex_t ifindex; + bool enabled; +}; + struct ldp_igp_sync_if_state_req { int proto; ifindex_t ifindex; diff --git a/lib/zclient.c b/lib/zclient.c index c5b1e72380ca..39bdb1268e47 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -2867,6 +2867,51 @@ size_t zebra_interface_link_params_write(struct stream *s, return w; } +int zebra_send_interface_mpls_set(struct zclient *zclient, vrf_id_t vrf_id, + ifindex_t ifindex, bool set) +{ + struct stream *s; + + if (!zclient->obuf) + return 0; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, ZEBRA_INTERFACE_MPLS_SET, VRF_DEFAULT); + + stream_putl(s, ifindex); + stream_putc(s, set); + + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); +} + +struct interface *zebra_interface_mpls_set_read(struct stream *s, + vrf_id_t vrf_id, + bool *value_to_set) +{ + ifindex_t ifindex; + struct interface *ifp = NULL; + + STREAM_GETL(s, ifindex); + + ifp = if_lookup_by_index(ifindex, vrf_id); + + if (ifp == NULL) { + flog_err(EC_LIB_ZAPI_ENCODE, + "%s: unknown ifindex %u, shouldn't happen", __func__, + ifindex); + return NULL; + } + if (value_to_set) + STREAM_GETC(s, *value_to_set); + +stream_failure: + return ifp; +} + /* * format of message for address addition is: * 0 diff --git a/lib/zclient.h b/lib/zclient.h index 3759f94542ea..3aed2a4121fc 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -134,6 +134,7 @@ typedef enum { ZEBRA_INTERFACE_DISABLE_RADV, ZEBRA_NEXTHOP_LOOKUP_MRIB, ZEBRA_INTERFACE_LINK_PARAMS, + ZEBRA_INTERFACE_MPLS_SET, ZEBRA_MPLS_LABELS_ADD, ZEBRA_MPLS_LABELS_DELETE, ZEBRA_MPLS_LABELS_REPLACE, @@ -1055,6 +1056,12 @@ extern struct interface *zebra_interface_link_params_read(struct stream *s, bool *changed); extern size_t zebra_interface_link_params_write(struct stream *, struct interface *); +extern int zebra_send_interface_mpls_set(struct zclient *zclient, + vrf_id_t vrf_id, ifindex_t ifindex, + bool set); +extern struct interface *zebra_interface_mpls_set_read(struct stream *s, + vrf_id_t vrf_id, + bool *value_to_set); extern enum zclient_send_status zclient_send_get_label_chunk(struct zclient *zclient, uint8_t keep, uint32_t chunk_size, uint32_t base); diff --git a/tests/topotests/ldp_topo1/r1/zebra.conf b/tests/topotests/ldp_topo1/r1/zebra.conf index 55b4b0e9c656..877b93810347 100644 --- a/tests/topotests/ldp_topo1/r1/zebra.conf +++ b/tests/topotests/ldp_topo1/r1/zebra.conf @@ -9,6 +9,7 @@ interface r1-eth0 description to sw0 ip address 10.0.1.1/24 no link-detect + mpls auto ! ip forwarding ! diff --git a/tests/topotests/ldp_topo1/r2/zebra.conf b/tests/topotests/ldp_topo1/r2/zebra.conf index dd1dbac32b8a..688aece30e03 100644 --- a/tests/topotests/ldp_topo1/r2/zebra.conf +++ b/tests/topotests/ldp_topo1/r2/zebra.conf @@ -9,16 +9,19 @@ interface r2-eth0 description to sw0 ip address 10.0.1.2/24 no link-detect + mpls auto ! interface r2-eth1 description to sw1 ip address 10.0.2.2/24 no link-detect + mpls auto ! interface r2-eth2 description to sw2 ip address 10.0.3.2/24 no link-detect + mpls auto ! ip forwarding ! diff --git a/tests/topotests/ldp_topo1/r3/zebra.conf b/tests/topotests/ldp_topo1/r3/zebra.conf index 456820fdb48a..dd76f9ea1468 100644 --- a/tests/topotests/ldp_topo1/r3/zebra.conf +++ b/tests/topotests/ldp_topo1/r3/zebra.conf @@ -9,11 +9,13 @@ interface r3-eth0 description to sw1 ip address 10.0.2.3/24 no link-detect + mpls auto ! interface r3-eth1 description to sw2 ip address 10.0.3.3/24 no link-detect + mpls auto ! ip forwarding ! diff --git a/tests/topotests/ldp_topo1/r4/zebra.conf b/tests/topotests/ldp_topo1/r4/zebra.conf index 4a270af578f6..149dc19b52b3 100644 --- a/tests/topotests/ldp_topo1/r4/zebra.conf +++ b/tests/topotests/ldp_topo1/r4/zebra.conf @@ -9,6 +9,7 @@ interface r4-eth0 description to sw1 ip address 10.0.2.4/24 no link-detect + mpls auto ! ip forwarding ! diff --git a/tests/topotests/ldp_topo1/test_ldp_topo1.py b/tests/topotests/ldp_topo1/test_ldp_topo1.py index fdd75581a3ec..0ccee8095f4f 100644 --- a/tests/topotests/ldp_topo1/test_ldp_topo1.py +++ b/tests/topotests/ldp_topo1/test_ldp_topo1.py @@ -75,7 +75,6 @@ def build_topo(tgen): - # Setup Routers for i in range(1, 5): tgen.add_router("r%s" % i) @@ -134,6 +133,7 @@ def setup_module(module): tgen.start_topology() net = tgen.net + os.environ["TOPOTESTS_MPLS_AUTO"] = "1" # Starting Routers for i in range(1, 5): @@ -781,6 +781,37 @@ def test_linux_mpls_routes(): assert fatal_error == "", fatal_error +def _check_mpls_interface_set(rname, ifname, value): + tgen = get_topogen() + val = ( + tgen.net[rname] + .cmd_raises("sysctl -n " + "net.mpls.conf." + ifname + ".input") + .strip() + ) + assert ( + val == value + ), f"{rname}, interface {ifname} has MPLS flag set to {val}, unexpected" + + +def test_linux_mpls_interface_settings(): + global fatal_error + + # Skip if previous fatal error condition is raised + if fatal_error != "": + pytest.skip(fatal_error) + + # Verify Linux Kernel MPLS settings + print("\n\n** Verifying Linux MPLS interface settings") + print("******************************************\n") + _check_mpls_interface_set("r1", "r1-eth0", "1") + _check_mpls_interface_set("r2", "r2-eth0", "1") + _check_mpls_interface_set("r2", "r2-eth1", "1") + _check_mpls_interface_set("r2", "r2-eth2", "1") + _check_mpls_interface_set("r3", "r3-eth0", "1") + _check_mpls_interface_set("r3", "r3-eth1", "1") + _check_mpls_interface_set("r4", "r4-eth0", "1") + + def test_shutdown_check_stderr(): global fatal_error net = get_topogen().net @@ -837,7 +868,6 @@ def test_shutdown_check_memleak(): if __name__ == "__main__": - # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli # retval = pytest.main(["-s", "--tb=no"]) retval = pytest.main(["-s"]) diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index f49e30ea5f9c..c679de905d37 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -907,9 +907,13 @@ def start(self): daemon=daemon, ) + if nrouter.daemons["ldpd"] == 1 and not os.environ.get("TOPOTESTS_MPLS_AUTO"): + need_mpls_for_ldp = True + else: + need_mpls_for_ldp = False if result != "": self.tgen.set_error(result) - elif nrouter.daemons["ldpd"] == 1 or nrouter.daemons["pathd"] == 1: + elif need_mpls_for_ldp or nrouter.daemons["pathd"] == 1: # Enable MPLS processing on all interfaces. for interface in self.links: topotest.sysctl_assure( diff --git a/zebra/interface.c b/zebra/interface.c index 30767eff16ae..72506497fb6b 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -3974,6 +3974,23 @@ void mpls_auto_interface_data_off(struct interface *ifp) mpls_auto_interface_data_internal(ifp, false); } +void zebra_interface_mpls_set(ZAPI_HANDLER_ARGS) +{ + struct interface *ifp; + bool mpls = false; + struct stream *s; + + s = msg; + ifp = zebra_interface_mpls_set_read(s, zvrf->vrf->vrf_id, &mpls); + if (!ifp) + return; + + if (mpls) + mpls_auto_interface_data_on(ifp); + else + mpls_auto_interface_data_off(ifp); +} + /* Allocate and initialize interface vector. */ void zebra_if_init(void) { diff --git a/zebra/interface.h b/zebra/interface.h index 7a9daf9a00b6..9a0f5b0ba983 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -17,6 +17,7 @@ #include "zebra/zebra_nhg_private.h" #include "zebra/zebra_router.h" #include "zebra/rtadv.h" +#include "zebra/zserv.h" #ifdef __cplusplus extern "C" { @@ -354,6 +355,8 @@ extern const char *zebra_protodown_rc_str(uint32_t protodown_rc, char *pd_buf, uint32_t pd_buf_len); extern void mpls_auto_interface_data_off(struct interface *ifp); extern void mpls_auto_interface_data_on(struct interface *ifp); +extern void zebra_interface_mpls_set(struct zserv *client, struct zmsghdr *hdr, + struct stream *msg, struct zebra_vrf *zvrf); void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx); #ifdef HAVE_PROC_NET_DEV diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 612f47751ebd..e1e152027e10 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -3908,6 +3908,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register, [ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable, [ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable, + [ZEBRA_INTERFACE_MPLS_SET] = zebra_interface_mpls_set, [ZEBRA_SR_POLICY_SET] = zread_sr_policy_set, [ZEBRA_SR_POLICY_DELETE] = zread_sr_policy_delete, [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels_add, From 8ace9667184371c57cd0ed3acf0a839db5ba384e Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 19 Dec 2023 12:17:22 +0100 Subject: [PATCH 8/8] zebra: change default mpls interface settings to auto mode Change the default MPLS setting per interface to auto mode. Signed-off-by: Philippe Guibert --- zebra/zebra_defaults.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra/zebra_defaults.h b/zebra/zebra_defaults.h index adfa16413cab..4383600da870 100644 --- a/zebra/zebra_defaults.h +++ b/zebra/zebra_defaults.h @@ -22,7 +22,7 @@ FRR_CFG_DEFAULT_BOOL(ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT, ); FRR_CFG_DEFAULT_UINT8_T(ZEBRA_MPLS, - { .val_uint8_t = IF_ZEBRA_DATA_UNSPEC }, + { .val_uint8_t = IF_ZEBRA_DATA_AUTO }, ); #ifdef __cplusplus