diff options
author | John Lo <loj@cisco.com> | 2016-04-23 15:14:12 -0400 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2016-04-25 12:58:41 +0000 |
commit | 405e41b50e336dccfdeeafae93bf4453774ecfec (patch) | |
tree | 021e77ef0458f1b2e814655d1d64a0b5b08f7613 /vnet/vnet/ethernet/interface.c | |
parent | d06b9f9cbf9402d66d26fc638a12b84ade197848 (diff) |
Improve mechanism for using loopback interface as BVI for BDs
When loopback interface is configured as BVI, instead of changing its
output node from loopN-output to l2-input, the loopN-output node is now
kept while its next tx node is changed from ethernet-input to l2-input.
The packet setup previously done in bvi_to_l2 as part of l2-input is now
performed in the loop output node.
This change adds an extra node in the BVI output path but provides the
following improvements:
1. IP address/route created on loopback prior to it being configured as
BVI will still work properly. The requirement to (re)configure IP/route
on loopback after it is configured as BVI is removed.
2. The output stats for loopback interfaces are always provided irrespective
of their BVI configuration.
3. The loopback-BVI output stats can be batch updated outside the packet
loop in output node, instead of per packet update in l2-input node,
making l2-input node more efficient for BVI packets.
4. Restore original node property as implemented in node.c function
vlib_node_add_next_with_slot() where next node indices stored in next
slots of each node will remain unique.
5. Packet trace for BVI output includes loopN output node which provides
useful packet data.
Change-Id: I7f5bc72ef953a367363a179088210596881f9e73
Signed-off-by: John Lo <loj@cisco.com>
Diffstat (limited to 'vnet/vnet/ethernet/interface.c')
-rw-r--r-- | vnet/vnet/ethernet/interface.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/vnet/vnet/ethernet/interface.c b/vnet/vnet/ethernet/interface.c index bb8c75364c8..6bc9f281a15 100644 --- a/vnet/vnet/ethernet/interface.c +++ b/vnet/vnet/ethernet/interface.c @@ -41,6 +41,7 @@ #include <vnet/ip/ip.h> #include <vnet/pg/pg.h> #include <vnet/ethernet/ethernet.h> +#include <vnet/l2/l2_input.h> static uword ethernet_set_rewrite (vnet_main_t * vnm, u32 sw_if_index, @@ -255,9 +256,7 @@ ethernet_set_flags (vnet_main_t * vnm, u32 hw_if_index, u32 flags) return (u32)~0; } -#define VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT VNET_INTERFACE_TX_N_NEXT - -/* Echo packets back to ethernet input. */ +/* Echo packets back to ethernet/l2-input. */ static uword simulated_ethernet_interface_tx (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -265,9 +264,22 @@ simulated_ethernet_interface_tx (vlib_main_t * vm, { u32 n_left_from, n_left_to_next, n_copy, * from, * to_next; u32 next_index = VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT; - u32 i; + u32 i, next_node_index, bvi_flag, sw_if_index; + u32 n_pkts = 0, n_bytes = 0; + u32 cpu_index = vm->cpu_index; + vnet_main_t * vnm = vnet_get_main(); + vnet_interface_main_t * im = &vnm->interface_main; + vlib_node_main_t * nm = &vm->node_main; + vlib_node_t *loop_node; vlib_buffer_t * b; + // check tx node index, it is ethernet-input on loopback create + // but can be changed to l2-input if loopback is configured as + // BVI of a BD (Bridge Domain). + loop_node = vec_elt (nm->nodes, node->node_index); + next_node_index = loop_node->next_nodes[next_index]; + bvi_flag = (next_node_index == l2input_node.index)? 1 : 0; + n_left_from = frame->n_vectors; from = vlib_frame_args (frame); @@ -280,16 +292,32 @@ simulated_ethernet_interface_tx (vlib_main_t * vm, clib_memcpy (to_next, from, n_copy * sizeof (from[0])); n_left_to_next -= n_copy; n_left_from -= n_copy; - for (i = 0; i < n_copy; i++) + i = 0; + b = vlib_get_buffer (vm, from[i]); + sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_TX]; + while (1) { - b = vlib_get_buffer (vm, from[i]); - /* Set up RX and TX indices as if received from a real driver */ - vnet_buffer (b)->sw_if_index[VLIB_RX] = - vnet_buffer (b)->sw_if_index[VLIB_TX]; - vnet_buffer (b)->sw_if_index[VLIB_TX] = (u32) ~0; + // Set up RX and TX indices as if received from a real driver + // unless loopback is used as a BVI. For BVI case, leave TX index + // and update l2_len in packet as required for l2 forwarding path + vnet_buffer (b)->sw_if_index[VLIB_RX] = sw_if_index; + if (bvi_flag) vnet_update_l2_len(b); + else vnet_buffer (b)->sw_if_index[VLIB_TX] = (u32) ~0; + + i++; + n_pkts++; + n_bytes += vlib_buffer_length_in_chain (vm, b); + + if (i < n_copy) b = vlib_get_buffer (vm, from[i]); + else break; } vlib_put_next_frame (vm, node, next_index, n_left_to_next); + + /* increment TX interface stat */ + vlib_increment_combined_counter ( + im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, + cpu_index, sw_if_index, n_pkts, n_bytes); } return n_left_from; |