memif: add ip mode
In IP mode memif interface is L3 point-to-point interfaces and we don't pass l2 header. There is no l2 header rewrite operation and received packets are sent straight to ip4-input / ip6-input nodes. Change-Id: I4177f3fce3004da7ecf14d235006ae053fcf3f09 Signed-off-by: Damjan Marion <damarion@cisco.com>
This commit is contained in:
Damjan Marion
committed by
Florin Coras
parent
f03a59ab00
commit
45ca2c7a9c
@ -62,6 +62,8 @@ memif_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
args.is_master = 1;
|
||||
else if (unformat (line_input, "slave"))
|
||||
args.is_master = 0;
|
||||
else if (unformat (line_input, "mode ip"))
|
||||
args.mode = MEMIF_INTERFACE_MODE_IP;
|
||||
else if (unformat (line_input, "hw-addr %U",
|
||||
unformat_ethernet_address, args.hw_addr))
|
||||
args.hw_addr_set = 1;
|
||||
@ -107,7 +109,8 @@ VLIB_CLI_COMMAND (memif_create_command, static) = {
|
||||
.path = "create memif",
|
||||
.short_help = "create memif [id <id>] [socket <path>] "
|
||||
"[ring-size <size>] [buffer-size <size>] [hw-addr <mac-address>] "
|
||||
"<master|slave> [rx-queues <number>] [tx-queues <number>]",
|
||||
"<master|slave> [rx-queues <number>] [tx-queues <number>]"
|
||||
"[mode ip]",
|
||||
.function = memif_create_command_fn,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
@ -482,7 +482,10 @@ memif_delete_if (vlib_main_t * vm, memif_if_t * mif)
|
||||
clib_error_free (err);
|
||||
|
||||
/* remove the interface */
|
||||
ethernet_delete_interface (vnm, mif->hw_if_index);
|
||||
if (mif->mode == MEMIF_INTERFACE_MODE_IP)
|
||||
vnet_delete_hw_interface (vnm, mif->hw_if_index);
|
||||
else
|
||||
ethernet_delete_interface (vnm, mif->hw_if_index);
|
||||
mif->hw_if_index = ~0;
|
||||
|
||||
/* free interface data structures */
|
||||
@ -519,6 +522,14 @@ memif_delete_if (vlib_main_t * vm, memif_if_t * mif)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VNET_HW_INTERFACE_CLASS (memif_ip_hw_if_class, static) =
|
||||
{
|
||||
.name = "memif-ip",
|
||||
.flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
int
|
||||
memif_create_if (vlib_main_t * vm, memif_create_if_args_t * args)
|
||||
{
|
||||
@ -614,28 +625,43 @@ memif_create_if (vlib_main_t * vm, memif_create_if_args_t * args)
|
||||
mif->sw_if_index = mif->hw_if_index = mif->per_interface_next_index = ~0;
|
||||
mif->conn_unix_file_index = ~0;
|
||||
mif->conn_fd = -1;
|
||||
mif->mode = args->mode;
|
||||
if (args->secret)
|
||||
mif->secret = vec_dup (args->secret);
|
||||
|
||||
if (tm->n_vlib_mains > 1)
|
||||
clib_spinlock_init (&mif->lockp);
|
||||
|
||||
if (!args->hw_addr_set)
|
||||
|
||||
if (mif->mode == MEMIF_INTERFACE_MODE_ETHERNET)
|
||||
{
|
||||
f64 now = vlib_time_now (vm);
|
||||
u32 rnd;
|
||||
rnd = (u32) (now * 1e6);
|
||||
rnd = random_u32 (&rnd);
|
||||
|
||||
memcpy (args->hw_addr + 2, &rnd, sizeof (rnd));
|
||||
args->hw_addr[0] = 2;
|
||||
args->hw_addr[1] = 0xfe;
|
||||
if (!args->hw_addr_set)
|
||||
{
|
||||
f64 now = vlib_time_now (vm);
|
||||
u32 rnd;
|
||||
rnd = (u32) (now * 1e6);
|
||||
rnd = random_u32 (&rnd);
|
||||
|
||||
memcpy (args->hw_addr + 2, &rnd, sizeof (rnd));
|
||||
args->hw_addr[0] = 2;
|
||||
args->hw_addr[1] = 0xfe;
|
||||
}
|
||||
error = ethernet_register_interface (vnm, memif_device_class.index,
|
||||
mif->dev_instance, args->hw_addr,
|
||||
&mif->hw_if_index,
|
||||
memif_eth_flag_change);
|
||||
}
|
||||
|
||||
error = ethernet_register_interface (vnm, memif_device_class.index,
|
||||
mif->dev_instance, args->hw_addr,
|
||||
&mif->hw_if_index,
|
||||
memif_eth_flag_change);
|
||||
else if (mif->mode == MEMIF_INTERFACE_MODE_IP)
|
||||
{
|
||||
mif->hw_if_index =
|
||||
vnet_register_interface (vnm, memif_device_class.index,
|
||||
mif->dev_instance,
|
||||
memif_ip_hw_if_class.index,
|
||||
mif->dev_instance);
|
||||
}
|
||||
else
|
||||
error = clib_error_return (0, "unsupported interface mode");
|
||||
|
||||
if (error)
|
||||
{
|
||||
@ -725,7 +751,10 @@ memif_create_if (vlib_main_t * vm, memif_create_if_args_t * args)
|
||||
error:
|
||||
if (mif->hw_if_index != ~0)
|
||||
{
|
||||
ethernet_delete_interface (vnm, mif->hw_if_index);
|
||||
if (mif->mode == MEMIF_INTERFACE_MODE_IP)
|
||||
vnet_delete_hw_interface (vnm, mif->hw_if_index);
|
||||
else
|
||||
ethernet_delete_interface (vnm, mif->hw_if_index);
|
||||
mif->hw_if_index = ~0;
|
||||
}
|
||||
memif_delete_if (vm, mif);
|
||||
|
@ -30,7 +30,8 @@
|
||||
#include <memif/memif.h>
|
||||
#include <memif/private.h>
|
||||
|
||||
#define foreach_memif_input_error
|
||||
#define foreach_memif_input_error \
|
||||
_(NOT_IP, "not ip packet")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -200,16 +201,33 @@ memif_copy_buffer_from_rx_ring (vlib_main_t * vm, memif_if_t * mif,
|
||||
return (total_bytes);
|
||||
}
|
||||
|
||||
|
||||
static_always_inline u32
|
||||
memif_next_from_ip_hdr (vlib_node_runtime_t * node, vlib_buffer_t * b)
|
||||
{
|
||||
u8 *ptr = vlib_buffer_get_current (b);
|
||||
u8 v = *ptr & 0xf0;
|
||||
|
||||
if (PREDICT_TRUE (v == 0x40))
|
||||
return VNET_DEVICE_INPUT_NEXT_IP4_NCS_INPUT;
|
||||
else if (PREDICT_TRUE (v == 0x60))
|
||||
return VNET_DEVICE_INPUT_NEXT_IP6_INPUT;
|
||||
|
||||
b->error = node->errors[MEMIF_INPUT_ERROR_NOT_IP];
|
||||
return VNET_DEVICE_INPUT_NEXT_DROP;
|
||||
}
|
||||
|
||||
static_always_inline uword
|
||||
memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame, memif_if_t * mif,
|
||||
memif_ring_type_t type, u16 qid)
|
||||
memif_ring_type_t type, u16 qid,
|
||||
memif_interface_mode_t mode)
|
||||
{
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
memif_ring_t *ring;
|
||||
memif_queue_t *mq;
|
||||
u16 head;
|
||||
u32 next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
|
||||
u32 next_index;
|
||||
uword n_trace = vlib_get_trace_count (vm, node);
|
||||
memif_main_t *nm = &memif_main;
|
||||
u32 n_rx_packets = 0;
|
||||
@ -227,8 +245,14 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
ring_size = 1 << mq->log2_ring_size;
|
||||
mask = ring_size - 1;
|
||||
|
||||
if (mif->per_interface_next_index != ~0)
|
||||
next_index = mif->per_interface_next_index;
|
||||
if (mode == MEMIF_INTERFACE_MODE_IP)
|
||||
{
|
||||
next_index = VNET_DEVICE_INPUT_NEXT_IP6_INPUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_index = VNET_DEVICE_INPUT_NEXT_ETHERNET_INPUT;
|
||||
}
|
||||
|
||||
n_free_bufs = vec_len (nm->rx_buffers[thread_index]);
|
||||
if (PREDICT_FALSE (n_free_bufs < ring_size))
|
||||
@ -308,6 +332,24 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
to_next += 2;
|
||||
n_left_to_next -= 2;
|
||||
|
||||
|
||||
if (mode == MEMIF_INTERFACE_MODE_IP)
|
||||
{
|
||||
next0 = memif_next_from_ip_hdr (node, first_b0);
|
||||
next1 = memif_next_from_ip_hdr (node, first_b1);
|
||||
}
|
||||
else if (mode == MEMIF_INTERFACE_MODE_ETHERNET)
|
||||
{
|
||||
if (PREDICT_FALSE (mif->per_interface_next_index != ~0))
|
||||
next0 = next1 = mif->per_interface_next_index;
|
||||
else
|
||||
/* redirect if feature path
|
||||
* enabled */
|
||||
vnet_feature_start_device_input_x2 (mif->sw_if_index,
|
||||
&next0, &next1,
|
||||
first_b0, first_b1);
|
||||
}
|
||||
|
||||
/* trace */
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (first_b0);
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (first_b1);
|
||||
@ -343,11 +385,6 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
}
|
||||
}
|
||||
|
||||
/* redirect if feature path enabled */
|
||||
vnet_feature_start_device_input_x2 (mif->sw_if_index,
|
||||
&next0, &next1, first_b0,
|
||||
first_b1);
|
||||
|
||||
/* enqueue */
|
||||
vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
|
||||
n_left_to_next, first_bi0,
|
||||
@ -368,6 +405,21 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
&first_bi0, &bi0,
|
||||
&num_slots);
|
||||
|
||||
if (mode == MEMIF_INTERFACE_MODE_IP)
|
||||
{
|
||||
next0 = memif_next_from_ip_hdr (node, first_b0);
|
||||
}
|
||||
else if (mode == MEMIF_INTERFACE_MODE_ETHERNET)
|
||||
{
|
||||
if (PREDICT_FALSE (mif->per_interface_next_index != ~0))
|
||||
next0 = mif->per_interface_next_index;
|
||||
else
|
||||
/* redirect if feature path
|
||||
* enabled */
|
||||
vnet_feature_start_device_input_x1 (mif->sw_if_index,
|
||||
&next0, first_b0);
|
||||
}
|
||||
|
||||
/* trace */
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (first_b0);
|
||||
|
||||
@ -391,10 +443,6 @@ memif_device_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
to_next += 1;
|
||||
n_left_to_next--;
|
||||
|
||||
/* redirect if feature path enabled */
|
||||
vnet_feature_start_device_input_x1 (mif->sw_if_index, &next0,
|
||||
first_b0);
|
||||
|
||||
/* enqueue */
|
||||
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
|
||||
n_left_to_next, first_bi0, next0);
|
||||
@ -433,11 +481,27 @@ memif_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
(mif->flags & MEMIF_IF_FLAG_CONNECTED))
|
||||
{
|
||||
if (mif->flags & MEMIF_IF_FLAG_IS_SLAVE)
|
||||
n_rx += memif_device_input_inline (vm, node, frame, mif,
|
||||
MEMIF_RING_M2S, dq->queue_id);
|
||||
{
|
||||
if (mif->mode == MEMIF_INTERFACE_MODE_IP)
|
||||
n_rx += memif_device_input_inline (vm, node, frame, mif,
|
||||
MEMIF_RING_M2S, dq->queue_id,
|
||||
MEMIF_INTERFACE_MODE_IP);
|
||||
else
|
||||
n_rx += memif_device_input_inline (vm, node, frame, mif,
|
||||
MEMIF_RING_M2S, dq->queue_id,
|
||||
MEMIF_INTERFACE_MODE_ETHERNET);
|
||||
}
|
||||
else
|
||||
n_rx += memif_device_input_inline (vm, node, frame, mif,
|
||||
MEMIF_RING_S2M, dq->queue_id);
|
||||
{
|
||||
if (mif->mode == MEMIF_INTERFACE_MODE_IP)
|
||||
n_rx += memif_device_input_inline (vm, node, frame, mif,
|
||||
MEMIF_RING_S2M, dq->queue_id,
|
||||
MEMIF_INTERFACE_MODE_IP);
|
||||
else
|
||||
n_rx += memif_device_input_inline (vm, node, frame, mif,
|
||||
MEMIF_RING_S2M, dq->queue_id,
|
||||
MEMIF_INTERFACE_MODE_ETHERNET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,7 @@ memif_msg_enq_init (memif_if_t * mif)
|
||||
e->fd = -1;
|
||||
i->version = MEMIF_VERSION;
|
||||
i->id = mif->id;
|
||||
i->mode = mif->mode;
|
||||
s = format (0, "VPP %s%c", VPP_BUILD_VER, 0);
|
||||
strncpy ((char *) i->name, (char *) s, sizeof (i->name));
|
||||
if (mif->secret)
|
||||
|
Reference in New Issue
Block a user