From bcebbb988da4fcbb6158c05050f96ae87cc50156 Mon Sep 17 00:00:00 2001 From: John Lo Date: Tue, 5 Apr 2016 15:47:43 -0400 Subject: [PATCH] Enhance CLI/API Support for Bonded Interface For interfaces which are slave links to a bounded interface, do not allow sub-interface creation nor interface state to be changed. Change "show interface" to display interface state as "bond-slave" for slave links to a bonded interface. Change "show hardware" to support a "bond" keyword and display slave links to a bonded interface. Change-Id: I4db3cae6985bcb1489ab16a07c72c5ee9b2f2dd3 Signed-off-by: John Lo --- vnet/vnet/api_errno.h | 3 ++- vnet/vnet/devices/dpdk/init.c | 34 ++++++++++++++++++++---------- vnet/vnet/interface.c | 9 ++++++++ vnet/vnet/interface.h | 11 ++++++++++ vnet/vnet/interface_cli.c | 49 ++++++++++++++++++++++++++++++++----------- vnet/vnet/interface_format.c | 31 ++++++++++++++++++++------- vpp/api/api.c | 5 +++++ 7 files changed, 111 insertions(+), 31 deletions(-) diff --git a/vnet/vnet/api_errno.h b/vnet/vnet/api_errno.h index 69535d3fa97..e59efd70c4e 100644 --- a/vnet/vnet/api_errno.h +++ b/vnet/vnet/api_errno.h @@ -69,7 +69,8 @@ _(TUNNEL_EXIST, -75, "Tunnel already exists") \ _(INVALID_DECAP_NEXT, -76, "Invalid decap-next") \ _(RESPONSE_NOT_READY, -77, "Response not ready") \ _(NOT_CONNECTED, -78, "Not connected to the data plane") \ -_(IF_ALREADY_EXISTS, -79, "Interface already exists") +_(IF_ALREADY_EXISTS, -79, "Interface already exists") \ +_(BOND_SLAVE_NOT_ALLOWED, -80, "Operation not allowed on slave of BondEthernet") typedef enum { #define _(a,b,c) VNET_API_ERROR_##a = (b), diff --git a/vnet/vnet/devices/dpdk/init.c b/vnet/vnet/devices/dpdk/init.c index e84f0de569b..822b05d4c11 100644 --- a/vnet/vnet/devices/dpdk/init.c +++ b/vnet/vnet/devices/dpdk/init.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -1622,23 +1623,34 @@ dpdk_process (vlib_main_t * vm, u8 slink[16]; int nlink = rte_eth_bond_slaves_get(i, slink, 16); if (nlink > 0) { - vnet_hw_interface_t * hi; - ethernet_interface_t * ei; + vnet_hw_interface_t * bhi; + ethernet_interface_t * bei; /* Get MAC of 1st slave link */ rte_eth_macaddr_get(slink[0], (struct ether_addr *)addr); /* Set MAC of bounded interface to that of 1st slave link */ rte_eth_bond_mac_address_set(i, (struct ether_addr *)addr); /* Populate MAC of bonded interface in VPP hw tables */ - hi = vnet_get_hw_interface ( + bhi = vnet_get_hw_interface( vnm, dm->devices[i].vlib_hw_if_index); - ei = pool_elt_at_index (em->interfaces, hi->hw_instance); - memcpy (hi->hw_address, addr, 6); - memcpy (ei->address, addr, 6); - /* Add MAC to other slave links */ - while (nlink > 1) { - nlink--; - rte_eth_dev_mac_addr_add( - slink[nlink], (struct ether_addr *)addr, 0); + bei = pool_elt_at_index(em->interfaces, bhi->hw_instance); + memcpy(bhi->hw_address, addr, 6); + memcpy(bei->address, addr, 6); + while (nlink >= 1) { /* for all slave links */ + int slave = slink[--nlink]; + dpdk_device_t * sdev = &dm->devices[slave]; + vnet_hw_interface_t * shi; + vnet_sw_interface_t * ssi; + /* Add MAC to all slave links except the first one */ + if (nlink) rte_eth_dev_mac_addr_add( + slave, (struct ether_addr *)addr, 0); + /* Set slaves bitmap for bonded interface */ + bhi->bond_info = clib_bitmap_set( + bhi->bond_info, sdev->vlib_hw_if_index, 1); + /* Set slave link flags on slave interface */ + shi = vnet_get_hw_interface(vnm, sdev->vlib_hw_if_index); + ssi = vnet_get_sw_interface(vnm, sdev->vlib_sw_if_index); + shi->bond_info = VNET_HW_INTERFACE_BOND_INFO_SLAVE; + ssi->flags |= VNET_SW_INTERFACE_FLAG_BOND_SLAVE; } } } diff --git a/vnet/vnet/interface.c b/vnet/vnet/interface.c index 6c8823f14bc..9189a4185d8 100644 --- a/vnet/vnet/interface.c +++ b/vnet/vnet/interface.c @@ -363,6 +363,15 @@ vnet_sw_interface_set_flags_helper (vnet_main_t * vnm, u32 sw_if_index, u32 flag } } + /* Donot change state for slave link of bonded interfaces */ + if (si->flags & VNET_SW_INTERFACE_FLAG_BOND_SLAVE) + { + error = clib_error_return + (0, "not allowed as %U belong to a BondEthernet interface", + format_vnet_sw_interface_name, vnm, si); + goto done; + } + /* Already in the desired state? */ if ((si->flags & mask) == flags) goto done; diff --git a/vnet/vnet/interface.h b/vnet/vnet/interface.h index 1ddd259a0b4..fdf23a6bd74 100644 --- a/vnet/vnet/interface.h +++ b/vnet/vnet/interface.h @@ -311,6 +311,15 @@ typedef struct vnet_hw_interface_t { /* Count of number of L2 subinterfaces */ u32 l2_if_count; + + /* Bonded interface info - + 0 - not a bonded interface nor a slave + ~0 - slave to a bonded interface + others - A bonded interface with a pointer to bitmap for all slaves */ + uword *bond_info; +#define VNET_HW_INTERFACE_BOND_INFO_NONE ((uword *) 0) +#define VNET_HW_INTERFACE_BOND_INFO_SLAVE ((uword *) ~0) + } vnet_hw_interface_t; typedef enum { @@ -364,6 +373,8 @@ typedef struct { #define VNET_SW_INTERFACE_FLAG_UNNUMBERED (1 << 3) +#define VNET_SW_INTERFACE_FLAG_BOND_SLAVE (1 << 4) + /* Index for this interface. */ u32 sw_if_index; diff --git a/vnet/vnet/interface_cli.c b/vnet/vnet/interface_cli.c index 94fb3916d4a..3b3da9b5b61 100644 --- a/vnet/vnet/interface_cli.c +++ b/vnet/vnet/interface_cli.c @@ -39,6 +39,7 @@ #include #include +#include static int compare_interface_names (void *a1, void *a2) { @@ -58,28 +59,21 @@ show_or_clear_hw_interfaces (vlib_main_t * vm, vnet_interface_main_t * im = &vnm->interface_main; vnet_hw_interface_t * hi; u32 hw_if_index, * hw_if_indices = 0; - int i, verbose = 1, is_show; + int i, verbose = -1, is_show, show_bond = 0; is_show = strstr (cmd->path, "show") != 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { /* See if user wants to show a specific interface. */ if (unformat (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index)) - { vec_add1 (hw_if_indices, hw_if_index); - /* Implies verbose. */ - verbose = 1; - } + /* See if user wants to show an interface with a specific hw_if_index. */ else if (unformat (input, "%u", &hw_if_index)) - { vec_add1 (hw_if_indices, hw_if_index); - /* Implies verbose. */ - verbose = 1; - } else if (unformat (input, "verbose")) - verbose = 1; + verbose = 1; /* this is also the default */ else if (unformat (input, "detail")) verbose = 2; @@ -87,6 +81,12 @@ show_or_clear_hw_interfaces (vlib_main_t * vm, else if (unformat (input, "brief")) verbose = 0; + else if (unformat (input, "bond")) + { + show_bond = 1; + if (verbose < 0) verbose = 0; /* default to brief for link bonding */ + } + else { error = clib_error_return (0, "unknown input `%U'", @@ -100,6 +100,8 @@ show_or_clear_hw_interfaces (vlib_main_t * vm, pool_foreach (hi, im->hw_interfaces, vec_add1 (hw_if_indices, hi - im->hw_interfaces)); + if (verbose < 0) verbose = 1; /* default to verbose (except bond) */ + if (is_show) { /* Sort by name. */ @@ -109,7 +111,23 @@ show_or_clear_hw_interfaces (vlib_main_t * vm, for (i = 0; i < vec_len (hw_if_indices); i++) { hi = vnet_get_hw_interface (vnm, hw_if_indices[i]); - vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm, hi, verbose); + if (show_bond == 0) /* show all interfaces */ + vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm, + hi, verbose); + else if ((hi->bond_info) && + (hi->bond_info != VNET_HW_INTERFACE_BOND_INFO_SLAVE)) + { /* show only bonded interface and all its slave interfaces */ + int hw_idx; + vnet_hw_interface_t * shi; + vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm, + hi, verbose); + clib_bitmap_foreach (hw_idx, hi->bond_info, + ({ + shi = vnet_get_hw_interface(vnm, hw_idx); + vlib_cli_output (vm, "%U\n", + format_vnet_hw_interface, vnm, shi, verbose); + })); + } } } else @@ -133,7 +151,7 @@ show_or_clear_hw_interfaces (vlib_main_t * vm, VLIB_CLI_COMMAND (show_hw_interfaces_command, static) = { .path = "show hardware-interfaces", - .short_help = "show hardware-interfaces [verbose|brief] [ ...]", + .short_help = "show hardware-interfaces [brief|verbose|detail] [bond] [ ...]", .function = show_or_clear_hw_interfaces, }; @@ -556,6 +574,13 @@ create_sub_interfaces (vlib_main_t * vm, */ hi = vnet_get_hw_interface (vnm, hw_if_index); + + if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE) { + error = clib_error_return ( + 0, "not allowed as %v belong to a BondEthernet interface", hi->name); + goto done; + } + for (id = id_min; id <= id_max; id++) { uword * p; diff --git a/vnet/vnet/interface_format.c b/vnet/vnet/interface_format.c index 1ebbfb12e06..840e72b61d7 100644 --- a/vnet/vnet/interface_format.c +++ b/vnet/vnet/interface_format.c @@ -38,14 +38,21 @@ */ #include +#include u8 * format_vnet_sw_interface_flags (u8 * s, va_list * args) { u32 flags = va_arg (*args, u32); - s = format (s, "%s", (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "down"); - if (flags & VNET_SW_INTERFACE_FLAG_PUNT) - s = format (s, "/punt"); + if (flags & VNET_SW_INTERFACE_FLAG_BOND_SLAVE) + s = format (s, "bond-slave"); + else + { + s = format (s, "%s", + (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "down"); + if (flags & VNET_SW_INTERFACE_FLAG_PUNT) + s = format (s, "/punt"); + } return s; } @@ -65,14 +72,24 @@ u8 * format_vnet_hw_interface (u8 * s, va_list * args) indent = format_get_indent (s); - s = format (s, "%-32v%=6d%=8s", - hi->name, hi->hw_if_index, - hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP ? "up" : "down"); + s = format (s, "%-32v%=6d", hi->name, hi->hw_if_index); + + if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE) + s = format (s, "%=8s", "slave"); + else + s = format (s, "%=8s", + hi->flags & VNET_HW_INTERFACE_FLAG_LINK_UP ? "up" : "down"); hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index); dev_class = vnet_get_device_class (vnm, hi->dev_class_index); - if (dev_class->format_device_name) + if (hi->bond_info && (hi->bond_info != VNET_HW_INTERFACE_BOND_INFO_SLAVE)) + { + int hw_idx; + s = format (s, "Slave-Idx:"); + clib_bitmap_foreach (hw_idx, hi->bond_info, format(s, " %d", hw_idx)); + } + else if (dev_class->format_device_name) s = format (s, "%U", dev_class->format_device_name, hi->dev_instance); else s = format (s, "%s%d", dev_class->name, hi->dev_instance); diff --git a/vpp/api/api.c b/vpp/api/api.c index 9867b596216..aaa4be58f55 100644 --- a/vpp/api/api.c +++ b/vpp/api/api.c @@ -1859,6 +1859,11 @@ vl_api_create_subif_t_handler (vl_api_create_subif_t * mp) si = vnet_get_sup_sw_interface (vnm, ntohl(mp->sw_if_index)); hi = vnet_get_sup_hw_interface (vnm, ntohl(mp->sw_if_index)); + if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE) { + rv = VNET_API_ERROR_BOND_SLAVE_NOT_ALLOWED; + goto out; + } + sw_if_index = si->sw_if_index; sub_id = ntohl(mp->sub_id); -- 2.16.6