/* *INDENT-ON */
/* *INDENT-OFF* */
-VNET_FEATURE_INIT (ct6in2out, static) =
-{
+VNET_FEATURE_INIT (ct6in2out, static) = {
.arc_name = "interface-output",
.node_name = "ct6-in2out",
- .runs_before = VNET_FEATURES ("interface-tx"),
+ .runs_before = VNET_FEATURES ("interface-output-arc-end"),
};
/* *INDENT-ON */
.runs_before = VNET_FEATURES ("interface-output"),
};
-VNET_FEATURE_INIT (flow_perpacket_l2, static) =
-{
+VNET_FEATURE_INIT (flow_perpacket_l2, static) = {
.arc_name = "interface-output",
.node_name = "flowprobe-l2",
- .runs_before = VNET_FEATURES ("interface-tx"),
+ .runs_before = VNET_FEATURES ("interface-output-arc-end"),
};
/* *INDENT-ON* */
clib_memcpy_fast (p, pm.packets_read[0], vec_len (pm.packets_read[0]));
vlib_buffer_pull (b, sizeof (ethernet_header_t));
- vlib_node_t *n = vlib_get_node_by_name (lgm->vlib_main,
- (u8 *) "interface-tx");
+ vlib_node_t *n =
+ vlib_get_node_by_name (lgm->vlib_main, (u8 *) "interface-output-arc-end");
f = vlib_get_frame_to_node (lgm->vlib_main, n->index);
u32 *to_next = vlib_frame_vector_args (f);
to_next[0] = bi;
/* *INDENT-ON */
/* *INDENT-OFF* */
-VNET_FEATURE_INIT (mactime_tx, static) =
-{
+VNET_FEATURE_INIT (mactime_tx, static) = {
.arc_name = "interface-output",
.node_name = "mactime-tx",
- .runs_before = VNET_FEATURES ("interface-tx"),
+ .runs_before = VNET_FEATURES ("interface-output-arc-end"),
};
/* *INDENT-ON */
/* *INDENT-ON */
/* *INDENT-OFF* */
-VNET_FEATURE_INIT (nsim_feature, static) =
-{
+VNET_FEATURE_INIT (nsim_feature, static) = {
.arc_name = "interface-output",
.node_name = "nsim-output-feature",
- .runs_before = VNET_FEATURES ("interface-tx"),
+ .runs_before = VNET_FEATURES ("interface-output-arc-end"),
};
/* *INDENT-ON */
}
}
+static void
+vnet_if_update_lookup_tables (vnet_main_t *vnm, u32 sw_if_index)
+{
+ vnet_interface_main_t *im = &vnm->interface_main;
+ vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
+
+ vec_validate_init_empty (im->hw_if_index_by_sw_if_index, sw_if_index, ~0);
+ vec_validate_init_empty (im->if_out_arc_end_next_index_by_sw_if_index,
+ sw_if_index, ~0);
+
+ im->hw_if_index_by_sw_if_index[sw_if_index] = hi->hw_if_index;
+ im->if_out_arc_end_next_index_by_sw_if_index[sw_if_index] =
+ hi->if_out_arc_end_node_next_index;
+}
+
static u32
vnet_create_sw_interface_no_callbacks (vnet_main_t * vnm,
vnet_sw_interface_t * template)
vnet_interface_counter_unlock (im);
}
+ vnet_if_update_lookup_tables (vnm, sw_if_index);
return sw_if_index;
}
vlib_node_add_next_with_slot (vm, hw->output_node_index,
hw->tx_node_index,
VNET_INTERFACE_OUTPUT_NEXT_TX);
-
/* add interface to the list of "output-interface" feature arc start nodes
and clone nexts from 1st interface if it exists */
fcm = vnet_feature_get_config_main (im->output_feature_arc_index);
}
}
+ hw->if_out_arc_end_node_next_index = vlib_node_add_next (
+ vm, vnet_interface_output_arc_end_node.index, hw->tx_node_index);
+ vnet_if_update_lookup_tables (vnm, hw->sw_if_index);
setup_output_node (vm, hw->output_node_index, hw_class);
setup_tx_node (vm, hw->tx_node_index, dev_class);
typedef struct vnet_hw_interface_t
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
- /* Interface name. */
- u8 *name;
-
/* flags */
vnet_hw_interface_flags_t flags;
/* capabilities flags */
vnet_hw_interface_capabilities_t caps;
- /* link speed in kbps */
- u32 link_speed;
-
/* Hardware address as vector. Zero (e.g. zero-length vector) if no
address for this class (e.g. PPP). */
u8 *hw_address;
/* NAME.{output,tx} nodes for this interface. */
u32 output_node_index, tx_node_index;
+ /* interface-output-arc-end node next index for tx node */
+ u32 if_out_arc_end_node_next_index;
+
/* (dev_class, dev_instance) uniquely identifies hw interface. */
u32 dev_class_index;
u32 dev_instance;
CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
+ /* Interface name. */
+ u8 *name;
+
+ /* link speed in kbps */
+ u32 link_speed;
+
/* Next index in interface-output node for this interface
used by node function vnet_per_buffer_interface_output() */
u32 output_node_next_index;
/* feature_arc_index */
u8 output_feature_arc_index;
+
+ /* fast lookup tables */
+ u32 *hw_if_index_by_sw_if_index;
+ u16 *if_out_arc_end_next_index_by_sw_if_index;
} vnet_interface_main_t;
static inline void
int vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t *);
extern vlib_node_registration_t vnet_interface_output_node;
+extern vlib_node_registration_t vnet_interface_output_arc_end_node;
#endif /* included_vnet_interface_h */
};
/* *INDENT-ON* */
-/* *INDENT-OFF* */
VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node) = {
.name = "interface-output",
.vector_size = sizeof (u32),
};
-/* *INDENT-ON* */
-static uword
-interface_tx_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
- vlib_frame_t * from_frame)
+VLIB_NODE_FN (vnet_interface_output_arc_end_node)
+(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
{
vnet_main_t *vnm = vnet_get_main ();
- u32 last_sw_if_index = ~0;
- vlib_frame_t *to_frame = 0;
- vnet_hw_interface_t *hw = 0;
- u32 *from, *to_next = 0;
- u32 n_left_from;
-
- from = vlib_frame_vector_args (from_frame);
- n_left_from = from_frame->n_vectors;
- while (n_left_from > 0)
- {
- u32 bi0;
- vlib_buffer_t *b0;
- u32 sw_if_index0;
+ vnet_interface_main_t *im = &vnm->interface_main;
+ vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
+ u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
+ u32 *from, n_left;
+ u16 *lt = im->if_out_arc_end_next_index_by_sw_if_index;
- bi0 = from[0];
- from++;
- n_left_from--;
- b0 = vlib_get_buffer (vm, bi0);
- sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
+ from = vlib_frame_vector_args (frame);
+ n_left = frame->n_vectors;
+ vlib_get_buffers (vm, from, bufs, n_left);
- if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
- {
- if (to_frame)
- {
- hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
- vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
- }
- last_sw_if_index = sw_if_index0;
- hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
- to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
- to_next = vlib_frame_vector_args (to_frame);
- }
+ while (n_left >= 8)
+ {
+ vlib_prefetch_buffer_header (b[4], LOAD);
+ vlib_prefetch_buffer_header (b[5], LOAD);
+ vlib_prefetch_buffer_header (b[6], LOAD);
+ vlib_prefetch_buffer_header (b[7], LOAD);
+ next[0] = vec_elt (lt, vnet_buffer (b[0])->sw_if_index[VLIB_TX]);
+ next[1] = vec_elt (lt, vnet_buffer (b[1])->sw_if_index[VLIB_TX]);
+ next[2] = vec_elt (lt, vnet_buffer (b[2])->sw_if_index[VLIB_TX]);
+ next[3] = vec_elt (lt, vnet_buffer (b[3])->sw_if_index[VLIB_TX]);
- to_next[0] = bi0;
- to_next++;
- to_frame->n_vectors++;
+ b += 4;
+ next += 4;
+ n_left -= 4;
}
- vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
- return from_frame->n_vectors;
+
+ while (n_left)
+ {
+ next[0] = vec_elt (lt, vnet_buffer (b[0])->sw_if_index[VLIB_TX]);
+ b++;
+ next++;
+ n_left--;
+ }
+
+ vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
+ return frame->n_vectors;
}
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (interface_tx) = {
- .function = interface_tx_node_fn,
- .name = "interface-tx",
+VLIB_REGISTER_NODE (vnet_interface_output_arc_end_node) = {
+ .name = "interface-output-arc-end",
.vector_size = sizeof (u32),
.n_next_nodes = 1,
.next_nodes = {
},
};
-VNET_FEATURE_ARC_INIT (interface_output, static) =
-{
- .arc_name = "interface-output",
+VNET_FEATURE_ARC_INIT (interface_output, static) = {
+ .arc_name = "interface-output",
.start_nodes = VNET_FEATURES (0),
- .last_in_arc = "interface-tx",
+ .last_in_arc = "interface-output-arc-end",
.arc_index_ptr = &vnet_main.interface_main.output_feature_arc_index,
};
VNET_FEATURE_INIT (span_tx, static) = {
.arc_name = "interface-output",
.node_name = "span-output",
- .runs_before = VNET_FEATURES ("interface-tx"),
+ .runs_before = VNET_FEATURES ("interface-output-arc-end"),
};
VNET_FEATURE_INIT (ipsec_if_tx, static) = {
.arc_name = "interface-output",
.node_name = "ipsec-if-output",
- .runs_before = VNET_FEATURES ("interface-tx"),
+ .runs_before = VNET_FEATURES ("interface-output-arc-end"),
};
-VNET_FEATURE_INIT (interface_tx, static) = {
+VNET_FEATURE_INIT (interface_output_arc_end, static) = {
.arc_name = "interface-output",
- .node_name = "interface-tx",
+ .node_name = "interface-output-arc-end",
.runs_before = 0,
};
-/* *INDENT-ON* */
#ifndef CLIB_MARCH_VARIANT
clib_error_t *
VNET_FEATURE_INIT (stats_collect_tx_node, static) = {
.arc_name = "interface-output",
.node_name = "stats-collect-tx",
- .runs_before = VNET_FEATURES ("interface-tx"),
+ .runs_before = VNET_FEATURES ("interface-output-arc-end"),
};
/* *INDENT-ON* */