From 1a2b9e6d73876f7c420184b78d46e14f586402bc Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 9 Apr 2018 01:53:01 -0700 Subject: L2: no-flood interface type in the Bridge-Domain Change-Id: I50ff0cacf88182f8e0be19840c50f4954de586e2 Signed-off-by: Neale Ranns (cherry picked from commit 87dad11c8717735479e57cf6c065c7a7963c3aa3) --- src/vnet/ethernet/interface.c | 4 ++++ src/vnet/interface.h | 6 +++++- src/vnet/l2/l2_bd.c | 28 ++++++++++++++++++---------- src/vnet/l2/l2_bd.h | 3 +++ src/vnet/l2/l2_input.c | 12 ++++++++++++ 5 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/vnet/ethernet/interface.c b/src/vnet/ethernet/interface.c index a29302bee3e..2ed20e15c24 100644 --- a/src/vnet/ethernet/interface.c +++ b/src/vnet/ethernet/interface.c @@ -621,6 +621,10 @@ vnet_create_loopback_interface (u32 * sw_if_indexp, u8 * mac_address, { vnet_sw_interface_t *si = vnet_get_hw_sw_interface (vnm, hw_if_index); *sw_if_indexp = si->sw_if_index; + + /* By default don't flood to loopbacks, as packets just keep + * coming back ... If this loopback becomes a BVI, we'll change it */ + si->flood_class = VNET_FLOOD_CLASS_NO_FLOOD; } return 0; diff --git a/src/vnet/interface.h b/src/vnet/interface.h index 00a7353d701..f49a1bcdc8e 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -556,11 +556,15 @@ typedef struct typedef enum { + /* THe BVI interface */ + VNET_FLOOD_CLASS_BVI, /* Always flood */ VNET_FLOOD_CLASS_NORMAL, VNET_FLOOD_CLASS_TUNNEL_MASTER, /* Does not flood when tunnel master is in the same L2 BD */ - VNET_FLOOD_CLASS_TUNNEL_NORMAL + VNET_FLOOD_CLASS_TUNNEL_NORMAL, + /* Never flood to this type */ + VNET_FLOOD_CLASS_NO_FLOOD, } vnet_flood_class_t; /* Software-interface. This corresponds to a Ethernet VLAN, ATM vc, a diff --git a/src/vnet/l2/l2_bd.c b/src/vnet/l2/l2_bd.c index b1abb4c0fba..7c8aef1df65 100644 --- a/src/vnet/l2/l2_bd.c +++ b/src/vnet/l2/l2_bd.c @@ -128,38 +128,46 @@ bd_delete (bd_main_t * bdm, u32 bd_index) static void update_flood_count (l2_bridge_domain_t * bd_config) { - bd_config->flood_count = vec_len (bd_config->members) - - (bd_config->tun_master_count ? bd_config->tun_normal_count : 0); + bd_config->flood_count = (vec_len (bd_config->members) - + (bd_config->tun_master_count ? + bd_config->tun_normal_count : 0)); + bd_config->flood_count -= bd_config->no_flood_count; } void bd_add_member (l2_bridge_domain_t * bd_config, l2_flood_member_t * member) { - u32 ix; + u32 ix = 0; vnet_sw_interface_t *sw_if = vnet_get_sw_interface (vnet_get_main (), member->sw_if_index); /* * Add one element to the vector - * vector is ordered [ bvi, normal/tun_masters..., tun_normals... ] + * vector is ordered [ bvi, normal/tun_masters..., tun_normals... no_flood] * When flooding, the bvi interface (if present) must be the last member * processed due to how BVI processing can change the packet. To enable * this order, we make the bvi interface the first in the vector and - * flooding walks the vector in reverse. + * flooding walks the vector in reverse. The flood-count determines where + * in the member list to start the walk from. */ switch (sw_if->flood_class) { + case VNET_FLOOD_CLASS_NO_FLOOD: + bd_config->no_flood_count++; + ix = vec_len (bd_config->members); + break; + case VNET_FLOOD_CLASS_BVI: + ix = 0; + break; case VNET_FLOOD_CLASS_TUNNEL_MASTER: bd_config->tun_master_count++; /* Fall through */ - default: - /* Fall through */ case VNET_FLOOD_CLASS_NORMAL: - ix = (member->flags & L2_FLOOD_MEMBER_BVI) ? 0 : - vec_len (bd_config->members) - bd_config->tun_normal_count; + ix = (vec_len (bd_config->members) - + bd_config->tun_normal_count - bd_config->no_flood_count); break; case VNET_FLOOD_CLASS_TUNNEL_NORMAL: - ix = vec_len (bd_config->members); + ix = (vec_len (bd_config->members) - bd_config->no_flood_count); bd_config->tun_normal_count++; break; } diff --git a/src/vnet/l2/l2_bd.h b/src/vnet/l2/l2_bd.h index fd34ae67a83..ffc75339e97 100644 --- a/src/vnet/l2/l2_bd.h +++ b/src/vnet/l2/l2_bd.h @@ -78,6 +78,9 @@ typedef struct /* Tunnels (Unicast vxlan) are flooded if there are no masters */ u32 tun_normal_count; + /* Interface on which packets are not flooded */ + u32 no_flood_count; + /* hash ip4/ip6 -> mac for arp/nd termination */ uword *mac_by_ip4; uword *mac_by_ip6; diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c index 5d16b1ddc9e..c2df5acb3b2 100644 --- a/src/vnet/l2/l2_input.c +++ b/src/vnet/l2/l2_input.c @@ -579,6 +579,8 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */ /* undo any BVI-related config */ if (bd_config->bvi_sw_if_index == sw_if_index) { + vnet_sw_interface_t *si; + bd_config->bvi_sw_if_index = ~0; config->bvi = 0; @@ -591,6 +593,10 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */ "ethernet-input", VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT); ASSERT (slot == VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT); + + /* since this is a no longer BVI interface do not to flood to it */ + si = vnet_get_sw_interface (vnm, sw_if_index); + si->flood_class = VNET_FLOOD_CLASS_NO_FLOOD; } /* Clear MACs learned on the interface */ @@ -673,6 +679,8 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */ /* Do BVI interface initializations */ if (bvi) { + vnet_sw_interface_t *si; + /* ensure BD has no bvi interface (or replace that one with this??) */ if (bd_config->bvi_sw_if_index != ~0) { @@ -693,6 +701,10 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */ "l2-input", VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT); ASSERT (slot == VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT); + + /* since this is a BVI interface we want to flood to it */ + si = vnet_get_sw_interface (vnm, sw_if_index); + si->flood_class = VNET_FLOOD_CLASS_BVI; } /* Add interface to bridge-domain flood vector */ -- cgit 1.2.3-korg