#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,
}
ei = pool_elt_at_index (em->interfaces, hw->hw_instance);
- memcpy (h->src_address, ei->address, sizeof (h->src_address));
+ clib_memcpy (h->src_address, ei->address, sizeof (h->src_address));
if (dst_address)
- memcpy (h->dst_address, dst_address, sizeof (h->dst_address));
+ clib_memcpy (h->dst_address, dst_address, sizeof (h->dst_address));
else
memset (h->dst_address, ~0, sizeof (h->dst_address)); /* broadcast */
ethernet_setup_node (vnm->vlib_main, hi->output_node_index);
- hi->min_packet_bytes = ETHERNET_MIN_PACKET_BYTES;
- hi->max_packet_bytes = ETHERNET_MAX_PACKET_BYTES;
+ hi->min_packet_bytes = hi->min_supported_packet_bytes = ETHERNET_MIN_PACKET_BYTES;
+ hi->max_packet_bytes = hi->max_supported_packet_bytes = ETHERNET_MAX_PACKET_BYTES;
hi->per_packet_overhead_bytes =
/* preamble */ 8 + /* inter frame gap */ 12;
/* Standard default ethernet MTU. */
hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] = 9000;
- memcpy (ei->address, address, sizeof (ei->address));
+ clib_memcpy (ei->address, address, sizeof (ei->address));
vec_free (hi->hw_address);
vec_add (hi->hw_address, address, sizeof (ei->address));
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,
{
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);
n_copy = clib_min (n_left_from, n_left_to_next);
- memcpy (to_next, from, n_copy * sizeof (from[0]));
+ 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;
* address is programmed on the loopback interface.
*/
if (memcmp (address, mac_address, sizeof (address)))
- memcpy (address, mac_address, sizeof (address));
+ clib_memcpy (address, mac_address, sizeof (address));
else
{
address[0] = 0xde;
if (rv)
return clib_error_return (0, "vnet_create_loopback_interface failed");
+ vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), sw_if_index);
return 0;
}