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 <loj@cisco.com>
This commit is contained in:

committed by
Gerrit Code Review

parent
2fa6beff57
commit
bcebbb988d
@ -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),
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <vppinfra/vec.h>
|
||||
#include <vppinfra/error.h>
|
||||
#include <vppinfra/format.h>
|
||||
#include <vppinfra/bitmap.h>
|
||||
|
||||
#include <vnet/ethernet/ethernet.h>
|
||||
#include <vnet/devices/dpdk/dpdk.h>
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include <vnet/vnet.h>
|
||||
#include <vnet/ip/ip.h>
|
||||
#include <vppinfra/bitmap.h>
|
||||
|
||||
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] [<if-name1> <if-name2> ...]",
|
||||
.short_help = "show hardware-interfaces [brief|verbose|detail] [bond] [<if-name1> <if-name2> ...]",
|
||||
.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;
|
||||
|
@ -38,14 +38,21 @@
|
||||
*/
|
||||
|
||||
#include <vnet/vnet.h>
|
||||
#include <vppinfra/bitmap.h>
|
||||
|
||||
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);
|
||||
|
@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user