diff options
| author | Donald Sharp <sharpd@nvidia.com> | 2022-06-29 07:43:50 -0400 | 
|---|---|---|
| committer | Donald Sharp <sharpd@nvidia.com> | 2022-08-08 09:15:22 -0400 | 
| commit | 39ffa8e8e8564e41020f5ecfa12441c013685e24 (patch) | |
| tree | 87e885926c2aa8fc269633090983d7a299a4e748 /zebra | |
| parent | c87f5c23922a17738111fff767501717d7b1b933 (diff) | |
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 <sharpd@nvidia.com>
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/if_socket.c | 11 | ||||
| -rw-r--r-- | zebra/interface.c | 24 | ||||
| -rw-r--r-- | zebra/kernel_netlink.c | 4 | ||||
| -rw-r--r-- | zebra/kernel_socket.c | 24 | ||||
| -rw-r--r-- | zebra/netconf_netlink.c | 53 | ||||
| -rw-r--r-- | zebra/netconf_netlink.h | 4 | ||||
| -rw-r--r-- | zebra/rt.h | 3 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 50 | ||||
| -rw-r--r-- | zebra/zebra_dplane.h | 2 | 
9 files changed, 171 insertions, 4 deletions
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.   */  | 
