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:
John Lo
2016-04-05 15:47:43 -04:00
committed by Gerrit Code Review
parent 2fa6beff57
commit bcebbb988d
7 changed files with 111 additions and 31 deletions

View File

@ -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),

View File

@ -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;
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);