aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
authorSteven <sluong@cisco.com>2018-06-05 11:09:32 -0700
committerSteven <sluong@cisco.com>2018-06-05 11:09:32 -0700
commit9f781d84b0943b03af2a9fd0b7c4cef721d1d4c6 (patch)
treea78172c460d265c89d3717a5cb8cb45775fe523b /src/vnet
parent439a122f3acd745dcb70e9b32bb518e43967afe4 (diff)
bond: send gratuitous arp when the active slave went down in active-backup mode
- Modify the API send_ip6_na and send_ip4_garp to take sw_if_index instead of vnet_hw_interface_t and add call to build_ethernet_rewrite to support subinterface/vlan - Add code to bonding driver to send an event to bond_process when the first interface becomes active or when the active interface is down - Create a bond_process to walk the interface and the corresponding subinterfaces to send garp/ip6_na when an event is received. - Minor cleanup in bonding/node.c Note: dpdk bonding driver does not send garp/ip6_na for subinterfaces. There is no attempt to fix it here. But the infra is now done and should be easy to add the support. Change-Id: If3ecc4cd0fb3051330f7fa11ca0dab3e18557ce1 Signed-off-by: Steven <sluong@cisco.com>
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/bonding/cli.c19
-rw-r--r--src/vnet/bonding/device.c48
-rw-r--r--src/vnet/bonding/node.c4
-rw-r--r--src/vnet/bonding/node.h6
-rw-r--r--src/vnet/ethernet/arp.c25
-rw-r--r--src/vnet/ethernet/arp_packet.h5
-rw-r--r--src/vnet/ip/ip6.h5
-rw-r--r--src/vnet/ip/ip6_neighbor.c26
8 files changed, 107 insertions, 31 deletions
diff --git a/src/vnet/bonding/cli.c b/src/vnet/bonding/cli.c
index 2799bb88b99..91c6e2cdb7d 100644
--- a/src/vnet/bonding/cli.c
+++ b/src/vnet/bonding/cli.c
@@ -24,9 +24,11 @@
void
bond_disable_collecting_distributing (vlib_main_t * vm, slave_if_t * sif)
{
+ bond_main_t *bm = &bond_main;
bond_if_t *bif;
int i;
uword p;
+ u8 switching_active = 0;
bif = bond_get_master_by_dev_instance (sif->bif_dev_instance);
clib_spinlock_lock_if_init (&bif->lockp);
@@ -35,8 +37,18 @@ bond_disable_collecting_distributing (vlib_main_t * vm, slave_if_t * sif)
p = *vec_elt_at_index (bif->active_slaves, i);
if (p == sif->sw_if_index)
{
+ /* Are we disabling the very 1st slave? */
+ if (sif->sw_if_index == *vec_elt_at_index (bif->active_slaves, 0))
+ switching_active = 1;
+
vec_del1 (bif->active_slaves, i);
hash_unset (bif->active_slave_by_sw_if_index, sif->sw_if_index);
+
+ /* We got a new slave just becoming active? */
+ if ((vec_len (bif->active_slaves) >= 1) &&
+ (bif->mode == BOND_MODE_ACTIVE_BACKUP) && switching_active)
+ vlib_process_signal_event (bm->vlib_main, bond_process_node.index,
+ BOND_SEND_GARP_NA, bif->hw_if_index);
break;
}
}
@@ -47,6 +59,7 @@ void
bond_enable_collecting_distributing (vlib_main_t * vm, slave_if_t * sif)
{
bond_if_t *bif;
+ bond_main_t *bm = &bond_main;
bif = bond_get_master_by_dev_instance (sif->bif_dev_instance);
clib_spinlock_lock_if_init (&bif->lockp);
@@ -55,6 +68,12 @@ bond_enable_collecting_distributing (vlib_main_t * vm, slave_if_t * sif)
hash_set (bif->active_slave_by_sw_if_index, sif->sw_if_index,
sif->sw_if_index);
vec_add1 (bif->active_slaves, sif->sw_if_index);
+
+ /* First slave becomes active? */
+ if ((vec_len (bif->active_slaves) == 1) &&
+ (bif->mode == BOND_MODE_ACTIVE_BACKUP))
+ vlib_process_signal_event (bm->vlib_main, bond_process_node.index,
+ BOND_SEND_GARP_NA, bif->hw_if_index);
}
clib_spinlock_unlock_if_init (&bif->lockp);
}
diff --git a/src/vnet/bonding/device.c b/src/vnet/bonding/device.c
index 8ddec80850a..1ade1c290a1 100644
--- a/src/vnet/bonding/device.c
+++ b/src/vnet/bonding/device.c
@@ -23,6 +23,8 @@
#include <vnet/ip/ip6_hop_by_hop_packet.h>
#include <vnet/bonding/node.h>
#include <vppinfra/lb_hash_hash.h>
+#include <vnet/ip/ip.h>
+#include <vnet/ethernet/arp_packet.h>
#define foreach_bond_tx_error \
_(NONE, "no error") \
@@ -700,6 +702,52 @@ bond_tx_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
return frame->n_vectors;
}
+static walk_rc_t
+bond_active_interface_switch_cb (vnet_main_t * vnm, u32 sw_if_index,
+ void *arg)
+{
+ bond_main_t *bm = &bond_main;
+
+ send_ip4_garp (bm->vlib_main, sw_if_index);
+ send_ip6_na (bm->vlib_main, sw_if_index);
+
+ return (WALK_CONTINUE);
+}
+
+static uword
+bond_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ uword event_type, *event_data = 0;
+
+ while (1)
+ {
+ u32 i;
+ u32 hw_if_index;
+
+ vlib_process_wait_for_event (vm);
+ event_type = vlib_process_get_events (vm, &event_data);
+ ASSERT (event_type == BOND_SEND_GARP_NA);
+ for (i = 0; i < vec_len (event_data); i++)
+ {
+ hw_if_index = event_data[i];
+ /* walk hw interface to process all subinterfaces */
+ vnet_hw_interface_walk_sw (vnm, hw_if_index,
+ bond_active_interface_switch_cb, 0);
+ }
+ vec_reset_length (event_data);
+ }
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (bond_process_node) = {
+ .function = bond_process,
+ .type = VLIB_NODE_TYPE_PROCESS,
+ .name = "bond-process",
+};
+/* *INDENT-ON* */
+
/* *INDENT-OFF* */
VNET_DEVICE_CLASS (bond_dev_class) = {
.name = "bond",
diff --git a/src/vnet/bonding/node.c b/src/vnet/bonding/node.c
index 9479fe98dd0..5842da3f5ec 100644
--- a/src/vnet/bonding/node.c
+++ b/src/vnet/bonding/node.c
@@ -67,7 +67,7 @@ typedef enum
{
BOND_INPUT_NEXT_DROP,
BOND_INPUT_N_NEXT,
-} l2output_next_t;
+} bond_output_next_t;
static_always_inline u8
packet_is_cdp (ethernet_header_t * eth)
@@ -329,7 +329,6 @@ VLIB_NODE_FN (bond_input_node) (vlib_main_t * vm,
n_left = frame->n_vectors; /* number of packets to process */
b = bufs;
sw_if_index = sw_if_indices;
- next = nexts;
bond_packet_trace_t *t0;
while (n_left)
@@ -346,7 +345,6 @@ VLIB_NODE_FN (bond_input_node) (vlib_main_t * vm,
n_left--;
b++;
sw_if_index++;
- next++;
}
}
diff --git a/src/vnet/bonding/node.h b/src/vnet/bonding/node.h
index 5c6ff32ac4a..7b8e1ad7cb2 100644
--- a/src/vnet/bonding/node.h
+++ b/src/vnet/bonding/node.h
@@ -70,6 +70,11 @@ typedef enum
#undef _
} bond_load_balance_t;
+enum
+{
+ BOND_SEND_GARP_NA = 1,
+} bond_send_garp_na_process_event_t;
+
typedef struct
{
u8 hw_addr_set;
@@ -325,6 +330,7 @@ typedef struct
} bond_load_balance_func_t;
extern vlib_node_registration_t bond_input_node;
+extern vlib_node_registration_t bond_process_node;
extern vnet_device_class_t bond_dev_class;
extern bond_main_t bond_main;
diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c
index 249e3b6e8cf..682bc2a2c92 100644
--- a/src/vnet/ethernet/arp.c
+++ b/src/vnet/ethernet/arp.c
@@ -2526,22 +2526,22 @@ ethernet_arp_change_mac (u32 sw_if_index)
}
void
-send_ip4_garp (vlib_main_t * vm, const vnet_hw_interface_t * hi)
+send_ip4_garp (vlib_main_t * vm, u32 sw_if_index)
{
ip4_main_t *i4m = &ip4_main;
- ip4_address_t *ip4_addr =
- ip4_interface_first_address (i4m, hi->sw_if_index, 0);
+ ip4_address_t *ip4_addr = ip4_interface_first_address (i4m, sw_if_index, 0);
- send_ip4_garp_w_addr (vm, ip4_addr, hi);
+ send_ip4_garp_w_addr (vm, ip4_addr, sw_if_index);
}
void
send_ip4_garp_w_addr (vlib_main_t * vm,
- const ip4_address_t * ip4_addr,
- const vnet_hw_interface_t * hi)
+ const ip4_address_t * ip4_addr, u32 sw_if_index)
{
ip4_main_t *i4m = &ip4_main;
- u32 sw_if_index = hi->sw_if_index;
+ vnet_main_t *vnm = vnet_get_main ();
+ u8 *rewrite, rewrite_len;
+ vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
if (ip4_addr)
{
@@ -2563,11 +2563,14 @@ send_ip4_garp_w_addr (vlib_main_t * vm,
/* Setup MAC header with ARP Etype and broadcast DMAC */
vlib_buffer_t *b = vlib_get_buffer (vm, bi);
- vlib_buffer_advance (b, -sizeof (ethernet_header_t));
+ rewrite =
+ ethernet_build_rewrite (vnm, sw_if_index, VNET_LINK_ARP,
+ VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST);
+ rewrite_len = vec_len (rewrite);
+ vlib_buffer_advance (b, -rewrite_len);
ethernet_header_t *e = vlib_buffer_get_current (b);
- e->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
- clib_memcpy (e->src_address, hi->hw_address, sizeof (e->src_address));
- memset (e->dst_address, 0xff, sizeof (e->dst_address));
+ clib_memcpy (e->dst_address, rewrite, rewrite_len);
+ vec_free (rewrite);
/* Send GARP packet out the specified interface */
vnet_buffer (b)->sw_if_index[VLIB_RX] =
diff --git a/src/vnet/ethernet/arp_packet.h b/src/vnet/ethernet/arp_packet.h
index d2a23a5949f..e5f424d7879 100644
--- a/src/vnet/ethernet/arp_packet.h
+++ b/src/vnet/ethernet/arp_packet.h
@@ -168,10 +168,9 @@ ethernet_arp_ip4_entry_t *ip4_neighbors_pool (void);
ethernet_arp_ip4_entry_t *ip4_neighbor_entries (u32 sw_if_index);
u8 *format_ethernet_arp_ip4_entry (u8 * s, va_list * va);
-void send_ip4_garp (vlib_main_t * vm, const vnet_hw_interface_t * hi);
+void send_ip4_garp (vlib_main_t * vm, u32 sw_if_index);
void send_ip4_garp_w_addr (vlib_main_t * vm,
- const ip4_address_t * ip4_addr,
- const vnet_hw_interface_t * hi);
+ const ip4_address_t * ip4_addr, u32 sw_if_index);
#endif /* included_ethernet_arp_packet_h */
diff --git a/src/vnet/ip/ip6.h b/src/vnet/ip/ip6.h
index 4b24774c277..6f6724b3903 100644
--- a/src/vnet/ip/ip6.h
+++ b/src/vnet/ip/ip6.h
@@ -407,10 +407,9 @@ int vnet_ip6_nd_term (vlib_main_t * vm,
ethernet_header_t * eth,
ip6_header_t * ip, u32 sw_if_index, u16 bd_index);
-void send_ip6_na (vlib_main_t * vm, const vnet_hw_interface_t * hi);
+void send_ip6_na (vlib_main_t * vm, u32 sw_if_index);
void send_ip6_na_w_addr (vlib_main_t * vm,
- const ip6_address_t * addr,
- const vnet_hw_interface_t * hi);
+ const ip6_address_t * addr, u32 sw_if_index);
u8 *format_ip6_forward_next_trace (u8 * s, va_list * args);
diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c
index 1b37e549e83..3daea6bafbe 100644
--- a/src/vnet/ip/ip6_neighbor.c
+++ b/src/vnet/ip/ip6_neighbor.c
@@ -4980,22 +4980,23 @@ ethernet_ndp_change_mac (u32 sw_if_index)
}
void
-send_ip6_na (vlib_main_t * vm, const vnet_hw_interface_t * hi)
+send_ip6_na (vlib_main_t * vm, u32 sw_if_index)
{
ip6_main_t *i6m = &ip6_main;
- u32 sw_if_index = hi->sw_if_index;
ip6_address_t *ip6_addr = ip6_interface_first_address (i6m, sw_if_index);
- send_ip6_na_w_addr (vm, ip6_addr, hi);
+ send_ip6_na_w_addr (vm, ip6_addr, sw_if_index);
}
void
send_ip6_na_w_addr (vlib_main_t * vm,
- const ip6_address_t * ip6_addr,
- const vnet_hw_interface_t * hi)
+ const ip6_address_t * ip6_addr, u32 sw_if_index)
{
ip6_main_t *i6m = &ip6_main;
- u32 sw_if_index = hi->sw_if_index;
+ vnet_main_t *vnm = vnet_get_main ();
+ u8 *rewrite, rewrite_len;
+ vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
+ u8 dst_address[6];
if (ip6_addr)
{
@@ -5026,12 +5027,15 @@ send_ip6_na_w_addr (vlib_main_t * vm,
/* Setup MAC header with IP6 Etype and mcast DMAC */
vlib_buffer_t *b = vlib_get_buffer (vm, bi);
- vlib_buffer_advance (b, -sizeof (ethernet_header_t));
- ethernet_header_t *e = vlib_buffer_get_current (b);
- e->type = clib_host_to_net_u16 (ETHERNET_TYPE_IP6);
- clib_memcpy (e->src_address, hi->hw_address, sizeof (e->src_address));
- ip6_multicast_ethernet_address (e->dst_address,
+ ip6_multicast_ethernet_address (dst_address,
IP6_MULTICAST_GROUP_ID_all_hosts);
+ rewrite =
+ ethernet_build_rewrite (vnm, sw_if_index, VNET_LINK_IP6, dst_address);
+ rewrite_len = vec_len (rewrite);
+ vlib_buffer_advance (b, -rewrite_len);
+ ethernet_header_t *e = vlib_buffer_get_current (b);
+ clib_memcpy (e->dst_address, rewrite, rewrite_len);
+ vec_free (rewrite);
/* Send unsolicited ND advertisement packet out the specified interface */
vnet_buffer (b)->sw_if_index[VLIB_RX] =