forked from Mirror/frr
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>
This commit is contained in:
parent
c87f5c2392
commit
39ffa8e8e8
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue