summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Lo <loj@cisco.com>2016-04-05 15:47:43 -0400
committerGerrit Code Review <gerrit@fd.io>2016-04-07 14:33:05 +0000
commitbcebbb988da4fcbb6158c05050f96ae87cc50156 (patch)
tree9542744dbc6315e15b41e361369bb8da983207c5
parent2fa6beff5726ecb7c863d0027395ed63dc4831ca (diff)
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>
-rw-r--r--vnet/vnet/api_errno.h3
-rw-r--r--vnet/vnet/devices/dpdk/init.c34
-rw-r--r--vnet/vnet/interface.c9
-rw-r--r--vnet/vnet/interface.h11
-rw-r--r--vnet/vnet/interface_cli.c49
-rw-r--r--vnet/vnet/interface_format.c31
-rw-r--r--vpp/api/api.c5
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 <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;
}
}
}
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 <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;
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 <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);
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);