aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Mazur <mkm@semihalf.com>2017-08-21 15:01:42 +0200
committerMichal Mazur <mkm@semihalf.com>2017-12-14 15:18:05 +0100
commit4c34d6c16947c5e1465319d9d44dbdaaa2f04c4e (patch)
tree47aecd5a2719916187f319357efde738674ae788
parent7e1f3998634c89aa6344468d26df0de519578a5f (diff)
Read ODP configuration from VPP startup config
1) Allow to setup size of allocated memory, number of packets in the pool, number of packets in transmit burst and delay in scheduler mode from VPP startup file. More details are in template: src/vpp/conf/startup.conf 2) Separate Rx mode from Tx mode. Traffic Manager is not supported. 3) Devices defined in VPP startup are automatically created at start. Change-Id: I1f8a3c2900f56cb23ce6997d311cfe55e1c2078c Signed-off-by: Michal Mazur <mkm@semihalf.com>
-rw-r--r--README.vppodp9
-rwxr-xr-xsrc/plugins/odp/cli.c20
-rwxr-xr-xsrc/plugins/odp/device.c16
-rwxr-xr-xsrc/plugins/odp/node.c11
-rwxr-xr-xsrc/plugins/odp/odp_packet.c314
-rwxr-xr-xsrc/plugins/odp/odp_packet.h29
-rw-r--r--src/vpp/conf/startup.conf36
7 files changed, 352 insertions, 83 deletions
diff --git a/README.vppodp b/README.vppodp
index 6e53698..fe1e298 100644
--- a/README.vppodp
+++ b/README.vppodp
@@ -73,10 +73,13 @@ Below is a basic verification test.
Note :For odp-dpdk the port has to bound with dpdk driver prior to test and interface name is passed as 0,1..etc.
-1)Configure odp packet interface with mode ie (0-burst,1-queue,2-schedule) default mode is 0.
- Setting rx-queues to more than 1 will enable RSS.
+1)Configure odp packet interface with Rx/Tx mode and number of queues.
+ Rx mode can be set to 0-burst, 1-queue, 2-schedule (default mode is burst).
+ Tx mode can be set to 0-burst, 1-queue (default mode is burst)
+ Number of Rx queues can be 1 or more. It will determine number of threads and enable RSS (default is 1).
+ Number of Tx queues can be 0 (equal to number of threads, default) or 1 (single shared queue).
--create pktio-interface name <int name> hw-addr <mac> mode <0/1/2> rx-queues <number of input queues>
+-create pktio-interface name <int name> hw-addr <mac> rx-mode <0/1/2> rx-queues <num queues> tx-mode <0/1> tx-queues <num queues>
-set int ip address odp-<int name> X.X.X.X/24
-set int state odp-<int name> up
diff --git a/src/plugins/odp/cli.c b/src/plugins/odp/cli.c
index 4da921a..2392ca1 100755
--- a/src/plugins/odp/cli.c
+++ b/src/plugins/odp/cli.c
@@ -25,14 +25,14 @@ odp_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
u8 *host_if_name = NULL;
u8 hwaddr[6];
u8 *hw_addr_ptr = 0;
- u32 sw_if_index;
- u32 mode = APPL_MODE_PKT_BURST;
- u32 rx_queues = 0;
+ u32 sw_if_index, num;
+ odp_if_mode_t if_mode;
int r;
if (!unformat_user (input, unformat_line_input, line_input))
return 0;
+ if_mode = def_if_mode;
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
{
@@ -42,10 +42,14 @@ odp_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
if (unformat
(line_input, "hw-addr %U", unformat_ethernet_address, hwaddr))
hw_addr_ptr = hwaddr;
- else if (unformat (line_input, "mode %d", &mode))
- ;
- else if (unformat (line_input, "rx-queues %d", &rx_queues))
- ;
+ else if (unformat (line_input, "rx-mode %d", &num))
+ if_mode.rx_mode = num;
+ else if (unformat (line_input, "tx-mode %d", &num))
+ if_mode.tx_mode = num;
+ else if (unformat (line_input, "rx-queues %d", &num))
+ if_mode.num_rx_queues = num;
+ else if (unformat (line_input, "tx-queues %d", &num))
+ if_mode.num_tx_queues = num;
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
@@ -56,7 +60,7 @@ odp_packet_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
return clib_error_return (0, "missing host interface name");
r = odp_packet_create_if (vm, host_if_name, hw_addr_ptr, &sw_if_index,
- mode, rx_queues);
+ &if_mode);
vec_free (host_if_name);
if (r == VNET_API_ERROR_SYSCALL_ERROR_1)
diff --git a/src/plugins/odp/device.c b/src/plugins/odp/device.c
index 68397db..eebc2aa 100755
--- a/src/plugins/odp/device.c
+++ b/src/plugins/odp/device.c
@@ -77,10 +77,11 @@ odp_packet_interface_tx (vlib_main_t * vm,
u32 n_left = frame->n_vectors;
vnet_interface_output_runtime_t *rd = (void *) node->runtime_data;
odp_packet_if_t *oif = pool_elt_at_index (om->interfaces, rd->dev_instance);
- uword queue_index = vlib_get_thread_index () % oif->tx_queues;
- u32 mode = oif->mode;
- odp_packet_t pkt_tbl[VLIB_FRAME_SIZE];
- odp_event_t evt_tbl[VLIB_FRAME_SIZE];
+ uword queue_index = vlib_get_thread_index () % oif->m.num_tx_queues;
+ u32 mode = oif->m.tx_mode;
+ u32 burst_size = (tx_burst_size ? tx_burst_size : VLIB_FRAME_SIZE);
+ odp_packet_t pkt_tbl[burst_size];
+ odp_event_t evt_tbl[burst_size];
vlib_buffer_t *b0;
u32 bi, sent, count = 0;
@@ -122,10 +123,9 @@ odp_packet_interface_tx (vlib_main_t * vm,
count++;
bi = b0->next_buffer;
}
- while ((b0->flags & VLIB_BUFFER_NEXT_PRESENT)
- && (count < VLIB_FRAME_SIZE));
+ while ((b0->flags & VLIB_BUFFER_NEXT_PRESENT) && (count < burst_size));
- if ((n_left > 0) && (count < VLIB_FRAME_SIZE))
+ if ((n_left > 0) && (count < burst_size))
continue;
sent = 0;
@@ -133,7 +133,6 @@ odp_packet_interface_tx (vlib_main_t * vm,
{
switch (mode)
{
- case APPL_MODE_PKT_SCHED:
case APPL_MODE_PKT_BURST:
ret =
odp_pktout_send (oif->outq[queue_index], &pkt_tbl[sent],
@@ -143,6 +142,7 @@ odp_packet_interface_tx (vlib_main_t * vm,
ret = odp_queue_enq_multi (oif->txq[queue_index],
&evt_tbl[sent], count);
break;
+ case APPL_MODE_PKT_TM:
default:
ret = 0;
clib_error ("Invalid mode\n");
diff --git a/src/plugins/odp/node.c b/src/plugins/odp/node.c
index f7e02b7..1a8b04c 100755
--- a/src/plugins/odp/node.c
+++ b/src/plugins/odp/node.c
@@ -80,7 +80,7 @@ odp_packet_queue_mode (odp_packet_if_t * oif, odp_packet_t pkt_tbl[],
clib_warning ("invalid oif->pktio value");
return 0;
}
- if ((oif->mode == APPL_MODE_PKT_QUEUE) &&
+ if ((oif->m.rx_mode == APPL_MODE_PKT_QUEUE) &&
(oif->rxq[queue_id] == ODP_QUEUE_INVALID))
{
clib_warning ("invalid rxq[%d] queue", queue_id);
@@ -89,14 +89,15 @@ odp_packet_queue_mode (odp_packet_if_t * oif, odp_packet_t pkt_tbl[],
while (req_pkts)
{
- if (oif->mode == APPL_MODE_PKT_QUEUE)
+ if (oif->m.rx_mode == APPL_MODE_PKT_QUEUE)
{
i = odp_queue_deq_multi (oif->rxq[queue_id],
&evt_tbl[num_evts], req_pkts);
}
else
{
- sched_wait = odp_schedule_wait_time (ODP_TIME_USEC_IN_NS);
+ sched_wait = odp_schedule_wait_time (ODP_TIME_USEC_IN_NS *
+ rx_sched_wait);
i = odp_schedule_multi (NULL, sched_wait,
&evt_tbl[num_evts], req_pkts);
}
@@ -229,8 +230,8 @@ odp_packet_device_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
do
{
- if ((oif->mode == (APPL_MODE_PKT_QUEUE)) ||
- (oif->mode == (APPL_MODE_PKT_SCHED)))
+ if ((oif->m.rx_mode == (APPL_MODE_PKT_QUEUE)) ||
+ (oif->m.rx_mode == (APPL_MODE_PKT_SCHED)))
{
pkts =
odp_packet_queue_mode (oif, pkt_tbl, queue_id, n_left_to_next);
diff --git a/src/plugins/odp/odp_packet.c b/src/plugins/odp/odp_packet.c
index bcb8a48..86992c6 100755
--- a/src/plugins/odp/odp_packet.c
+++ b/src/plugins/odp/odp_packet.c
@@ -10,11 +10,17 @@
#include <vlib/unix/unix.h>
#include <vnet/ip/ip.h>
#include <vnet/ethernet/ethernet.h>
-#include <odp/odp_packet.h>
#include <vnet/plugin/plugin.h>
#include <vpp/app/version.h>
+#include <odp/odp_packet.h>
odp_packet_main_t *odp_packet_main;
+odp_platform_init_t platform_params;
+u32 rx_sched_wait;
+u32 tx_burst_size;
+u32 num_pkts_in_pool = SHM_PKT_POOL_NB_PKTS;
+odp_if_mode_t def_if_mode;
+odp_if_config_t *if_config;
static u32
odp_packet_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi,
@@ -61,8 +67,7 @@ drop_err_pkts (odp_packet_t pkt_tbl[], unsigned len)
}
static odp_pktio_t
-create_pktio (const char *dev, odp_pool_t pool, u32 mode,
- odp_packet_if_t * oif)
+create_pktio (const char *dev, odp_pool_t pool, odp_packet_if_t * oif)
{
odp_pktio_t pktio;
int ret;
@@ -75,22 +80,35 @@ create_pktio (const char *dev, odp_pool_t pool, u32 mode,
odp_pktio_param_init (&pktio_param);
- switch (mode)
+ switch (oif->m.rx_mode)
{
case APPL_MODE_PKT_BURST:
pktio_param.in_mode = ODP_PKTIN_MODE_DIRECT;
- pktio_param.out_mode = ODP_PKTOUT_MODE_DIRECT;
break;
case APPL_MODE_PKT_QUEUE:
pktio_param.in_mode = ODP_PKTIN_MODE_QUEUE;
- pktio_param.out_mode = ODP_PKTOUT_MODE_QUEUE;
break;
case APPL_MODE_PKT_SCHED:
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
+ break;
+ default:
+ clib_warning ("Invalid RX mode\n");
+ }
+
+ switch (oif->m.tx_mode)
+ {
+ case APPL_MODE_PKT_BURST:
pktio_param.out_mode = ODP_PKTOUT_MODE_DIRECT;
break;
+ case APPL_MODE_PKT_QUEUE:
+ pktio_param.out_mode = ODP_PKTOUT_MODE_QUEUE;
+ break;
+ case APPL_MODE_PKT_TM:
+ clib_error ("Traffic Manager mode not supported!\n");
+ pktio_param.out_mode = ODP_PKTOUT_MODE_TM;
+ break;
default:
- clib_warning ("Invalid mode\n");
+ clib_warning ("Invalid TX mode\n");
}
/* Open a packet IO instance */
@@ -115,28 +133,29 @@ create_pktio (const char *dev, odp_pool_t pool, u32 mode,
odp_pktin_queue_param_init (&pktin_param);
pktin_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;
- if (oif->rx_queues > capa.max_input_queues)
+ if (oif->m.num_rx_queues > capa.max_input_queues)
{
- oif->rx_queues = capa.max_input_queues;
- clib_warning ("Number of RX queues limited to %d\n", oif->rx_queues);
+ oif->m.num_rx_queues = capa.max_input_queues;
+ clib_warning ("pktio %s: Number of RX queues limited to %d\n",
+ dev, oif->m.num_rx_queues);
}
- if (oif->rx_queues > 1)
+ if (oif->m.num_rx_queues > 1)
{
- if (oif->rx_queues > MAX_QUEUES)
- oif->rx_queues = MAX_QUEUES;
+ if (oif->m.num_rx_queues > MAX_QUEUES)
+ oif->m.num_rx_queues = MAX_QUEUES;
pktin_param.classifier_enable = 0;
pktin_param.hash_enable = 1;
- pktin_param.num_queues = oif->rx_queues;
+ pktin_param.num_queues = oif->m.num_rx_queues;
pktin_param.hash_proto.proto.ipv4_udp = 1;
pktin_param.hash_proto.proto.ipv4_tcp = 1;
pktin_param.hash_proto.proto.ipv4 = 1;
}
else
- oif->rx_queues = 1;
+ oif->m.num_rx_queues = 1;
- if (mode == APPL_MODE_PKT_SCHED)
+ if (oif->m.rx_mode == APPL_MODE_PKT_SCHED)
pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;
if (odp_pktin_queue_config (pktio, &pktin_param))
@@ -145,15 +164,16 @@ create_pktio (const char *dev, odp_pool_t pool, u32 mode,
}
odp_pktout_queue_param_init (&pktout_param);
- if (capa.max_output_queues >= tm->n_vlib_mains)
+ if ((capa.max_output_queues >= tm->n_vlib_mains) &&
+ (oif->m.num_tx_queues == 0))
{
pktout_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;
pktout_param.num_queues = tm->n_vlib_mains;
- oif->tx_queues = tm->n_vlib_mains;
+ oif->m.num_tx_queues = tm->n_vlib_mains;
}
else
{
- oif->tx_queues = 1;
+ oif->m.num_tx_queues = 1;
}
if (odp_pktout_queue_config (pktio, &pktout_param))
@@ -172,7 +192,7 @@ create_pktio (const char *dev, odp_pool_t pool, u32 mode,
u32
odp_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
- u32 * sw_if_index, u32 mode, u32 rx_queues)
+ u32 * sw_if_index, odp_if_mode_t * mode)
{
odp_packet_main_t *om = odp_packet_main;
int ret = 0, j;
@@ -182,7 +202,6 @@ odp_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
vnet_sw_interface_t *sw;
vnet_main_t *vnm = vnet_get_main ();
uword *p;
- u8 *host_if_name_dup = vec_dup (host_if_name);
vlib_thread_main_t *tm = vlib_get_thread_main ();
p = mhash_get (&om->if_index_by_host_if_name, host_if_name);
@@ -191,17 +210,21 @@ odp_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
pool_get (om->interfaces, oif);
oif->if_index = oif - om->interfaces;
- oif->host_if_name = host_if_name_dup;
+ oif->host_if_name = vec_dup (host_if_name);
oif->per_interface_next_index = ~0;
+ oif->m = *mode;
- if (mode == APPL_MODE_PKT_SCHED)
- oif->rx_queues = tm->n_vlib_mains - 1;
- else
- oif->rx_queues = rx_queues;
+ if (mode->rx_mode == APPL_MODE_PKT_SCHED)
+ oif->m.num_rx_queues = tm->n_vlib_mains - 1;
/* Create a pktio instance */
- oif->pktio = create_pktio ((char *) host_if_name, om->pool, mode, oif);
- oif->mode = mode;
+ oif->pktio = create_pktio ((char *) host_if_name, om->pool, oif);
+ if (oif->pktio == 0)
+ {
+ ret = VNET_API_ERROR_INVALID_INTERFACE;
+ goto error;
+ }
+
om->if_count++;
if (tm->n_vlib_mains > 1)
@@ -211,22 +234,21 @@ odp_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
memset ((void *) oif->lockp, 0, CLIB_CACHE_LINE_BYTES);
}
- if ((mode == APPL_MODE_PKT_BURST) || (mode == APPL_MODE_PKT_SCHED))
- {
- odp_pktin_queue (oif->pktio, oif->inq, oif->rx_queues);
- odp_pktout_queue (oif->pktio, oif->outq, oif->tx_queues);
- }
- else if (mode == APPL_MODE_PKT_QUEUE)
- {
- odp_pktin_event_queue (oif->pktio, oif->rxq, oif->rx_queues);
- odp_pktout_event_queue (oif->pktio, oif->txq, oif->tx_queues);
- }
+ if (mode->rx_mode == APPL_MODE_PKT_BURST)
+ odp_pktin_queue (oif->pktio, oif->inq, oif->m.num_rx_queues);
+ else if (mode->rx_mode == APPL_MODE_PKT_QUEUE)
+ odp_pktin_event_queue (oif->pktio, oif->rxq, oif->m.num_rx_queues);
+ if (mode->tx_mode == APPL_MODE_PKT_BURST)
+ odp_pktout_queue (oif->pktio, oif->outq, oif->m.num_tx_queues);
+ else if (mode->tx_mode == APPL_MODE_PKT_QUEUE)
+ odp_pktout_event_queue (oif->pktio, oif->txq, oif->m.num_tx_queues);
- /*use configured or generate random MAC address */
+ /* Use configured MAC or read MAC from DPDK */
if (hw_addr_set)
clib_memcpy (hw_addr, hw_addr_set, 6);
- else
+ else if (odp_pktio_mac_addr (oif->pktio, hw_addr, sizeof (hw_addr)) < 6)
{
+ /* Failed to read MAC from driver, set random MAC */
f64 now = vlib_time_now (vm);
u32 rnd;
rnd = (u32) (now * 1e6);
@@ -244,8 +266,6 @@ odp_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
if (error)
{
- memset (oif, 0, sizeof (*oif));
- pool_put (om->interfaces, oif);
clib_error_report (error);
ret = VNET_API_ERROR_SYSCALL_ERROR_1;
goto error;
@@ -259,15 +279,15 @@ odp_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
vnet_hw_interface_set_flags (vnm, oif->hw_if_index,
VNET_HW_INTERFACE_FLAG_LINK_UP);
- mhash_set_mem (&om->if_index_by_host_if_name, host_if_name_dup,
+ mhash_set_mem (&om->if_index_by_host_if_name, oif->host_if_name,
&oif->if_index, 0);
if (sw_if_index)
*sw_if_index = oif->sw_if_index;
/* Assign queues of the new interface to first available worker thread */
- for (j = 0; j < oif->rx_queues; j++)
+ for (j = 0; j < oif->m.num_rx_queues; j++)
{
- if (mode == APPL_MODE_PKT_SCHED)
+ if (mode->rx_mode == APPL_MODE_PKT_SCHED)
vnet_hw_interface_assign_rx_thread (vnm, oif->hw_if_index, 0, j + 1);
else
vnet_hw_interface_assign_rx_thread (vnm, oif->hw_if_index, j, -1);
@@ -276,7 +296,9 @@ odp_packet_create_if (vlib_main_t * vm, u8 * host_if_name, u8 * hw_addr_set,
return 0;
error:
- vec_free (host_if_name_dup);
+ vec_free (oif->host_if_name);
+ memset (oif, 0, sizeof (*oif));
+ pool_put (om->interfaces, oif);
return ret;
}
@@ -326,6 +348,191 @@ odp_packet_delete_if (vlib_main_t * vm, u8 * host_if_name)
}
static clib_error_t *
+odp_device_config (char *name, unformat_input_t * input)
+{
+ odp_if_mode_t mode;
+ odp_if_config_t *config;
+ char *val;
+ u32 num;
+ u8 set_hw_addr = 0;
+ u8 hw_addr[6];
+
+ mode = def_if_mode;
+
+ if (input)
+ {
+ unformat_skip_white_space (input);
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "rx-mode %s", &val))
+ {
+ if (!strcmp (val, "burst") || !strcmp (val, "0"))
+ mode.rx_mode = APPL_MODE_PKT_BURST;
+ else if (!strcmp (val, "queue") || !strcmp (val, "1"))
+ mode.rx_mode = APPL_MODE_PKT_QUEUE;
+ else if (!strcmp (val, "sched") || !strcmp (val, "2"))
+ mode.rx_mode = APPL_MODE_PKT_SCHED;
+ vec_free (val);
+ }
+ else if (unformat (input, "tx-mode %s", &val))
+ {
+ if (!strcmp (val, "burst") || !strcmp (val, "0"))
+ mode.tx_mode = APPL_MODE_PKT_BURST;
+ else if (!strcmp (val, "queue") || !strcmp (val, "1"))
+ mode.tx_mode = APPL_MODE_PKT_QUEUE;
+ else if (!strcmp (val, "tm") || !strcmp (val, "2"))
+ mode.tx_mode = APPL_MODE_PKT_TM;
+ vec_free (val);
+ }
+ else if (unformat (input, "num-rx-queues %u", &num))
+ mode.num_rx_queues = num;
+ else if (unformat (input, "num-tx-queues %u", &num))
+ mode.num_tx_queues = num;
+ else if (unformat (input, "num-tx-queues %s", &val))
+ {
+ if (!strcmp (val, "max"))
+ mode.num_tx_queues = 0;
+ vec_free (val);
+ }
+ else if (unformat (input, "hw-addr %U", unformat_ethernet_address,
+ hw_addr))
+ set_hw_addr = 1;
+ else if (unformat (input, "%s", &val))
+ {
+ clib_warning ("%s: Unknown option %s\n", __func__, val);
+ vec_free (val);
+ }
+ }
+ }
+
+ if (!name)
+ {
+ def_if_mode = mode;
+ return 0;
+ }
+
+ /* Save configuration */
+ pool_get (if_config, config);
+ config->name = (u8 *) vec_dup (name);
+ config->mode = mode;
+ clib_memcpy (config->hw_addr, hw_addr, 6);
+ config->set_hw_addr = set_hw_addr;
+
+ return 0;
+}
+
+static clib_error_t *
+odp_config (vlib_main_t * vm, unformat_input_t * input)
+{
+ char *param = NULL;
+ u32 num;
+ unformat_input_t sub_input;
+ unformat_input_t line_input;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "platform-params %U",
+ unformat_vlib_cli_sub_input, &sub_input))
+ {
+ unformat_skip_white_space (&sub_input);
+ while (unformat_check_input (&sub_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (&sub_input, "memory %u", &num))
+ platform_params.memory = num;
+ else if (unformat (&sub_input, "cmdline %U",
+ unformat_vlib_cli_sub_input, &line_input))
+ {
+ unformat (&line_input, "%U", unformat_line, &param);
+ platform_params.cmdline = param;
+ unformat_free (&line_input);
+ }
+ else if (unformat (&sub_input, "%s", &param))
+ {
+ clib_warning ("%s: Unknown platform option %s\n", __func__,
+ param);
+ vec_free (param);
+ }
+ }
+ unformat_free (&sub_input);
+ }
+ else if (unformat (input, "rx-sched-wait %u", &rx_sched_wait))
+ ;
+ else if (unformat (input, "tx-burst-size %u", &tx_burst_size))
+ ;
+ else if (unformat (input, "num-pkts-in-pool %u", &num_pkts_in_pool))
+ ;
+ else if (unformat (input, "default %U", unformat_vlib_cli_sub_input,
+ &sub_input))
+ {
+ odp_device_config (NULL, &sub_input);
+ unformat_free (&sub_input);
+ }
+ else if (unformat (input, "dev %s %U", &param,
+ unformat_vlib_cli_sub_input, &sub_input))
+ {
+ odp_device_config (param, &sub_input);
+ vec_free (param);
+ unformat_free (&sub_input);
+ }
+ else if (unformat (input, "dev %s", &param))
+ {
+ odp_device_config (param, NULL);
+ vec_free (param);
+ }
+ else if (unformat (input, "%s", &param))
+ {
+ clib_warning ("%s: Unknown option %s\n", __func__, param);
+ vec_free (param);
+ }
+ }
+
+ return 0;
+}
+
+VLIB_EARLY_CONFIG_FUNCTION (odp_config, "odp");
+
+static uword
+odp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
+{
+ u32 i, ret;
+ odp_if_config_t *config;
+ vlib_thread_main_t *tm = vlib_get_thread_main ();
+
+ /* Create interfaces defined in startup configuration file */
+ for (i = 0; i < pool_len (if_config); i++)
+ {
+ config = pool_elt_at_index (if_config, i);
+ ret = odp_packet_create_if (vm, config->name,
+ (config->set_hw_addr ? config->hw_addr :
+ NULL), NULL, &config->mode);
+ vec_free (config->name);
+
+ if (ret == VNET_API_ERROR_SYSCALL_ERROR_1)
+ clib_warning ("%s (errno %d)", strerror (errno), errno);
+
+ if (ret == VNET_API_ERROR_INVALID_INTERFACE)
+ clib_warning ("Invalid interface name");
+
+ if (ret == VNET_API_ERROR_SUBIF_ALREADY_EXISTS)
+ clib_warning ("Interface already exists");
+ }
+ pool_free (if_config);
+
+ /* Initialization complete and worker threads can start */
+ tm->worker_thread_release = 1;
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (odp_process_node,static) = {
+ .function = odp_process,
+ .type = VLIB_NODE_TYPE_PROCESS,
+ .name = "odp-process",
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
odp_packet_init (vlib_main_t * vm)
{
odp_packet_main_t *om;
@@ -333,17 +540,19 @@ odp_packet_init (vlib_main_t * vm)
vlib_thread_registration_t *tr;
vlib_physmem_main_t *vpm = &vm->physmem_main;
uword *p;
- odp_platform_init_t platform_params;
odp_pool_param_t params;
odp_pool_capability_t capa;
odp_shm_t shm;
odp_instance_t instance;
- memset (&platform_params, 0, sizeof (platform_params));
- platform_params.memory = 100;
+ if (platform_params.memory == 0)
+ {
+ platform_params.memory = 50 + num_pkts_in_pool * 4 / 1024;
+ clib_warning ("Warning: Platform 'memory' parameter not configured!");
+ }
if (odp_init_global (&instance, NULL, &platform_params))
- clib_warning ("Error:ODP global init failed");
+ clib_warning ("Error: ODP global init failed");
if (odp_init_local (instance, ODP_THREAD_CONTROL) != 0)
{
@@ -379,7 +588,7 @@ odp_packet_init (vlib_main_t * vm)
params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
params.type = ODP_POOL_PACKET;
- params.pkt.num = SHM_PKT_POOL_NB_PKTS;
+ params.pkt.num = num_pkts_in_pool;
params.pkt.uarea_size = sizeof (vlib_buffer_t) - VLIB_BUFFER_PRE_DATA_SIZE;
om->pool = odp_pool_create (SHM_PKT_POOL_NAME, &params);
@@ -405,9 +614,6 @@ odp_packet_init (vlib_main_t * vm)
vpm->virtual.end = params.pool_end;
vpm->virtual.size = params.pool_size;
- /* Initialization complete and worker threads do not need to sync */
- tm->worker_thread_release = 1;
-
return 0;
}
diff --git a/src/plugins/odp/odp_packet.h b/src/plugins/odp/odp_packet.h
index 81b4a8e..a80ab32 100755
--- a/src/plugins/odp/odp_packet.h
+++ b/src/plugins/odp/odp_packet.h
@@ -14,12 +14,29 @@
#define APPL_MODE_PKT_BURST 0
#define APPL_MODE_PKT_QUEUE 1
#define APPL_MODE_PKT_SCHED 2
+#define APPL_MODE_PKT_TM 3
#define MAX_WORKERS 32
#define MAX_QUEUES (MAX_WORKERS + 1)
typedef struct
{
+ u16 num_tx_queues;
+ u16 num_rx_queues;
+ u8 tx_mode;
+ u8 rx_mode;
+} odp_if_mode_t;
+
+typedef struct
+{
+ u8 *name;
+ odp_if_mode_t mode;
+ u8 hw_addr[6];
+ u8 set_hw_addr;
+} odp_if_config_t;
+
+typedef struct
+{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
u8 *host_if_name;
volatile u32 *lockp;
@@ -31,13 +48,11 @@ typedef struct
u32 next_tx_frame;
u32 per_interface_next_index;
u8 is_admin_up;
- u32 mode;
odp_queue_t rxq[MAX_QUEUES];
odp_pktin_queue_t inq[MAX_QUEUES];
odp_pktout_queue_t outq[MAX_QUEUES];
odp_queue_t txq[MAX_QUEUES];
- u16 rx_queues;
- u16 tx_queues;
+ odp_if_mode_t m;
} odp_packet_if_t;
typedef struct
@@ -58,10 +73,14 @@ typedef struct
extern odp_packet_main_t *odp_packet_main;
extern vnet_device_class_t odp_packet_device_class;
extern vlib_node_registration_t odp_packet_input_node;
+extern u32 rx_sched_wait;
+extern u32 tx_burst_size;
+extern u32 num_pkts_in_pool;
+extern odp_if_mode_t def_if_mode;
u32 odp_packet_create_if (vlib_main_t * vm, u8 * host_if_name,
- u8 * hw_addr_set, u32 * sw_if_index, u32 mode,
- u32 rx_queues);
+ u8 * hw_addr_set, u32 * sw_if_index,
+ odp_if_mode_t * mode);
u32 odp_packet_delete_if (vlib_main_t * vm, u8 * host_if_name);
u32 drop_err_pkts (odp_packet_t pkt_tbl[], u32 len);
diff --git a/src/vpp/conf/startup.conf b/src/vpp/conf/startup.conf
index f671439..6438f77 100644
--- a/src/vpp/conf/startup.conf
+++ b/src/vpp/conf/startup.conf
@@ -98,6 +98,42 @@ cpu {
# socket-mem 2048,2048
# }
+# odp {
+ # platform-params {
+ # memory 100
+ # }
+
+ ## Number of packets in allocated pool
+ # num-pkts-in-pool 10240
+
+ ## Delay in microseconds between calls to odp_schedule_multi
+ # rx-sched-wait 0
+
+ ## Limit of output burst size. May increase performance.
+ # tx-burst-size 32
+
+ ## Default configuration for all ODP devices.
+ ## rx-mode can be set to burst, queue or sched
+ ## tx-mode can be burst, queue or tm (traffic manager)
+ ## num-rx-queues can be set to more than 1 to enable RSS
+ ## num-tx-queues can be 'max' (separate queue for each thread) or 1
+ # default {
+ # rx-mode burst
+ # tx-mode burst
+ # num-rx-queues 1
+ # num-tx-queues max
+ # }
+
+ ## Defined ODP devices are created automatically at startup.
+ ## dev (DPDK port number) [{ options }]
+ ## hw-addr - if not specified, MAC will be read from hardware
+ # dev 0 {
+ # rx-mode queue
+ # num-rx-queues 2
+ # hw-addr 3c:fd:fe:a4:37:99
+ # }
+# }
+
# Adjusting the plugin path depending on where the VPP plugins are:
#plugins
#{