+ n_left -= 1;
+ }
+}
+
+static_always_inline void
+bond_tx_trace (vlib_main_t * vm, vlib_node_runtime_t * node, bond_if_t * bif,
+ vlib_buffer_t ** b, u32 n_left, u32 * h)
+{
+ uword n_trace = vlib_get_trace_count (vm, node);
+
+ while (n_trace > 0 && n_left > 0)
+ {
+ bond_packet_trace_t *t0;
+ ethernet_header_t *eth;
+ u32 next0 = 0;
+
+ vlib_trace_buffer (vm, node, next0, b[0], 0 /* follow_chain */ );
+ vlib_set_trace_count (vm, node, --n_trace);
+ t0 = vlib_add_trace (vm, node, b[0], sizeof (*t0));
+ eth = vlib_buffer_get_current (b[0]);
+ t0->ethernet = *eth;
+ t0->sw_if_index = vnet_buffer (b[0])->sw_if_index[VLIB_TX];
+ if (!h)
+ {
+ t0->bond_sw_if_index = *vec_elt_at_index (bif->active_members, 0);
+ }
+ else
+ {
+ t0->bond_sw_if_index =
+ *vec_elt_at_index (bif->active_members, h[0]);
+ h++;
+ }
+ b++;
+ n_left--;
+ }
+}
+
+VNET_DEVICE_CLASS_TX_FN (bond_dev_class) (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ vnet_interface_output_runtime_t *rund = (void *) node->runtime_data;
+ bond_main_t *bm = &bond_main;
+ u16 thread_index = vm->thread_index;
+ bond_if_t *bif = pool_elt_at_index (bm->interfaces, rund->dev_instance);
+ uword n_members;
+ vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
+ u32 *from = vlib_frame_vector_args (frame);
+ u32 n_left = frame->n_vectors;
+ u32 hashes[VLIB_FRAME_SIZE], *h;
+ vnet_main_t *vnm = vnet_get_main ();
+ bond_per_thread_data_t *ptd = vec_elt_at_index (bm->per_thread_data,
+ thread_index);
+ u32 p, sw_if_index;
+
+ if (PREDICT_FALSE (bif->admin_up == 0))
+ {
+ vlib_buffer_free (vm, vlib_frame_vector_args (frame), frame->n_vectors);
+ vlib_increment_simple_counter (vnet_main.interface_main.sw_if_counters +
+ VNET_INTERFACE_COUNTER_DROP,
+ thread_index, bif->sw_if_index,
+ frame->n_vectors);
+ vlib_error_count (vm, node->node_index, BOND_TX_ERROR_IF_DOWN,
+ frame->n_vectors);
+ return frame->n_vectors;
+ }
+
+ n_members = vec_len (bif->active_members);
+ if (PREDICT_FALSE (n_members == 0))
+ {
+ vlib_buffer_free (vm, vlib_frame_vector_args (frame), frame->n_vectors);
+ vlib_increment_simple_counter (vnet_main.interface_main.sw_if_counters +
+ VNET_INTERFACE_COUNTER_DROP,
+ thread_index, bif->sw_if_index,
+ frame->n_vectors);
+ vlib_error_count (vm, node->node_index, BOND_TX_ERROR_NO_MEMBER,
+ frame->n_vectors);
+ return frame->n_vectors;
+ }
+
+ vlib_get_buffers (vm, from, bufs, n_left);
+
+ /* active-backup mode, ship everything to first sw if index */
+ if ((bif->lb == BOND_LB_AB) || PREDICT_FALSE (n_members == 1))
+ {
+ sw_if_index = *vec_elt_at_index (bif->active_members, 0);
+
+ bond_tx_trace (vm, node, bif, bufs, frame->n_vectors, 0);
+ bond_update_sw_if_index (ptd, bif, from, bufs, &sw_if_index, n_left,
+ /* single_sw_if_index */ 1);
+ goto done;