From a69b10c1e6a0f2e41f08eaef0724b360ef41611d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Jun 2022 13:13:10 -0400 Subject: [PATCH 1/5] zebra: Cleanup unguarded debug Left over debug from earlier commits Signed-off-by: Donald Sharp --- zebra/zebra_nhg.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 660ac1f102..c5b533fc22 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -1613,9 +1613,6 @@ void zebra_nhg_free(struct nhg_hash_entry *nhe) THREAD_OFF(nhe->timer); - if (nhe->refcnt) - zlog_debug("nhe_id=%pNG hash refcnt=%d", nhe, nhe->refcnt); - zebra_nhg_free_members(nhe); XFREE(MTYPE_NHG, nhe); From e63831f1336beb25192e3a55143c46abe4a55210 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Jun 2022 09:05:17 -0400 Subject: [PATCH 2/5] zebra: Add IF_ZEBRA_DATA_X define There are 2 defines IF_ZEBRA_MULTICAST_X and IF_ZEBRA_SHUTDOWN_X macros that do the same thing. Combine into one. Future commits will use the IF_ZEBRA_DATA_X macro as well. Signed-off-by: Donald Sharp --- zebra/interface.c | 59 +++++++++++++++++++++++------------------------ zebra/interface.h | 12 ++++------ 2 files changed, 33 insertions(+), 38 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index de7db2d48f..c66f103b33 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -147,8 +147,8 @@ static int if_zebra_new_hook(struct interface *ifp) zebra_if = XCALLOC(MTYPE_ZINFO, sizeof(struct zebra_if)); zebra_if->ifp = ifp; - zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC; - zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF; + zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC; + zebra_if->shutdown = IF_ZEBRA_DATA_OFF; zebra_if_nhg_dependents_init(zebra_if); @@ -583,9 +583,9 @@ void if_add_update(struct interface *ifp) if_data = ifp->info; assert(if_data); - if (if_data->multicast == IF_ZEBRA_MULTICAST_ON) + if (if_data->multicast == IF_ZEBRA_DATA_ON) if_set_flags(ifp, IFF_MULTICAST); - else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF) + else if (if_data->multicast == IF_ZEBRA_DATA_OFF) if_unset_flags(ifp, IFF_MULTICAST); zebra_ptm_if_set_ptm_state(ifp, if_data); @@ -595,7 +595,7 @@ void if_add_update(struct interface *ifp) if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { SET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE); - if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) { + if (if_data->shutdown == IF_ZEBRA_DATA_ON) { if (IS_ZEBRA_DEBUG_KERNEL) { zlog_debug( "interface %s vrf %s(%u) index %d is shutdown. Won't wake it up.", @@ -2908,7 +2908,7 @@ int if_multicast_set(struct interface *ifp) if_refresh(ifp); } if_data = ifp->info; - if_data->multicast = IF_ZEBRA_MULTICAST_ON; + if_data->multicast = IF_ZEBRA_DATA_ON; return 0; } @@ -2931,7 +2931,7 @@ DEFUN (multicast, if_refresh(ifp); } if_data = ifp->info; - if_data->multicast = IF_ZEBRA_MULTICAST_ON; + if_data->multicast = IF_ZEBRA_DATA_ON; return CMD_SUCCESS; } @@ -2949,7 +2949,7 @@ int if_multicast_unset(struct interface *ifp) if_refresh(ifp); } if_data = ifp->info; - if_data->multicast = IF_ZEBRA_MULTICAST_OFF; + if_data->multicast = IF_ZEBRA_DATA_OFF; return 0; } @@ -2973,7 +2973,7 @@ DEFUN (no_multicast, if_refresh(ifp); } if_data = ifp->info; - if_data->multicast = IF_ZEBRA_MULTICAST_OFF; + if_data->multicast = IF_ZEBRA_DATA_OFF; return CMD_SUCCESS; } @@ -3039,7 +3039,7 @@ int if_shutdown(struct interface *ifp) if_refresh(ifp); } if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON; + if_data->shutdown = IF_ZEBRA_DATA_ON; return 0; } @@ -3064,7 +3064,7 @@ DEFUN (shutdown_if, if_refresh(ifp); } if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON; + if_data->shutdown = IF_ZEBRA_DATA_ON; return CMD_SUCCESS; } @@ -3088,7 +3088,7 @@ int if_no_shutdown(struct interface *ifp) } if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF; + if_data->shutdown = IF_ZEBRA_DATA_OFF; return 0; } @@ -3119,7 +3119,7 @@ DEFUN (no_shutdown_if, } if_data = ifp->info; - if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF; + if_data->shutdown = IF_ZEBRA_DATA_OFF; return CMD_SUCCESS; } @@ -3906,9 +3906,9 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix, SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); /* In case of this route need to install kernel. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) - && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) - && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) && + CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) && + !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) { /* Some system need to up the interface to set IP address. */ if (!if_is_up(ifp)) { if_set_flags(ifp, IFF_UP | IFF_RUNNING); @@ -4001,9 +4001,9 @@ static int ip_address_install(struct vty *vty, struct interface *ifp, SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); /* In case of this route need to install kernel. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) - && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) - && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) && + CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) && + !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) { /* Some system need to up the interface to set IP address. */ if (!if_is_up(ifp)) { if_set_flags(ifp, IFF_UP | IFF_RUNNING); @@ -4264,9 +4264,9 @@ int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix, SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); /* In case of this route need to install kernel. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) - && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) - && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) && + CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) && + !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) { /* Some system need to up the interface to set IP address. */ if (!if_is_up(ifp)) { if_set_flags(ifp, IFF_UP | IFF_RUNNING); @@ -4337,9 +4337,9 @@ static int ipv6_address_install(struct vty *vty, struct interface *ifp, SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED); /* In case of this route need to install kernel. */ - if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) - && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) - && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) { + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) && + CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) && + !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) { /* Some system need to up the interface to set IP address. */ if (!if_is_up(ifp)) { if_set_flags(ifp, IFF_UP | IFF_RUNNING); @@ -4524,7 +4524,7 @@ static int if_config_write(struct vty *vty) if_vty_config_start(vty, ifp); if (if_data) { - if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) + if (if_data->shutdown == IF_ZEBRA_DATA_ON) vty_out(vty, " shutdown\n"); zebra_ptm_if_write(vty, if_data); @@ -4574,11 +4574,10 @@ static int if_config_write(struct vty *vty) } if (if_data) { - if (if_data->multicast - != IF_ZEBRA_MULTICAST_UNSPEC) + if (if_data->multicast != IF_ZEBRA_DATA_UNSPEC) vty_out(vty, " %smulticast\n", - if_data->multicast - == IF_ZEBRA_MULTICAST_ON + if_data->multicast == + IF_ZEBRA_DATA_ON ? "" : "no "); } diff --git a/zebra/interface.h b/zebra/interface.h index f3f41b90c5..801078e83d 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -36,14 +36,10 @@ extern "C" { #endif -/* For interface multicast configuration. */ -#define IF_ZEBRA_MULTICAST_UNSPEC 0 -#define IF_ZEBRA_MULTICAST_ON 1 -#define IF_ZEBRA_MULTICAST_OFF 2 - -/* For interface shutdown configuration. */ -#define IF_ZEBRA_SHUTDOWN_OFF 0 -#define IF_ZEBRA_SHUTDOWN_ON 1 +/* For interface configuration. */ +#define IF_ZEBRA_DATA_UNSPEC 0 +#define IF_ZEBRA_DATA_ON 1 +#define IF_ZEBRA_DATA_OFF 2 #define IF_VLAN_BITMAP_MAX 4096 From c87f5c23922a17738111fff767501717d7b1b933 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 28 Jun 2022 14:58:55 -0400 Subject: [PATCH 3/5] zebra: Notice when an interface is turned on w/ mpls and enable mpls subsystem Currently when FRR starts up it queries the kernel to see if mpls is turned on. If not FRR does not enable zebra's mpls subsection. If at a later time mpls is turned on, let's notice that an interface now is enabled for mpls( thus implying that all the bits and bobs in the kernel are now setup properly ). a) convert mpls_enabled to a bool b) abstract a new function zebra_mpls_turned_on and call it when FRR notices that an interface now has mpls enabled. c) mpls_processq_init cannot fail, so actually notice that and don't have special code to detect a failure. New results: sharpd@eva ~> vtysh -c "show zebra" OS Linux(5.10.0-12-amd64) ECMP Maximum 128 v4 Forwarding On v6 Forwarding On MPLS Off EVPN Off Kernel socket buffer size 90000000 VRF l3mdev Available ASIC offload Unavailable RA Compiled in RFC 5549 BGP is not using Kernel NHG Available v4 All LinkDown Routes Off v4 Default LinkDown Routes Off v6 All LinkDown Routes Off v6 Default LinkDown Routes Off v4 All MC Forwarding On v4 Default MC Forwarding Off v6 All MC Forwarding On v6 Default MC Forwarding Off Route Route Neighbor LSP LSP VRF Installs Removals Updates Installs Removals default 26 7 0 0 0 : sharpd@eva ~> sudo sysctl -w net.mpls.conf.enp39s0.input=1 [sudo] password for sharpd: net.mpls.conf.enp39s0.input = 1 sharpd@eva ~> vtysh -c "show zebra" OS Linux(5.10.0-12-amd64) ECMP Maximum 128 v4 Forwarding On v6 Forwarding On MPLS On EVPN Off Kernel socket buffer size 90000000 VRF l3mdev Available ASIC offload Unavailable RA Compiled in RFC 5549 BGP is not using Kernel NHG Available v4 All LinkDown Routes Off v4 Default LinkDown Routes Off v6 All LinkDown Routes Off v6 Default LinkDown Routes Off v4 All MC Forwarding On v4 Default MC Forwarding Off v6 All MC Forwarding On v6 Default MC Forwarding Off Route Route Neighbor LSP LSP VRF Installs Removals Updates Installs Removals default 26 7 0 0 0 sharpd@eva ~> I am doing this work because FRR keeps having operators not know about how to properly use mpls. Let's make FRR behave a bit better in this weird edge case. Signed-off-by: Donald Sharp --- zebra/interface.c | 5 +++-- zebra/zebra_mpls.c | 30 +++++++++++++++--------------- zebra/zebra_mpls.h | 9 ++++++++- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index c66f103b33..b1f59a4e4f 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1453,9 +1453,10 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx, /* * mpls netconf data is neither v4 or v6 it's AF_MPLS! */ - if (mpls == DPLANE_NETCONF_STATUS_ENABLED) + if (mpls == DPLANE_NETCONF_STATUS_ENABLED) { zif->mpls = true; - else if (mpls == DPLANE_NETCONF_STATUS_DISABLED) + zebra_mpls_turned_on(); + } else if (mpls == DPLANE_NETCONF_STATUS_DISABLED) zif->mpls = false; } diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index caac3e3230..ade381e27f 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -53,7 +53,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object"); DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object"); DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object"); -int mpls_enabled; +bool mpls_enabled; bool mpls_pw_reach_strict; /* Strict reachability checking */ /* static function declarations */ @@ -1748,14 +1748,9 @@ static int lsp_cmp(const struct zebra_lsp *lsp1, const struct zebra_lsp *lsp2) /* * Initialize work queue for processing changed LSPs. */ -static int mpls_processq_init(void) +static void mpls_processq_init(void) { zrouter.lsp_process_q = work_queue_new(zrouter.master, "LSP processing"); - if (!zrouter.lsp_process_q) { - flog_err(EC_ZEBRA_WQ_NONEXISTENT, - "%s: could not initialise work queue!", __func__); - return -1; - } zrouter.lsp_process_q->spec.workfunc = &lsp_process; zrouter.lsp_process_q->spec.del_item_data = &lsp_processq_del; @@ -1763,8 +1758,6 @@ static int mpls_processq_init(void) zrouter.lsp_process_q->spec.completion_func = &lsp_processq_complete; zrouter.lsp_process_q->spec.max_retries = 0; zrouter.lsp_process_q->spec.hold = 10; - - return 0; } @@ -4061,12 +4054,23 @@ void zebra_mpls_init_tables(struct zebra_vrf *zvrf) zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL; } +void zebra_mpls_turned_on(void) +{ + if (!mpls_enabled) { + mpls_processq_init(); + mpls_enabled = true; + } + + hook_register(zserv_client_close, zebra_mpls_cleanup_fecs_for_client); + hook_register(zserv_client_close, zebra_mpls_cleanup_zclient_labels); +} + /* * Global MPLS initialization. */ void zebra_mpls_init(void) { - mpls_enabled = 0; + mpls_enabled = false; mpls_pw_reach_strict = false; if (mpls_kernel_init() < 0) { @@ -4075,9 +4079,5 @@ void zebra_mpls_init(void) return; } - if (!mpls_processq_init()) - mpls_enabled = 1; - - hook_register(zserv_client_close, zebra_mpls_cleanup_fecs_for_client); - hook_register(zserv_client_close, zebra_mpls_cleanup_zclient_labels); + zebra_mpls_turned_on(); } diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index a8c4e1a60c..a7a955a80b 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -394,6 +394,13 @@ void zebra_mpls_close_tables(struct zebra_vrf *zvrf); */ void zebra_mpls_init_tables(struct zebra_vrf *zvrf); +/* + * If mpls is turned on *after* FRR is brought + * up let's actually notice this and turn on + * the relevant bits to make it work. + */ +void zebra_mpls_turned_on(void); + /* * Global MPLS initialization. */ @@ -569,7 +576,7 @@ static inline int mpls_should_lsps_be_processed(struct route_node *rn) } /* Global variables. */ -extern int mpls_enabled; +extern bool mpls_enabled; extern bool mpls_pw_reach_strict; /* Strict pseudowire reachability checking */ #ifdef __cplusplus From 39ffa8e8e8564e41020f5ecfa12441c013685e24 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Jun 2022 07:43:50 -0400 Subject: [PATCH 4/5] zebra: Add a `mpls enable` interface node command Allow individual interfaces to turn on/off the mpls subsystem for it in linux. sharpd@eva:~/frr9$ sudo sysctl -a | grep enp39s0 | grep mpls net.mpls.conf.enp39s0.input = 0 sharpd@eva:~/frr9$ vtysh -c "conf" -c "int enp39s0" -c "mpls enable" sharpd@eva:~/frr9$ sudo sysctl -a | grep enp39s0 | grep mpls net.mpls.conf.enp39s0.input = 1 sharpd@eva:~/frr9$ vtysh -c "conf" -c "int enp39s0" -c "no mpls enable" sharpd@eva:~/frr9$ sudo sysctl -a | grep enp39s0 | grep mpls net.mpls.conf.enp39s0.input = 0 sharpd@eva:~/frr9$ Signed-off-by: Donald Sharp --- doc/user/zebra.rst | 7 ++++++ zebra/if_socket.c | 11 +++++++++ zebra/interface.c | 24 +++++++++++++++++++ zebra/kernel_netlink.c | 4 +++- zebra/kernel_socket.c | 24 ++++++++++++++++--- zebra/netconf_netlink.c | 53 +++++++++++++++++++++++++++++++++++++++++ zebra/netconf_netlink.h | 4 ++++ zebra/rt.h | 3 +++ zebra/zebra_dplane.c | 50 ++++++++++++++++++++++++++++++++++++++ zebra/zebra_dplane.h | 2 ++ 10 files changed, 178 insertions(+), 4 deletions(-) diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index d96df0ce52..05990e2523 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -155,6 +155,13 @@ Standard Commands Set description for the interface. +.. clicmd:: mpls enable + + Enable or disable mpls kernel processing 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. + .. clicmd:: multicast diff --git a/zebra/if_socket.c b/zebra/if_socket.c index 309d5a3f3e..da9fadf7c7 100644 --- a/zebra/if_socket.c +++ b/zebra/if_socket.c @@ -38,4 +38,15 @@ enum zebra_dplane_result kernel_intf_update(struct zebra_dplane_ctx *ctx) return ZEBRA_DPLANE_REQUEST_FAILURE; } +enum zebra_dplane_result +kernel_intf_netconf_update(struct zebra_dplane_ctx *ctx) +{ + const char *ifname = dplane_ctx_get_ifname(ctx); + enum dplane_netconf_status_e mpls_on = dplane_ctx_get_netconf_mpls(ctx); + + zlog_warn("%s: Unable to set kernel mpls state for interface %s(%d)", + __func__, ifname, mpls_on); + + return ZEBRA_DPLANE_REQUEST_SUCCESS; +} #endif diff --git a/zebra/interface.c b/zebra/interface.c index b1f59a4e4f..b7a984e44d 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -2937,6 +2937,27 @@ DEFUN (multicast, return CMD_SUCCESS; } +DEFPY (mpls, + mpls_cmd, + "[no] mpls enable", + NO_STR + MPLS_STR + "Set mpls to be on for the interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct zebra_if *if_data = ifp->info; + + if (no) { + dplane_intf_mpls_modify_state(ifp, false); + if_data->mpls = IF_ZEBRA_DATA_UNSPEC; + } else { + dplane_intf_mpls_modify_state(ifp, true); + if_data->mpls = IF_ZEBRA_DATA_ON; + } + + return CMD_SUCCESS; +} + int if_multicast_unset(struct interface *ifp) { struct zebra_if *if_data; @@ -4581,6 +4602,8 @@ static int if_config_write(struct vty *vty) IF_ZEBRA_DATA_ON ? "" : "no "); + if (if_data->mpls == IF_ZEBRA_DATA_ON) + vty_out(vty, " mpls\n"); } hook_call(zebra_if_config_wr, vty, ifp); @@ -4617,6 +4640,7 @@ void zebra_if_init(void) install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd); install_element(INTERFACE_NODE, &multicast_cmd); install_element(INTERFACE_NODE, &no_multicast_cmd); + install_element(INTERFACE_NODE, &mpls_cmd); install_element(INTERFACE_NODE, &linkdetect_cmd); install_element(INTERFACE_NODE, &no_linkdetect_cmd); install_element(INTERFACE_NODE, &shutdown_if_cmd); diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 5c8aca9691..396ccb34bd 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1613,10 +1613,12 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth, case DPLANE_OP_INTF_ADDR_ADD: case DPLANE_OP_INTF_ADDR_DEL: - case DPLANE_OP_INTF_NETCONFIG: case DPLANE_OP_NONE: return FRR_NETLINK_ERROR; + case DPLANE_OP_INTF_NETCONFIG: + return netlink_put_intf_netconfig(bth, ctx); + case DPLANE_OP_INTF_INSTALL: case DPLANE_OP_INTF_UPDATE: case DPLANE_OP_INTF_DELETE: diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 2741a23242..076e9c4dfa 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -1529,7 +1529,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list) { struct zebra_dplane_ctx *ctx; struct dplane_ctx_q handled_list; - enum zebra_dplane_result res; + enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS; TAILQ_INIT(&handled_list); @@ -1611,9 +1611,27 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list) res = ZEBRA_DPLANE_REQUEST_SUCCESS; break; - default: - res = ZEBRA_DPLANE_REQUEST_FAILURE; + case DPLANE_OP_INTF_NETCONFIG: + res = kernel_intf_netconf_update(ctx); break; + + case DPLANE_OP_NONE: + case DPLANE_OP_BR_PORT_UPDATE: + case DPLANE_OP_IPTABLE_ADD: + case DPLANE_OP_IPTABLE_DELETE: + case DPLANE_OP_IPSET_ADD: + case DPLANE_OP_IPSET_DELETE: + case DPLANE_OP_IPSET_ENTRY_ADD: + case DPLANE_OP_IPSET_ENTRY_DELETE: + case DPLANE_OP_NEIGH_IP_INSTALL: + case DPLANE_OP_NEIGH_IP_DELETE: + case DPLANE_OP_NEIGH_TABLE_UPDATE: + case DPLANE_OP_GRE_SET: + case DPLANE_OP_INTF_ADDR_ADD: + case DPLANE_OP_INTF_ADDR_DEL: + zlog_err("Unhandled dplane data for %s", + dplane_op2str(dplane_ctx_get_op(ctx))); + res = ZEBRA_DPLANE_REQUEST_FAILURE; } skip_one: diff --git a/zebra/netconf_netlink.c b/zebra/netconf_netlink.c index f9cb37a3cf..56f56bfe66 100644 --- a/zebra/netconf_netlink.c +++ b/zebra/netconf_netlink.c @@ -29,6 +29,7 @@ #include "linux/netconf.h" +#include "lib/lib_errors.h" #include "zebra/zebra_ns.h" #include "zebra/zebra_dplane.h" #include "zebra/kernel_netlink.h" @@ -185,4 +186,56 @@ int netlink_request_netconf(int sockfd) return netlink_request(nls, &req); } +extern struct zebra_privs_t zserv_privs; +/* + * Currently netconf has no ability to set from netlink. + * So we've received a request to do this work in the data plane. + * as such we need to set the value via the /proc system + */ +enum netlink_msg_status netlink_put_intf_netconfig(struct nl_batch *bth, + struct zebra_dplane_ctx *ctx) +{ + const char *ifname = dplane_ctx_get_ifname(ctx); + enum dplane_netconf_status_e mpls_on = dplane_ctx_get_netconf_mpls(ctx); + char set[64]; + char mpls_proc[PATH_MAX]; + int fd, ret = FRR_NETLINK_ERROR; + + snprintf(mpls_proc, sizeof(mpls_proc), + "/proc/sys/net/mpls/conf/%s/input", ifname); + + if (mpls_on == DPLANE_NETCONF_STATUS_ENABLED) + snprintf(set, sizeof(set), "1\n"); + else if (mpls_on == DPLANE_NETCONF_STATUS_DISABLED) + snprintf(set, sizeof(set), "0\n"); + else { + flog_err_sys( + EC_LIB_DEVELOPMENT, + "%s: Expected interface %s to be set to ENABLED or DISABLED was %d", + __func__, ifname, mpls_on); + return ret; + } + + frr_with_privs (&zserv_privs) { + fd = open(mpls_proc, O_WRONLY); + if (fd < 0) { + flog_err_sys( + EC_LIB_SOCKET, + "%s: Unable to open %s for writing: %s(%d)", + __func__, mpls_proc, safe_strerror(errno), + errno); + return ret; + } + if (write(fd, set, 2) == 2) + ret = FRR_NETLINK_SUCCESS; + else + flog_err_sys(EC_LIB_SOCKET, + "%s: Unsuccessful write to %s: %s(%d)", + __func__, mpls_proc, safe_strerror(errno), + errno); + close(fd); + } + return ret; +} + #endif /* HAVE_NETLINK */ diff --git a/zebra/netconf_netlink.h b/zebra/netconf_netlink.h index 3f2e7af768..1b3450bcb5 100644 --- a/zebra/netconf_netlink.h +++ b/zebra/netconf_netlink.h @@ -38,6 +38,10 @@ extern int netlink_netconf_change(struct nlmsghdr *h, ns_id_t ns_id, /* Request info from the host OS. */ int netlink_request_netconf(int sockfd); +struct nl_batch; + +extern enum netlink_msg_status +netlink_put_intf_netconfig(struct nl_batch *bth, struct zebra_dplane_ctx *ctx); #ifdef __cplusplus } diff --git a/zebra/rt.h b/zebra/rt.h index 4952c3eb1a..0a86a2897c 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -69,6 +69,9 @@ kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx); extern enum zebra_dplane_result kernel_intf_update(struct zebra_dplane_ctx *ctx); +extern enum zebra_dplane_result +kernel_intf_netconf_update(struct zebra_dplane_ctx *ctx); + #endif /* !HAVE_NETLINK */ extern int kernel_neigh_update(int cmd, int ifindex, void *addr, char *lla, diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index a4330a3200..4c7838198e 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -509,6 +509,8 @@ static struct zebra_dplane_globals { _Atomic uint32_t dg_intf_addrs_in; _Atomic uint32_t dg_intf_addr_errors; + _Atomic uint32_t dg_intf_changes; + _Atomic uint32_t dg_intf_changes_errors; _Atomic uint32_t dg_macs_in; _Atomic uint32_t dg_mac_errors; @@ -3913,6 +3915,47 @@ dplane_br_port_update(const struct interface *ifp, bool non_df, return result; } +enum zebra_dplane_result +dplane_intf_mpls_modify_state(const struct interface *ifp, bool set) +{ + enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; + struct zebra_dplane_ctx *ctx; + struct zebra_ns *zns; + int ret = EINVAL; + + ctx = dplane_ctx_alloc(); + ctx->zd_op = DPLANE_OP_INTF_NETCONFIG; + ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + ctx->zd_vrf_id = ifp->vrf->vrf_id; + strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname)); + + zns = zebra_ns_lookup(ifp->vrf->vrf_id); + dplane_ctx_ns_init(ctx, zns, false); + + ctx->zd_ifindex = ifp->ifindex; + if (set) + dplane_ctx_set_netconf_mpls(ctx, DPLANE_NETCONF_STATUS_ENABLED); + else + dplane_ctx_set_netconf_mpls(ctx, + DPLANE_NETCONF_STATUS_DISABLED); + /* Increment counter */ + atomic_fetch_add_explicit(&zdplane_info.dg_intf_changes, 1, + memory_order_relaxed); + + ret = dplane_update_enqueue(ctx); + + if (ret == AOK) + result = ZEBRA_DPLANE_REQUEST_QUEUED; + else { + /* Error counter */ + atomic_fetch_add_explicit(&zdplane_info.dg_intf_changes_errors, + 1, memory_order_relaxed); + dplane_ctx_free(&ctx); + } + + return result; +} + /* * Enqueue interface address add for the dataplane. */ @@ -4900,6 +4943,13 @@ int dplane_show_helper(struct vty *vty, bool detailed) vty_out(vty, "Intf addr updates: %"PRIu64"\n", incoming); vty_out(vty, "Intf addr errors: %"PRIu64"\n", errs); + incoming = atomic_load_explicit(&zdplane_info.dg_intf_changes, + memory_order_relaxed); + errs = atomic_load_explicit(&zdplane_info.dg_intf_changes_errors, + memory_order_relaxed); + vty_out(vty, "Intf change updates: %" PRIu64 "\n", incoming); + vty_out(vty, "Intf change errors: %" PRIu64 "\n", errs); + incoming = atomic_load_explicit(&zdplane_info.dg_macs_in, memory_order_relaxed); errs = atomic_load_explicit(&zdplane_info.dg_mac_errors, diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index d940bd9568..c96ea40094 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -690,6 +690,8 @@ enum zebra_dplane_result dplane_lsp_notif_update(struct zebra_lsp *lsp, enum zebra_dplane_result dplane_pw_install(struct zebra_pw *pw); enum zebra_dplane_result dplane_pw_uninstall(struct zebra_pw *pw); +enum zebra_dplane_result +dplane_intf_mpls_modify_state(const struct interface *ifp, const bool set); /* * Enqueue interface address changes for the dataplane. */ From cbc08d1fb9f511323363fd3578ed7b1a5f9a6859 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 29 Jun 2022 13:20:11 -0400 Subject: [PATCH 5/5] tests: Convert one test to use interface based mpls config To prove that this works. Modify a test that uses mpls to turn on mpls for the interfaces that need mpls via the new mpls command. Signed-off-by: Donald Sharp --- .../bgp_l3vpn_to_bgp_direct/customize.py | 16 ---------------- .../bgp_l3vpn_to_bgp_direct/r1/zebra.conf | 3 +++ .../bgp_l3vpn_to_bgp_direct/r2/zebra.conf | 4 ++++ .../bgp_l3vpn_to_bgp_direct/r3/zebra.conf | 3 +++ .../bgp_l3vpn_to_bgp_direct/r4/zebra.conf | 3 +++ 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py index 36bfdfe068..c0a5c7ad9c 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py @@ -137,22 +137,6 @@ def ltemplatePreRouterStartHook(): if tgen.hasmpls != True: logger.info("MPLS not available, skipping setup") return False - # configure r2 mpls interfaces - intfs = ["lo", "r2-eth0", "r2-eth1", "r2-eth2"] - for intf in intfs: - cc.doCmd(tgen, "r2", "echo 1 > /proc/sys/net/mpls/conf/{}/input".format(intf)) - # configure MPLS - rtrs = ["r1", "r3", "r4"] - cmds = ["echo 1 > /proc/sys/net/mpls/conf/lo/input"] - for rtr in rtrs: - router = tgen.gears[rtr] - for cmd in cmds: - cc.doCmd(tgen, rtr, cmd) - intfs = ["lo", rtr + "-eth0", rtr + "-eth4"] - for intf in intfs: - cc.doCmd( - tgen, rtr, "echo 1 > /proc/sys/net/mpls/conf/{}/input".format(intf) - ) logger.info("setup mpls input") return True diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/zebra.conf index 18f61e0c54..767e17e62c 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/zebra.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/zebra.conf @@ -3,15 +3,18 @@ log file zebra.log hostname r1 ! interface lo + mpls ip address 1.1.1.1/32 ! interface r1-eth0 description to sw0 + mpls ip address 10.0.1.1/24 no link-detect ! interface r1-eth4 description to ce1 + mpls ip address 192.168.1.1/24 no link-detect ! diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/zebra.conf index dd1dbac32b..829ac969e3 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/zebra.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/zebra.conf @@ -3,20 +3,24 @@ log file zebra.log hostname r2 ! interface lo + mpls ip address 2.2.2.2/32 ! interface r2-eth0 description to sw0 + mpls ip address 10.0.1.2/24 no link-detect ! interface r2-eth1 description to sw1 + mpls ip address 10.0.2.2/24 no link-detect ! interface r2-eth2 description to sw2 + mpls ip address 10.0.3.2/24 no link-detect ! diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/zebra.conf index 9dbc290243..916dabf37d 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/zebra.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/zebra.conf @@ -3,10 +3,12 @@ log file zebra.log hostname r3 ! interface lo + mpls ip address 3.3.3.3/32 ! interface r3-eth0 description to sw1 + mpls ip address 10.0.2.3/24 no link-detect ! @@ -17,6 +19,7 @@ interface r3-eth1 ! interface r3-eth4 description to ce2 + mpls ip address 192.168.1.1/24 no link-detect ! diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/zebra.conf index 415f03df51..e08ac86aec 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/zebra.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/zebra.conf @@ -3,15 +3,18 @@ log file zebra.log hostname r4 ! interface lo + mpls ip address 4.4.4.4/32 ! interface r4-eth0 description to sw1 + mpls ip address 10.0.2.4/24 no link-detect ! interface r4-eth4 description to ce3 + mpls ip address 192.168.1.1/24 no link-detect !