-
-static_always_inline void
-l2flood_process (vlib_main_t * vm,
- vlib_node_runtime_t * node,
- l2flood_main_t * msm,
- u64 * counter_base,
- vlib_buffer_t * b0,
- u32 * sw_if_index0,
- l2fib_entry_key_t * key0,
- u32 * bucket0, l2fib_entry_result_t * result0, u32 * next0)
-{
- u16 bd_index0;
- l2_bridge_domain_t *bd_config;
- l2_flood_member_t *members;
- i32 current_member; /* signed */
- replication_context_t *ctx;
- u8 in_shg = vnet_buffer (b0)->l2.shg;
-
- if (!replication_is_recycled (b0))
- {
-
- /* Do flood "prep node" processing */
-
- /* Get config for the bridge domain interface */
- bd_index0 = vnet_buffer (b0)->l2.bd_index;
- bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index0);
- members = bd_config->members;
-
- /* Find first member that passes the reflection and SHG checks */
- current_member = bd_config->flood_count - 1;
- while ((current_member >= 0) &&
- ((members[current_member].sw_if_index == *sw_if_index0) ||
- (in_shg && members[current_member].shg == in_shg)))
- {
- current_member--;
- }
-
- if (current_member < 0)
- {
- /* No members to flood to */
- *next0 = L2FLOOD_NEXT_DROP;
- b0->error = node->errors[L2FLOOD_ERROR_NO_MEMBERS];
- return;
- }
-
- if ((current_member > 0) &&
- ((current_member > 1) ||
- ((members[0].sw_if_index != *sw_if_index0) &&
- (!in_shg || members[0].shg != in_shg))))
- {
- /* If more than one member then initiate replication */
- ctx =
- replication_prep (vm, b0, l2flood_node.index, 1 /* l2_packet */ );
- ctx->feature_replicas = (uword) members;
- ctx->feature_counter = current_member;
- }
-
- }
- else
- {
- vnet_buffer_opaque_t *vnet_buff_op;
-
- /* Do flood "recycle node" processing */
-
- if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_REPL_FAIL))
- {
- (void) replication_recycle (vm, b0, 1 /* is_last */ );
- *next0 = L2FLOOD_NEXT_DROP;
- b0->error = node->errors[L2FLOOD_ERROR_REPL_FAIL];
- return;
- }
-
- ctx = replication_get_ctx (b0);
- replication_clear_recycled (b0);
-
- members = (l2_flood_member_t *) (intptr_t) ctx->feature_replicas;
- current_member = (i32) ctx->feature_counter - 1;
-
- /* Need to update input index from saved packet context */
- vnet_buff_op = (vnet_buffer_opaque_t *) ctx->vnet_buffer;
- *sw_if_index0 = vnet_buff_op->sw_if_index[VLIB_RX];
-
- /* Find next member that passes the reflection and SHG check */
- while ((current_member >= 0) &&
- ((members[current_member].sw_if_index == *sw_if_index0) ||
- (in_shg && members[current_member].shg == in_shg)))
- {
- current_member--;
- }
-
- if (current_member < 0)
- {
- /*
- * No more members to flood to.
- * Terminate replication and drop packet.
- */
-
- replication_recycle (vm, b0, 1 /* is_last */ );
-
- *next0 = L2FLOOD_NEXT_DROP;
- /* Ideally we woudn't bump a counter here, just silently complete */
- b0->error = node->errors[L2FLOOD_ERROR_NO_MEMBERS];
- return;
- }
-
- /* Restore packet and context and continue replication */
- ctx->feature_counter = current_member;
- replication_recycle (vm, b0, ((current_member == 0) || /*is_last */
- ((current_member == 1) &&
- ((members[0].sw_if_index ==
- *sw_if_index0) || (in_shg
- && members[0].shg ==
- in_shg)))));
- }
-
- /* Forward packet to the current member */
- if (PREDICT_FALSE (members[current_member].flags & L2_FLOOD_MEMBER_BVI))
- {
- /* Do BVI processing */
- u32 rc;
- rc = l2_to_bvi (vm,
- msm->vnet_main,
- b0,
- members[current_member].sw_if_index,
- &msm->l3_next, next0);
-
- if (PREDICT_FALSE (rc))
- {
- if (rc == TO_BVI_ERR_BAD_MAC)
- {
- b0->error = node->errors[L2FLOOD_ERROR_BVI_BAD_MAC];
- *next0 = L2FLOOD_NEXT_DROP;
- }
- else if (rc == TO_BVI_ERR_ETHERTYPE)
- {
- b0->error = node->errors[L2FLOOD_ERROR_BVI_ETHERTYPE];
- *next0 = L2FLOOD_NEXT_DROP;
- }
- }
- }
- else
- {
- /* Do normal L2 forwarding */
- vnet_buffer (b0)->sw_if_index[VLIB_TX] =
- members[current_member].sw_if_index;
- *next0 = L2FLOOD_NEXT_L2_OUTPUT;
-
- }
-
-}
-
-
-static uword
-l2flood_node_fn (vlib_main_t * vm,
- vlib_node_runtime_t * node, vlib_frame_t * frame)