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
2017-06-16 22:06:00 +02:00
committed by Florin Coras
parent f03a59ab00
commit 45ca2c7a9c
4 changed files with 131 additions and 34 deletions

View File

@ -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* */

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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)