#include <vnet/ip/ip_packet.h>
#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip6_packet.h>
+#include <vnet/fib/fib_node.h>
+#include <vnet/ethernet/arp_packet.h>
#include <vlib/cli.h>
#include <vnet/l2/l2_input.h>
#include <vnet/l2/l2_output.h>
* set tx sw-if-handle
*/
- u16 ethertype;
- u8 protocol;
- l2_input_config_t *config;
- l2_bridge_domain_t *bd_config;
- u16 bd_index0;
- u32 feature_bitmap;
- u32 feat_mask;
- ethernet_header_t *h0;
- u8 *l3h0;
- u32 sw_if_index0;
-
-#define get_u16(addr) ( *((u16 *)(addr)) )
-
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
-
- h0 = vlib_buffer_get_current (b0);
- l3h0 = (u8 *) h0 + vnet_buffer (b0)->l2.l2_len;
-
- ethertype = clib_net_to_host_u16 (get_u16 (l3h0 - 2));
- feat_mask = ~0;
+ u32 feat_mask = ~0;
+ u32 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ ethernet_header_t *h0 = vlib_buffer_get_current (b0);
/* Get config for the input interface */
- config = vec_elt_at_index (msm->configs, sw_if_index0);
+ l2_input_config_t *config = vec_elt_at_index (msm->configs, sw_if_index0);
/* Save split horizon group */
vnet_buffer (b0)->l2.shg = config->shg;
/* determine layer2 kind for stat and mask */
if (PREDICT_FALSE (ethernet_address_cast (h0->dst_address)))
{
- protocol = ((ip6_header_t *) l3h0)->protocol;
+ u8 *l3h0 = (u8 *) h0 + vnet_buffer (b0)->l2.l2_len;
+
+#define get_u16(addr) ( *((u16 *)(addr)) )
+ u16 ethertype = clib_net_to_host_u16 (get_u16 (l3h0 - 2));
+ u8 protocol = ((ip6_header_t *) l3h0)->protocol;
/* Disable bridge forwarding (flooding will execute instead if not xconnect) */
- feat_mask &= ~(L2INPUT_FEAT_FWD | L2INPUT_FEAT_UU_FLOOD);
+ feat_mask &= ~(L2INPUT_FEAT_FWD |
+ L2INPUT_FEAT_UU_FLOOD | L2INPUT_FEAT_GBP_FWD);
/* Disable ARP-term for non-ARP and non-ICMP6 packet */
if (ethertype != ETHERNET_TYPE_ARP &&
(ethertype != ETHERNET_TYPE_IP6 || protocol != IP_PROTOCOL_ICMP6))
feat_mask &= ~(L2INPUT_FEAT_ARP_TERM);
+
+ /*
+ * For packet from BVI - set SHG of ARP request or ICMPv6 neighbor
+ * solicitation packet from BVI to 0 so it can also flood to VXLAN
+ * tunnels or other ports with the same SHG as that of the BVI.
+ */
+ else if (PREDICT_FALSE (vnet_buffer (b0)->sw_if_index[VLIB_TX] ==
+ L2INPUT_BVI))
+ {
+ if (ethertype == ETHERNET_TYPE_ARP)
+ {
+ ethernet_arp_header_t *arp0 = (ethernet_arp_header_t *) l3h0;
+ if (arp0->opcode ==
+ clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request))
+ vnet_buffer (b0)->l2.shg = 0;
+ }
+ else /* must be ICMPv6 */
+ {
+ ip6_header_t *iph0 = (ip6_header_t *) l3h0;
+ icmp6_neighbor_solicitation_or_advertisement_header_t *ndh0;
+ ndh0 = ip6_next_header (iph0);
+ if (ndh0->icmp.type == ICMP6_neighbor_solicitation)
+ vnet_buffer (b0)->l2.shg = 0;
+ }
+ }
}
else
{
/*
- * Check for from-BVI processing - set SHG of unicast packets from BVI
- * to 0 so it is not dropped for VXLAN tunnels or other ports with the
+ * For packet from BVI - set SHG of unicast packet from BVI to 0 so it
+ * is not dropped on output to VXLAN tunnels or other ports with the
* same SHG as that of the BVI.
*/
if (PREDICT_FALSE (vnet_buffer (b0)->sw_if_index[VLIB_TX] ==
if (config->bridge)
{
/* Do bridge-domain processing */
- bd_index0 = config->bd_index;
+ u16 bd_index0 = config->bd_index;
/* save BD ID for next feature graph nodes */
vnet_buffer (b0)->l2.bd_index = bd_index0;
/* Get config for the bridge domain interface */
- bd_config = vec_elt_at_index (msm->bd_configs, bd_index0);
+ l2_bridge_domain_t *bd_config =
+ vec_elt_at_index (msm->bd_configs, bd_index0);
/* Save bridge domain and interface seq_num */
/* *INDENT-OFF* */
};
/* *INDENT-ON* */
vnet_buffer (b0)->l2.l2fib_sn = sn.as_u16;;
+ vnet_buffer (b0)->l2.bd_age = bd_config->mac_age;
/*
* Process bridge domain feature enables.
feat_mask = L2INPUT_FEAT_DROP;
/* mask out features from bitmap using packet type and bd config */
- feature_bitmap = config->feature_bitmap & feat_mask;
+ u32 feature_bitmap = config->feature_bitmap & feat_mask;
/* save for next feature graph nodes */
vnet_buffer (b0)->l2.feature_bitmap = feature_bitmap;
}
}
- vlib_node_increment_counter (vm, l2input_node.index,
- L2INPUT_ERROR_L2INPUT, 4);
-
classify_and_dispatch (msm, b0, &next0);
classify_and_dispatch (msm, b1, &next1);
classify_and_dispatch (msm, b2, &next2);
clib_memcpy (t->dst, h0->dst_address, 6);
}
- vlib_node_increment_counter (vm, l2input_node.index,
- L2INPUT_ERROR_L2INPUT, 1);
-
classify_and_dispatch (msm, b0, &next0);
/* verify speculative enqueue, maybe switch current next frame */
vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
+ vlib_node_increment_counter (vm, l2input_node.index,
+ L2INPUT_ERROR_L2INPUT, frame->n_vectors);
+
return frame->n_vectors;
}
l2_output_config_t *out_config;
l2_input_config_t *config;
l2_bridge_domain_t *bd_config;
- u64 mac;
i32 l2_if_adjust = 0;
u32 slot;
+ vnet_device_class_t *dev_class;
hi = vnet_get_sup_hw_interface (vnet_main, sw_if_index);
config = l2input_intf_config (sw_if_index);
/* 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;
/* delete the l2fib entry for the bvi interface */
- mac = *((u64 *) hi->hw_address);
- l2fib_del_entry (mac, config->bd_index);
+ l2fib_del_entry (hi->hw_address, config->bd_index);
/* Make loop output node send packet back to ethernet-input node */
slot =
"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 */
/* 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)
{
config->bvi = 1;
/* create the l2fib entry for the bvi interface */
- mac = *((u64 *) hi->hw_address);
- l2fib_add_fwd_entry (mac, bd_index, sw_if_index, 1, 1); /* static + bvi */
+ l2fib_add_fwd_entry (hi->hw_address, bd_index, sw_if_index, 1, 1); /* static + bvi */
/* Disable learning by default. no use since l2fib entry is static. */
config->feature_bitmap &= ~L2INPUT_FEAT_LEARN;
"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 */
/* Set up the L2/L3 flag in the interface parsing tables */
ethernet_sw_interface_set_l2_mode (vnm, sw_if_index, (mode != MODE_L3));
+ dev_class = vnet_get_device_class (vnet_main, hi->dev_class_index);
+ if (dev_class->set_l2_mode_function)
+ {
+ dev_class->set_l2_mode_function (vnet_main, hi, l2_if_adjust);
+ }
+
return 0;
}
_(l2_input_classify_init) \
_(l2bd_init) \
_(l2fwd_init) \
-_(l2_inacl_init) \
+_(l2_in_out_acl_init) \
_(l2input_init) \
_(l2_vtr_init) \
_(l2_invtr_init) \
_(l2_efp_filter_init) \
_(l2learn_init) \
_(l2flood_init) \
-_(l2_outacl_init) \
_(l2output_init) \
_(l2_patch_init) \
_(l2_xcrw_init)