/* next node index for the L3 input node of each ethertype */
next_by_ethertype_t l3_next;
+ /* Next nodes for each feature */
+ u32 feat_next_node_index[32];
+
/* convenience variables */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
_(BVI_BAD_MAC, "BVI L3 MAC mismatch") \
_(BVI_ETHERTYPE, "BVI packet with unhandled ethertype") \
_(FILTER_DROP, "Filter Mac Drop") \
-_(REFLECT_DROP, "Reflection Drop")
+_(REFLECT_DROP, "Reflection Drop") \
+_(STALE_DROP, "Stale entry Drop")
typedef enum
{
typedef enum
{
L2FWD_NEXT_L2_OUTPUT,
- L2FWD_NEXT_FLOOD,
L2FWD_NEXT_DROP,
L2FWD_N_NEXT,
} l2fwd_next_t;
vlib_buffer_t * b0,
u32 sw_if_index0, l2fib_entry_result_t * result0, u32 * next0)
{
- if (PREDICT_FALSE (result0->raw == ~0))
- {
- /*
- * lookup miss, so flood
- * TODO:replicate packet to each intf in bridge-domain
- * For now just drop
- */
- if (vnet_buffer (b0)->l2.feature_bitmap & L2INPUT_FEAT_UU_FLOOD)
- {
- *next0 = L2FWD_NEXT_FLOOD;
- }
- else
- {
- /* Flooding is disabled */
- b0->error = node->errors[L2FWD_ERROR_FLOOD];
- *next0 = L2FWD_NEXT_DROP;
- }
+ int try_flood = result0->raw == ~0;
+ int flood_error;
+ if (PREDICT_FALSE (try_flood))
+ {
+ flood_error = L2FWD_ERROR_FLOOD;
}
else
{
-
/* lookup hit, forward packet */
#ifdef COUNTERS
em->counters[node_counter_base_index + L2FWD_ERROR_HIT] += 1;
vnet_buffer (b0)->sw_if_index[VLIB_TX] = result0->fields.sw_if_index;
*next0 = L2FWD_NEXT_L2_OUTPUT;
+ int l2fib_seq_num_valid = 1;
+
+ /* check l2fib seq num for stale entries */
+ if (!l2fib_entry_result_is_set_AGE_NOT (result0))
+ {
+ l2fib_seq_num_t in_sn = {.as_u16 = vnet_buffer (b0)->l2.l2fib_sn };
+ l2fib_seq_num_t expected_sn = {
+ .bd = in_sn.bd,
+ .swif = *l2fib_swif_seq_num (result0->fields.sw_if_index),
+ };
+ l2fib_seq_num_valid =
+ expected_sn.as_u16 == result0->fields.sn.as_u16;
+ }
+ if (PREDICT_FALSE (!l2fib_seq_num_valid))
+ {
+ flood_error = L2FWD_ERROR_STALE_DROP;
+ try_flood = 1;
+ }
/* perform reflection check */
- if (PREDICT_FALSE (sw_if_index0 == result0->fields.sw_if_index))
+ else if (PREDICT_FALSE (sw_if_index0 == result0->fields.sw_if_index))
{
b0->error = node->errors[L2FWD_ERROR_REFLECT_DROP];
*next0 = L2FWD_NEXT_DROP;
-
- /* perform filter check */
}
- else if (PREDICT_FALSE (result0->fields.filter))
+ /* perform filter check */
+ else if (PREDICT_FALSE (l2fib_entry_result_is_set_FILTER (result0)))
{
b0->error = node->errors[L2FWD_ERROR_FILTER_DROP];
*next0 = L2FWD_NEXT_DROP;
-
- /* perform BVI check */
}
- else if (PREDICT_FALSE (result0->fields.bvi))
+ /* perform BVI check */
+ else if (PREDICT_FALSE (l2fib_entry_result_is_set_BVI (result0)))
{
u32 rc;
rc = l2_to_bvi (vm,
}
}
}
+
+ /* flood */
+ if (PREDICT_FALSE (try_flood))
+ {
+ /*
+ * lookup miss, so flood which is typically the next feature
+ * unless some other feature is inserted before uu_flood
+ */
+ if (vnet_buffer (b0)->l2.feature_bitmap & L2INPUT_FEAT_UU_FLOOD)
+ {
+ *next0 = vnet_l2_feature_next (b0, msm->feat_next_node_index,
+ L2INPUT_FEAT_FWD);
+ }
+ else
+ {
+ /* Flooding is disabled */
+ b0->error = node->errors[flood_error];
+ *next0 = L2FWD_NEXT_DROP;
+ }
+ }
+
}
-static uword
-l2fwd_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)
+static_always_inline uword
+l2fwd_node_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
+ vlib_frame_t * frame, int do_trace)
{
u32 n_left_from, *from, *to_next;
l2fwd_next_t next_index;
h2 = vlib_buffer_get_current (b2);
h3 = vlib_buffer_get_current (b3);
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
+ if (do_trace)
{
if (b0->flags & VLIB_BUFFER_IS_TRACED)
{
h0 = vlib_buffer_get_current (b0);
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
- && (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ if (do_trace && PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
{
l2fwd_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
t->sw_if_index = sw_if_index0;
return frame->n_vectors;
}
+static uword
+l2fwd_node_fn (vlib_main_t * vm,
+ vlib_node_runtime_t * node, vlib_frame_t * frame)
+{
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
+ return l2fwd_node_inline (vm, node, frame, 1 /* do_trace */ );
+ return l2fwd_node_inline (vm, node, frame, 0 /* do_trace */ );
+}
+
/* *INDENT-OFF* */
VLIB_REGISTER_NODE (l2fwd_node,static) = {
.function = l2fwd_node_fn,
/* edit / add dispositions here */
.next_nodes = {
[L2FWD_NEXT_L2_OUTPUT] = "l2-output",
- [L2FWD_NEXT_FLOOD] = "l2-flood",
[L2FWD_NEXT_DROP] = "error-drop",
},
};
mp->vlib_main = vm;
mp->vnet_main = vnet_get_main ();
+ /* Initialize the feature next-node indexes */
+ feat_bitmap_init_next_nodes (vm,
+ l2fwd_node.index,
+ L2INPUT_N_FEAT,
+ l2input_get_feat_names (),
+ mp->feat_next_node_index);
+
/* init the hash table ptr */
mp->mac_table = get_mac_table ();