examples/ip_pipeline: support KNI

1. add KNI support to the IP Pipeline sample Application
2. some bug fix
3. update doc
4. add config file with two KNI interfaces connected using
   a Linux kernel bridge

Signed-off-by: WeiJie Zhuang <zhuangwj@gmail.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
WeiJie Zhuang 2016-06-21 18:55:53 +08:00 committed by Thomas Monjalon
parent 9fc37d1c07
commit 81d084dd2a
9 changed files with 769 additions and 41 deletions

View File

@ -1,5 +1,5 @@
.. BSD LICENSE .. BSD LICENSE
Copyright(c) 2015 Intel Corporation. All rights reserved. Copyright(c) 2015-2016 Intel Corporation. All rights reserved.
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -351,33 +351,35 @@ Application resources present in the configuration file
.. table:: Application resource names in the configuration file .. table:: Application resource names in the configuration file
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Resource type | Format | Examples | | Resource type | Format | Examples |
+==========================+=============================+=================================================+ +============================+=============================+=================================================+
| Pipeline | ``PIPELINE<ID>`` | ``PIPELINE0``, ``PIPELINE1`` | | Pipeline | ``PIPELINE<ID>`` | ``PIPELINE0``, ``PIPELINE1`` |
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Mempool | ``MEMPOOL<ID>`` | ``MEMPOOL0``, ``MEMPOOL1`` | | Mempool | ``MEMPOOL<ID>`` | ``MEMPOOL0``, ``MEMPOOL1`` |
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Link (network interface) | ``LINK<ID>`` | ``LINK0``, ``LINK1`` | | Link (network interface) | ``LINK<ID>`` | ``LINK0``, ``LINK1`` |
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Link RX queue | ``RXQ<LINK_ID>.<QUEUE_ID>`` | ``RXQ0.0``, ``RXQ1.5`` | | Link RX queue | ``RXQ<LINK_ID>.<QUEUE_ID>`` | ``RXQ0.0``, ``RXQ1.5`` |
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Link TX queue | ``TXQ<LINK_ID>.<QUEUE_ID>`` | ``TXQ0.0``, ``TXQ1.5`` | | Link TX queue | ``TXQ<LINK_ID>.<QUEUE_ID>`` | ``TXQ0.0``, ``TXQ1.5`` |
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Software queue | ``SWQ<ID>`` | ``SWQ0``, ``SWQ1`` | | Software queue | ``SWQ<ID>`` | ``SWQ0``, ``SWQ1`` |
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Traffic Manager | ``TM<LINK_ID>`` | ``TM0``, ``TM1`` | | Traffic Manager | ``TM<LINK_ID>`` | ``TM0``, ``TM1`` |
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Source | ``SOURCE<ID>`` | ``SOURCE0``, ``SOURCE1`` | | KNI (kernel NIC interface) | ``KNI<LINK_ID>`` | ``KNI0``, ``KNI1`` |
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Sink | ``SINK<ID>`` | ``SINK0``, ``SINK1`` | | Source | ``SOURCE<ID>`` | ``SOURCE0``, ``SOURCE1`` |
+--------------------------+-----------------------------+-------------------------------------------------+ +----------------------------+-----------------------------+-------------------------------------------------+
| Message queue | ``MSGQ<ID>`` | ``MSGQ0``, ``MSGQ1``, | | Sink | ``SINK<ID>`` | ``SINK0``, ``SINK1`` |
| | ``MSGQ-REQ-PIPELINE<ID>`` | ``MSGQ-REQ-PIPELINE2``, ``MSGQ-RSP-PIPELINE2,`` | +----------------------------+-----------------------------+-------------------------------------------------+
| | ``MSGQ-RSP-PIPELINE<ID>`` | ``MSGQ-REQ-CORE-s0c1``, ``MSGQ-RSP-CORE-s0c1`` | | Message queue | ``MSGQ<ID>`` | ``MSGQ0``, ``MSGQ1``, |
| | ``MSGQ-REQ-CORE-<CORE_ID>`` | | | | ``MSGQ-REQ-PIPELINE<ID>`` | ``MSGQ-REQ-PIPELINE2``, ``MSGQ-RSP-PIPELINE2,`` |
| | ``MSGQ-RSP-CORE-<CORE_ID>`` | | | | ``MSGQ-RSP-PIPELINE<ID>`` | ``MSGQ-REQ-CORE-s0c1``, ``MSGQ-RSP-CORE-s0c1`` |
+--------------------------+-----------------------------+-------------------------------------------------+ | | ``MSGQ-REQ-CORE-<CORE_ID>`` | |
| | ``MSGQ-RSP-CORE-<CORE_ID>`` | |
+----------------------------+-----------------------------+-------------------------------------------------+
``LINK`` instances are created implicitly based on the ``PORT_MASK`` application startup argument. ``LINK`` instances are created implicitly based on the ``PORT_MASK`` application startup argument.
``LINK0`` is the first port enabled in the ``PORT_MASK``, port 1 is the next one, etc. ``LINK0`` is the first port enabled in the ``PORT_MASK``, port 1 is the next one, etc.
@ -386,7 +388,7 @@ For example, if bit 5 is the first bit set in the bitmask, then ``LINK0`` is hav
This mechanism creates a contiguous LINK ID space and isolates the configuration file against changes in the board This mechanism creates a contiguous LINK ID space and isolates the configuration file against changes in the board
PCIe slots where NICs are plugged in. PCIe slots where NICs are plugged in.
``RXQ``, ``TXQ`` and ``TM`` instances have the LINK ID as part of their name. ``RXQ``, ``TXQ``, ``TM`` and ``KNI`` instances have the LINK ID as part of their name.
For example, ``RXQ2.1``, ``TXQ2.1`` and ``TM2`` are all associated with ``LINK2``. For example, ``RXQ2.1``, ``TXQ2.1`` and ``TM2`` are all associated with ``LINK2``.
@ -707,6 +709,58 @@ TM section
+---------------+---------------------------------------------+----------+----------+---------------+ +---------------+---------------------------------------------+----------+----------+---------------+
KNI section
~~~~~~~~~~~
.. _table_ip_pipelines_kni_section:
.. tabularcolumns:: |p{2.5cm}|p{7cm}|p{1.5cm}|p{1.5cm}|p{1.5cm}|
.. table:: Configuration file KNI section
+---------------+----------------------------------------------+----------+------------------+---------------+
| Section | Description | Optional | Type | Default value |
+===============+==============================================+==========+==================+===============+
| core | CPU core to run the KNI kernel thread. | YES | See "CPU Core | Not set |
| | When core config is set, the KNI kernel | | notation" | |
| | thread will be bound to the particular core. | | | |
| | When core config is not set, the KNI kernel | | | |
| | thread will be scheduled by the OS. | | | |
+---------------+----------------------------------------------+----------+------------------+---------------+
| mempool | Mempool to use for buffer allocation for | YES | uint32_t | MEMPOOL0 |
| | current KNI port. The mempool ID has | | | |
| | to be associated with a valid instance | | | |
| | defined in the mempool entry of the global | | | |
| | section. | | | |
+---------------+----------------------------------------------+----------+------------------+---------------+
| burst_read | Read burst size (number of packets) | YES | uint32_t | 32 |
| | | | power of 2 | |
| | | | 0 < burst < size | |
+---------------+----------------------------------------------+----------+------------------+---------------+
| burst_write | Write burst size (number of packets) | YES | uint32_t | 32 |
| | | | power of 2 | |
| | | | 0 < burst < size | |
+---------------+----------------------------------------------+----------+------------------+---------------+
| dropless | When dropless is set to NO, packets can be | YES | YES/NO | NO |
| | dropped if not enough free slots are | | | |
| | currently available in the queue, so the | | | |
| | write operation to the queue is non- | | | |
| | blocking. | | | |
| | When dropless is set to YES, packets cannot | | | |
| | be dropped if not enough free slots are | | | |
| | currently available in the queue, so the | | | |
| | write operation to the queue is blocking, as | | | |
| | the write operation is retried until enough | | | |
| | free slots become available and all the | | | |
| | packets are successfully written to the | | | |
| | queue. | | | |
+---------------+----------------------------------------------+----------+------------------+---------------+
| n_retries | Number of retries. Valid only when dropless | YES | uint64_t | 0 |
| | is set to YES. When set to 0, it indicates | | | |
| | unlimited number of retries. | | | |
+---------------+----------------------------------------------+----------+------------------+---------------+
SOURCE section SOURCE section
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~

View File

@ -44,6 +44,9 @@
#include <cmdline_parse.h> #include <cmdline_parse.h>
#include <rte_ethdev.h> #include <rte_ethdev.h>
#ifdef RTE_LIBRTE_KNI
#include <rte_kni.h>
#endif
#include "cpu_core_map.h" #include "cpu_core_map.h"
#include "pipeline.h" #include "pipeline.h"
@ -132,6 +135,22 @@ struct app_pktq_swq_params {
uint32_t mempool_indirect_id; uint32_t mempool_indirect_id;
}; };
struct app_pktq_kni_params {
char *name;
uint32_t parsed;
uint32_t socket_id;
uint32_t core_id;
uint32_t hyper_th_id;
uint32_t force_bind;
uint32_t mempool_id; /* Position in the app->mempool_params */
uint32_t burst_read;
uint32_t burst_write;
uint32_t dropless;
uint64_t n_retries;
};
#ifndef APP_FILE_NAME_SIZE #ifndef APP_FILE_NAME_SIZE
#define APP_FILE_NAME_SIZE 256 #define APP_FILE_NAME_SIZE 256
#endif #endif
@ -185,6 +204,7 @@ enum app_pktq_in_type {
APP_PKTQ_IN_HWQ, APP_PKTQ_IN_HWQ,
APP_PKTQ_IN_SWQ, APP_PKTQ_IN_SWQ,
APP_PKTQ_IN_TM, APP_PKTQ_IN_TM,
APP_PKTQ_IN_KNI,
APP_PKTQ_IN_SOURCE, APP_PKTQ_IN_SOURCE,
}; };
@ -197,6 +217,7 @@ enum app_pktq_out_type {
APP_PKTQ_OUT_HWQ, APP_PKTQ_OUT_HWQ,
APP_PKTQ_OUT_SWQ, APP_PKTQ_OUT_SWQ,
APP_PKTQ_OUT_TM, APP_PKTQ_OUT_TM,
APP_PKTQ_OUT_KNI,
APP_PKTQ_OUT_SINK, APP_PKTQ_OUT_SINK,
}; };
@ -420,6 +441,8 @@ struct app_eal_params {
#define APP_MAX_PKTQ_TM APP_MAX_LINKS #define APP_MAX_PKTQ_TM APP_MAX_LINKS
#define APP_MAX_PKTQ_KNI APP_MAX_LINKS
#ifndef APP_MAX_PKTQ_SOURCE #ifndef APP_MAX_PKTQ_SOURCE
#define APP_MAX_PKTQ_SOURCE 64 #define APP_MAX_PKTQ_SOURCE 64
#endif #endif
@ -471,6 +494,7 @@ struct app_params {
struct app_pktq_hwq_out_params hwq_out_params[APP_MAX_HWQ_OUT]; struct app_pktq_hwq_out_params hwq_out_params[APP_MAX_HWQ_OUT];
struct app_pktq_swq_params swq_params[APP_MAX_PKTQ_SWQ]; struct app_pktq_swq_params swq_params[APP_MAX_PKTQ_SWQ];
struct app_pktq_tm_params tm_params[APP_MAX_PKTQ_TM]; struct app_pktq_tm_params tm_params[APP_MAX_PKTQ_TM];
struct app_pktq_kni_params kni_params[APP_MAX_PKTQ_KNI];
struct app_pktq_source_params source_params[APP_MAX_PKTQ_SOURCE]; struct app_pktq_source_params source_params[APP_MAX_PKTQ_SOURCE];
struct app_pktq_sink_params sink_params[APP_MAX_PKTQ_SINK]; struct app_pktq_sink_params sink_params[APP_MAX_PKTQ_SINK];
struct app_msgq_params msgq_params[APP_MAX_MSGQ]; struct app_msgq_params msgq_params[APP_MAX_MSGQ];
@ -482,6 +506,7 @@ struct app_params {
uint32_t n_pktq_hwq_out; uint32_t n_pktq_hwq_out;
uint32_t n_pktq_swq; uint32_t n_pktq_swq;
uint32_t n_pktq_tm; uint32_t n_pktq_tm;
uint32_t n_pktq_kni;
uint32_t n_pktq_source; uint32_t n_pktq_source;
uint32_t n_pktq_sink; uint32_t n_pktq_sink;
uint32_t n_msgq; uint32_t n_msgq;
@ -495,6 +520,9 @@ struct app_params {
struct app_link_data link_data[APP_MAX_LINKS]; struct app_link_data link_data[APP_MAX_LINKS];
struct rte_ring *swq[APP_MAX_PKTQ_SWQ]; struct rte_ring *swq[APP_MAX_PKTQ_SWQ];
struct rte_sched_port *tm[APP_MAX_PKTQ_TM]; struct rte_sched_port *tm[APP_MAX_PKTQ_TM];
#ifdef RTE_LIBRTE_KNI
struct rte_kni *kni[APP_MAX_PKTQ_KNI];
#endif /* RTE_LIBRTE_KNI */
struct rte_ring *msgq[APP_MAX_MSGQ]; struct rte_ring *msgq[APP_MAX_MSGQ];
struct pipeline_type pipeline_type[APP_MAX_PIPELINE_TYPES]; struct pipeline_type pipeline_type[APP_MAX_PIPELINE_TYPES];
struct app_pipeline_data pipeline_data[APP_MAX_PIPELINES]; struct app_pipeline_data pipeline_data[APP_MAX_PIPELINES];
@ -667,11 +695,11 @@ app_swq_get_reader(struct app_params *app,
struct app_pktq_swq_params *swq, struct app_pktq_swq_params *swq,
uint32_t *pktq_in_id) uint32_t *pktq_in_id)
{ {
struct app_pipeline_params *reader; struct app_pipeline_params *reader = NULL;
uint32_t pos = swq - app->swq_params; uint32_t pos = swq - app->swq_params;
uint32_t n_pipelines = RTE_MIN(app->n_pipelines, uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
RTE_DIM(app->pipeline_params)); RTE_DIM(app->pipeline_params));
uint32_t n_readers = 0, id, i; uint32_t n_readers = 0, id = 0, i;
for (i = 0; i < n_pipelines; i++) { for (i = 0; i < n_pipelines; i++) {
struct app_pipeline_params *p = &app->pipeline_params[i]; struct app_pipeline_params *p = &app->pipeline_params[i];
@ -727,11 +755,11 @@ app_tm_get_reader(struct app_params *app,
struct app_pktq_tm_params *tm, struct app_pktq_tm_params *tm,
uint32_t *pktq_in_id) uint32_t *pktq_in_id)
{ {
struct app_pipeline_params *reader; struct app_pipeline_params *reader = NULL;
uint32_t pos = tm - app->tm_params; uint32_t pos = tm - app->tm_params;
uint32_t n_pipelines = RTE_MIN(app->n_pipelines, uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
RTE_DIM(app->pipeline_params)); RTE_DIM(app->pipeline_params));
uint32_t n_readers = 0, id, i; uint32_t n_readers = 0, id = 0, i;
for (i = 0; i < n_pipelines; i++) { for (i = 0; i < n_pipelines; i++) {
struct app_pipeline_params *p = &app->pipeline_params[i]; struct app_pipeline_params *p = &app->pipeline_params[i];
@ -757,6 +785,66 @@ app_tm_get_reader(struct app_params *app,
return reader; return reader;
} }
static inline uint32_t
app_kni_get_readers(struct app_params *app, struct app_pktq_kni_params *kni)
{
uint32_t pos = kni - app->kni_params;
uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
RTE_DIM(app->pipeline_params));
uint32_t n_readers = 0, i;
for (i = 0; i < n_pipelines; i++) {
struct app_pipeline_params *p = &app->pipeline_params[i];
uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
uint32_t j;
for (j = 0; j < n_pktq_in; j++) {
struct app_pktq_in_params *pktq = &p->pktq_in[j];
if ((pktq->type == APP_PKTQ_IN_KNI) &&
(pktq->id == pos))
n_readers++;
}
}
return n_readers;
}
static inline struct app_pipeline_params *
app_kni_get_reader(struct app_params *app,
struct app_pktq_kni_params *kni,
uint32_t *pktq_in_id)
{
struct app_pipeline_params *reader = NULL;
uint32_t pos = kni - app->kni_params;
uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
RTE_DIM(app->pipeline_params));
uint32_t n_readers = 0, id = 0, i;
for (i = 0; i < n_pipelines; i++) {
struct app_pipeline_params *p = &app->pipeline_params[i];
uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in));
uint32_t j;
for (j = 0; j < n_pktq_in; j++) {
struct app_pktq_in_params *pktq = &p->pktq_in[j];
if ((pktq->type == APP_PKTQ_IN_KNI) &&
(pktq->id == pos)) {
n_readers++;
reader = p;
id = j;
}
}
}
if (n_readers != 1)
return NULL;
*pktq_in_id = id;
return reader;
}
static inline uint32_t static inline uint32_t
app_source_get_readers(struct app_params *app, app_source_get_readers(struct app_params *app,
struct app_pktq_source_params *source) struct app_pktq_source_params *source)
@ -861,11 +949,11 @@ app_swq_get_writer(struct app_params *app,
struct app_pktq_swq_params *swq, struct app_pktq_swq_params *swq,
uint32_t *pktq_out_id) uint32_t *pktq_out_id)
{ {
struct app_pipeline_params *writer; struct app_pipeline_params *writer = NULL;
uint32_t pos = swq - app->swq_params; uint32_t pos = swq - app->swq_params;
uint32_t n_pipelines = RTE_MIN(app->n_pipelines, uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
RTE_DIM(app->pipeline_params)); RTE_DIM(app->pipeline_params));
uint32_t n_writers = 0, id, i; uint32_t n_writers = 0, id = 0, i;
for (i = 0; i < n_pipelines; i++) { for (i = 0; i < n_pipelines; i++) {
struct app_pipeline_params *p = &app->pipeline_params[i]; struct app_pipeline_params *p = &app->pipeline_params[i];
@ -923,11 +1011,11 @@ app_tm_get_writer(struct app_params *app,
struct app_pktq_tm_params *tm, struct app_pktq_tm_params *tm,
uint32_t *pktq_out_id) uint32_t *pktq_out_id)
{ {
struct app_pipeline_params *writer; struct app_pipeline_params *writer = NULL;
uint32_t pos = tm - app->tm_params; uint32_t pos = tm - app->tm_params;
uint32_t n_pipelines = RTE_MIN(app->n_pipelines, uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
RTE_DIM(app->pipeline_params)); RTE_DIM(app->pipeline_params));
uint32_t n_writers = 0, id, i; uint32_t n_writers = 0, id = 0, i;
for (i = 0; i < n_pipelines; i++) { for (i = 0; i < n_pipelines; i++) {
struct app_pipeline_params *p = &app->pipeline_params[i]; struct app_pipeline_params *p = &app->pipeline_params[i];
@ -939,10 +1027,73 @@ app_tm_get_writer(struct app_params *app,
struct app_pktq_out_params *pktq = &p->pktq_out[j]; struct app_pktq_out_params *pktq = &p->pktq_out[j];
if ((pktq->type == APP_PKTQ_OUT_TM) && if ((pktq->type == APP_PKTQ_OUT_TM) &&
(pktq->id == pos)) (pktq->id == pos)) {
n_writers++; n_writers++;
writer = p; writer = p;
id = j; id = j;
}
}
}
if (n_writers != 1)
return NULL;
*pktq_out_id = id;
return writer;
}
static inline uint32_t
app_kni_get_writers(struct app_params *app, struct app_pktq_kni_params *kni)
{
uint32_t pos = kni - app->kni_params;
uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
RTE_DIM(app->pipeline_params));
uint32_t n_writers = 0, i;
for (i = 0; i < n_pipelines; i++) {
struct app_pipeline_params *p = &app->pipeline_params[i];
uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
RTE_DIM(p->pktq_out));
uint32_t j;
for (j = 0; j < n_pktq_out; j++) {
struct app_pktq_out_params *pktq = &p->pktq_out[j];
if ((pktq->type == APP_PKTQ_OUT_KNI) &&
(pktq->id == pos))
n_writers++;
}
}
return n_writers;
}
static inline struct app_pipeline_params *
app_kni_get_writer(struct app_params *app,
struct app_pktq_kni_params *kni,
uint32_t *pktq_out_id)
{
struct app_pipeline_params *writer = NULL;
uint32_t pos = kni - app->kni_params;
uint32_t n_pipelines = RTE_MIN(app->n_pipelines,
RTE_DIM(app->pipeline_params));
uint32_t n_writers = 0, id = 0, i;
for (i = 0; i < n_pipelines; i++) {
struct app_pipeline_params *p = &app->pipeline_params[i];
uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out,
RTE_DIM(p->pktq_out));
uint32_t j;
for (j = 0; j < n_pktq_out; j++) {
struct app_pktq_out_params *pktq = &p->pktq_out[j];
if ((pktq->type == APP_PKTQ_OUT_KNI) &&
(pktq->id == pos)) {
n_writers++;
writer = p;
id = j;
}
} }
} }
@ -1051,6 +1202,22 @@ app_get_link_for_tm(struct app_params *app, struct app_pktq_tm_params *p_tm)
return &app->link_params[link_param_idx]; return &app->link_params[link_param_idx];
} }
static inline struct app_link_params *
app_get_link_for_kni(struct app_params *app, struct app_pktq_kni_params *p_kni)
{
char link_name[APP_PARAM_NAME_SIZE];
uint32_t link_id;
ssize_t link_param_idx;
sscanf(p_kni->name, "KNI%" PRIu32, &link_id);
sprintf(link_name, "LINK%" PRIu32, link_id);
link_param_idx = APP_PARAM_FIND(app->link_params, link_name);
APP_CHECK((link_param_idx >= 0),
"Cannot find %s for %s", link_name, p_kni->name);
return &app->link_params[link_param_idx];
}
void app_pipeline_params_get(struct app_params *app, void app_pipeline_params_get(struct app_params *app,
struct app_pipeline_params *p_in, struct app_pipeline_params *p_in,
struct pipeline_params *p_out); struct pipeline_params *p_out);

View File

@ -0,0 +1,67 @@
; BSD LICENSE
;
; Copyright(c) 2016 Intel Corporation.
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
;
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in
; the documentation and/or other materials provided with the
; distribution.
; * Neither the name of Intel Corporation nor the names of its
; contributors may be used to endorse or promote products derived
; from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
; ______________ ______________________
; | | KNI0 | |
; RXQ0.0 --->| |------->|--+ |
; | | KNI1 | | br0 |
; TXQ1.0 <---| |<-------|<-+ |
; | Pass-through | | Linux Kernel |
; | (P1) | | Network Stack |
; | | KNI1 | |
; RXQ1.0 --->| |------->|--+ |
; | | KNI0 | | br0 |
; TXQ0.0 <---| |<-------|<-+ |
; |______________| |______________________|
;
; Insert Linux kernel KNI module:
; [Linux]$ insmod rte_kni.ko
;
; Configure Linux kernel bridge between KNI0 and KNI1 interfaces:
; [Linux]$ ifconfig KNI0 up
; [Linux]$ ifconfig KNI1 up
; [Linux]$ brctl addbr "br0"
; [Linux]$ brctl addif br0 KNI0
; [Linux]$ brctl addif br0 KNI1
; [Linux]$ ifconfig br0 up
[EAL]
log_level = 0
[PIPELINE0]
type = MASTER
core = 0
[PIPELINE1]
type = PASS-THROUGH
core = 1
pktq_in = RXQ0.0 KNI1 RXQ1.0 KNI0
pktq_out = KNI0 TXQ1.0 KNI1 TXQ0.0

View File

@ -1,7 +1,7 @@
/*- /*-
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -315,6 +315,29 @@ check_tms(struct app_params *app)
} }
} }
static void
check_knis(struct app_params *app) {
uint32_t i;
for (i = 0; i < app->n_pktq_kni; i++) {
struct app_pktq_kni_params *p = &app->kni_params[i];
uint32_t n_readers = app_kni_get_readers(app, p);
uint32_t n_writers = app_kni_get_writers(app, p);
APP_CHECK((n_readers != 0),
"%s has no reader\n", p->name);
APP_CHECK((n_readers == 1),
"%s has more than one reader\n", p->name);
APP_CHECK((n_writers != 0),
"%s has no writer\n", p->name);
APP_CHECK((n_writers == 1),
"%s has more than one writer\n", p->name);
}
}
static void static void
check_sources(struct app_params *app) check_sources(struct app_params *app)
{ {
@ -453,6 +476,7 @@ app_config_check(struct app_params *app)
check_txqs(app); check_txqs(app);
check_swqs(app); check_swqs(app);
check_tms(app); check_tms(app);
check_knis(app);
check_sources(app); check_sources(app);
check_sinks(app); check_sinks(app);
check_msgqs(app); check_msgqs(app);

View File

@ -189,6 +189,20 @@ struct app_pktq_tm_params default_tm_params = {
.burst_write = 32, .burst_write = 32,
}; };
struct app_pktq_kni_params default_kni_params = {
.parsed = 0,
.socket_id = 0,
.core_id = 0,
.hyper_th_id = 0,
.force_bind = 0,
.mempool_id = 0,
.burst_read = 32,
.burst_write = 32,
.dropless = 0,
.n_retries = 0,
};
struct app_pktq_source_params default_source_params = { struct app_pktq_source_params default_source_params = {
.parsed = 0, .parsed = 0,
.mempool_id = 0, .mempool_id = 0,
@ -300,6 +314,18 @@ app_print_usage(char *prgname)
link_param_pos; \ link_param_pos; \
}) })
#define APP_PARAM_ADD_LINK_FOR_KNI(app, kni_name) \
({ \
char link_name[APP_PARAM_NAME_SIZE]; \
ssize_t link_param_pos; \
uint32_t link_id; \
\
sscanf((kni_name), "KNI%" SCNu32, &link_id); \
sprintf(link_name, "LINK%" PRIu32, link_id); \
link_param_pos = APP_PARAM_ADD((app)->link_params, link_name); \
link_param_pos; \
})
#define PARSE_CHECK_DUPLICATE_SECTION(obj) \ #define PARSE_CHECK_DUPLICATE_SECTION(obj) \
do { \ do { \
APP_CHECK(((obj)->parsed == 0), \ APP_CHECK(((obj)->parsed == 0), \
@ -826,6 +852,10 @@ parse_pipeline_pktq_in(struct app_params *app,
type = APP_PKTQ_IN_TM; type = APP_PKTQ_IN_TM;
id = APP_PARAM_ADD(app->tm_params, name); id = APP_PARAM_ADD(app->tm_params, name);
APP_PARAM_ADD_LINK_FOR_TM(app, name); APP_PARAM_ADD_LINK_FOR_TM(app, name);
} else if (validate_name(name, "KNI", 1) == 0) {
type = APP_PKTQ_IN_KNI;
id = APP_PARAM_ADD(app->kni_params, name);
APP_PARAM_ADD_LINK_FOR_KNI(app, name);
} else if (validate_name(name, "SOURCE", 1) == 0) { } else if (validate_name(name, "SOURCE", 1) == 0) {
type = APP_PKTQ_IN_SOURCE; type = APP_PKTQ_IN_SOURCE;
id = APP_PARAM_ADD(app->source_params, name); id = APP_PARAM_ADD(app->source_params, name);
@ -871,6 +901,10 @@ parse_pipeline_pktq_out(struct app_params *app,
type = APP_PKTQ_OUT_TM; type = APP_PKTQ_OUT_TM;
id = APP_PARAM_ADD(app->tm_params, name); id = APP_PARAM_ADD(app->tm_params, name);
APP_PARAM_ADD_LINK_FOR_TM(app, name); APP_PARAM_ADD_LINK_FOR_TM(app, name);
} else if (validate_name(name, "KNI", 1) == 0) {
type = APP_PKTQ_OUT_KNI;
id = APP_PARAM_ADD(app->kni_params, name);
APP_PARAM_ADD_LINK_FOR_KNI(app, name);
} else if (validate_name(name, "SINK", 1) == 0) { } else if (validate_name(name, "SINK", 1) == 0) {
type = APP_PKTQ_OUT_SINK; type = APP_PKTQ_OUT_SINK;
id = APP_PARAM_ADD(app->sink_params, name); id = APP_PARAM_ADD(app->sink_params, name);
@ -1581,6 +1615,15 @@ parse_txq(struct app_params *app,
continue; continue;
} }
if (strcmp(ent->name, "n_retries") == 0) {
int status = parser_read_uint64(&param->n_retries,
ent->value);
PARSE_ERROR((status == 0), section_name,
ent->name);
continue;
}
/* unrecognized */ /* unrecognized */
PARSE_ERROR_INVALID(0, section_name, ent->name); PARSE_ERROR_INVALID(0, section_name, ent->name);
} }
@ -1816,7 +1859,7 @@ parse_tm(struct app_params *app,
param = &app->tm_params[param_idx]; param = &app->tm_params[param_idx];
PARSE_CHECK_DUPLICATE_SECTION(param); PARSE_CHECK_DUPLICATE_SECTION(param);
APP_PARAM_ADD_LINK_FOR_TXQ(app, section_name); APP_PARAM_ADD_LINK_FOR_TM(app, section_name);
for (i = 0; i < n_entries; i++) { for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i]; struct rte_cfgfile_entry *ent = &entries[i];
@ -1852,6 +1895,102 @@ parse_tm(struct app_params *app,
free(entries); free(entries);
} }
static void
parse_kni(struct app_params *app,
const char *section_name,
struct rte_cfgfile *cfg)
{
struct app_pktq_kni_params *param;
struct rte_cfgfile_entry *entries;
int n_entries, i;
ssize_t param_idx;
n_entries = rte_cfgfile_section_num_entries(cfg, section_name);
PARSE_ERROR_SECTION_NO_ENTRIES((n_entries > 0), section_name);
entries = malloc(n_entries * sizeof(struct rte_cfgfile_entry));
PARSE_ERROR_MALLOC(entries != NULL);
rte_cfgfile_section_entries(cfg, section_name, entries, n_entries);
param_idx = APP_PARAM_ADD(app->kni_params, section_name);
param = &app->kni_params[param_idx];
PARSE_CHECK_DUPLICATE_SECTION(param);
APP_PARAM_ADD_LINK_FOR_KNI(app, section_name);
for (i = 0; i < n_entries; i++) {
struct rte_cfgfile_entry *ent = &entries[i];
if (strcmp(ent->name, "core") == 0) {
int status = parse_pipeline_core(
&param->socket_id,
&param->core_id,
&param->hyper_th_id,
ent->value);
PARSE_ERROR((status == 0), section_name,
ent->name);
param->force_bind = 1;
continue;
}
if (strcmp(ent->name, "mempool") == 0) {
int status = validate_name(ent->value,
"MEMPOOL", 1);
ssize_t idx;
PARSE_ERROR((status == 0), section_name,
ent->name);
idx = APP_PARAM_ADD(app->mempool_params, ent->value);
param->mempool_id = idx;
continue;
}
if (strcmp(ent->name, "burst_read") == 0) {
int status = parser_read_uint32(&param->burst_read,
ent->value);
PARSE_ERROR((status == 0), section_name,
ent->name);
continue;
}
if (strcmp(ent->name, "burst_write") == 0) {
int status = parser_read_uint32(&param->burst_write,
ent->value);
PARSE_ERROR((status == 0), section_name,
ent->name);
continue;
}
if (strcmp(ent->name, "dropless") == 0) {
int status = parser_read_arg_bool(ent->value);
PARSE_ERROR((status != -EINVAL), section_name,
ent->name);
param->dropless = status;
continue;
}
if (strcmp(ent->name, "n_retries") == 0) {
int status = parser_read_uint64(&param->n_retries,
ent->value);
PARSE_ERROR((status == 0), section_name,
ent->name);
continue;
}
/* unrecognized */
PARSE_ERROR_INVALID(0, section_name, ent->name);
}
free(entries);
}
static void static void
parse_source(struct app_params *app, parse_source(struct app_params *app,
const char *section_name, const char *section_name,
@ -2147,6 +2286,7 @@ static const struct config_section cfg_file_scheme[] = {
{"TXQ", 2, parse_txq}, {"TXQ", 2, parse_txq},
{"SWQ", 1, parse_swq}, {"SWQ", 1, parse_swq},
{"TM", 1, parse_tm}, {"TM", 1, parse_tm},
{"KNI", 1, parse_kni},
{"SOURCE", 1, parse_source}, {"SOURCE", 1, parse_source},
{"SINK", 1, parse_sink}, {"SINK", 1, parse_sink},
{"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline}, {"MSGQ-REQ-PIPELINE", 1, parse_msgq_req_pipeline},
@ -2285,6 +2425,7 @@ app_config_parse(struct app_params *app, const char *file_name)
APP_PARAM_COUNT(app->hwq_out_params, app->n_pktq_hwq_out); APP_PARAM_COUNT(app->hwq_out_params, app->n_pktq_hwq_out);
APP_PARAM_COUNT(app->swq_params, app->n_pktq_swq); APP_PARAM_COUNT(app->swq_params, app->n_pktq_swq);
APP_PARAM_COUNT(app->tm_params, app->n_pktq_tm); APP_PARAM_COUNT(app->tm_params, app->n_pktq_tm);
APP_PARAM_COUNT(app->kni_params, app->n_pktq_kni);
APP_PARAM_COUNT(app->source_params, app->n_pktq_source); APP_PARAM_COUNT(app->source_params, app->n_pktq_source);
APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink); APP_PARAM_COUNT(app->sink_params, app->n_pktq_sink);
APP_PARAM_COUNT(app->msgq_params, app->n_msgq); APP_PARAM_COUNT(app->msgq_params, app->n_msgq);
@ -2582,6 +2723,7 @@ save_txq_params(struct app_params *app, FILE *f)
fprintf(f, "%s = %s\n", fprintf(f, "%s = %s\n",
"dropless", "dropless",
p->dropless ? "yes" : "no"); p->dropless ? "yes" : "no");
fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
fputc('\n', f); fputc('\n', f);
} }
@ -2646,6 +2788,53 @@ save_tm_params(struct app_params *app, FILE *f)
} }
} }
static void
save_kni_params(struct app_params *app, FILE *f)
{
struct app_pktq_kni_params *p;
size_t i, count;
count = RTE_DIM(app->kni_params);
for (i = 0; i < count; i++) {
p = &app->kni_params[i];
if (!APP_PARAM_VALID(p))
continue;
/* section name */
fprintf(f, "[%s]\n", p->name);
/* core */
if (p->force_bind) {
fprintf(f, "; force_bind = 1\n");
fprintf(f, "core = s%" PRIu32 "c%" PRIu32 "%s\n",
p->socket_id,
p->core_id,
(p->hyper_th_id) ? "h" : "");
} else
fprintf(f, "; force_bind = 0\n");
/* mempool */
fprintf(f, "%s = %s\n", "mempool",
app->mempool_params[p->mempool_id].name);
/* burst_read */
fprintf(f, "%s = %" PRIu32 "\n", "burst_read", p->burst_read);
/* burst_write */
fprintf(f, "%s = %" PRIu32 "\n", "burst_write", p->burst_write);
/* dropless */
fprintf(f, "%s = %s\n",
"dropless",
p->dropless ? "yes" : "no");
/* n_retries */
fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries);
fputc('\n', f);
}
}
static void static void
save_source_params(struct app_params *app, FILE *f) save_source_params(struct app_params *app, FILE *f)
{ {
@ -2753,6 +2942,9 @@ save_pipeline_params(struct app_params *app, FILE *f)
case APP_PKTQ_IN_TM: case APP_PKTQ_IN_TM:
name = app->tm_params[pp->id].name; name = app->tm_params[pp->id].name;
break; break;
case APP_PKTQ_IN_KNI:
name = app->kni_params[pp->id].name;
break;
case APP_PKTQ_IN_SOURCE: case APP_PKTQ_IN_SOURCE:
name = app->source_params[pp->id].name; name = app->source_params[pp->id].name;
break; break;
@ -2787,6 +2979,9 @@ save_pipeline_params(struct app_params *app, FILE *f)
case APP_PKTQ_OUT_TM: case APP_PKTQ_OUT_TM:
name = app->tm_params[pp->id].name; name = app->tm_params[pp->id].name;
break; break;
case APP_PKTQ_OUT_KNI:
name = app->kni_params[pp->id].name;
break;
case APP_PKTQ_OUT_SINK: case APP_PKTQ_OUT_SINK:
name = app->sink_params[pp->id].name; name = app->sink_params[pp->id].name;
break; break;
@ -2872,6 +3067,7 @@ app_config_save(struct app_params *app, const char *file_name)
save_txq_params(app, file); save_txq_params(app, file);
save_swq_params(app, file); save_swq_params(app, file);
save_tm_params(app, file); save_tm_params(app, file);
save_kni_params(app, file);
save_source_params(app, file); save_source_params(app, file);
save_sink_params(app, file); save_sink_params(app, file);
save_msgq_params(app, file); save_msgq_params(app, file);
@ -2921,6 +3117,11 @@ app_config_init(struct app_params *app)
&default_tm_params, &default_tm_params,
sizeof(default_tm_params)); sizeof(default_tm_params));
for (i = 0; i < RTE_DIM(app->kni_params); i++)
memcpy(&app->kni_params[i],
&default_kni_params,
sizeof(default_kni_params));
for (i = 0; i < RTE_DIM(app->source_params); i++) for (i = 0; i < RTE_DIM(app->source_params); i++)
memcpy(&app->source_params[i], memcpy(&app->source_params[i],
&default_source_params, &default_source_params,

View File

@ -1176,6 +1176,111 @@ app_init_tm(struct app_params *app)
} }
} }
#ifdef RTE_LIBRTE_KNI
static int
kni_config_network_interface(uint8_t port_id, uint8_t if_up) {
int ret = 0;
if (port_id >= rte_eth_dev_count())
return -EINVAL;
ret = (if_up) ?
rte_eth_dev_set_link_up(port_id) :
rte_eth_dev_set_link_down(port_id);
return ret;
}
static int
kni_change_mtu(uint8_t port_id, unsigned new_mtu) {
int ret;
if (port_id >= rte_eth_dev_count())
return -EINVAL;
if (new_mtu > ETHER_MAX_LEN)
return -EINVAL;
/* Set new MTU */
ret = rte_eth_dev_set_mtu(port_id, new_mtu);
if (ret < 0)
return ret;
return 0;
}
#endif /* RTE_LIBRTE_KNI */
#ifndef RTE_LIBRTE_KNI
static void
app_init_kni(struct app_params *app) {
if (app->n_pktq_kni == 0)
return;
rte_panic("Can not init KNI without librte_kni support.\n");
}
#else
static void
app_init_kni(struct app_params *app) {
uint32_t i;
if (app->n_pktq_kni == 0)
return;
rte_kni_init(app->n_pktq_kni);
for (i = 0; i < app->n_pktq_kni; i++) {
struct app_pktq_kni_params *p_kni = &app->kni_params[i];
struct app_link_params *p_link;
struct rte_eth_dev_info dev_info;
struct app_mempool_params *mempool_params;
struct rte_mempool *mempool;
struct rte_kni_conf conf;
struct rte_kni_ops ops;
/* LINK */
p_link = app_get_link_for_kni(app, p_kni);
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(p_link->pmd_id, &dev_info);
/* MEMPOOL */
mempool_params = &app->mempool_params[p_kni->mempool_id];
mempool = app->mempool[p_kni->mempool_id];
/* KNI */
memset(&conf, 0, sizeof(conf));
snprintf(conf.name, RTE_KNI_NAMESIZE, "%s", p_kni->name);
conf.force_bind = p_kni->force_bind;
if (conf.force_bind) {
int lcore_id;
lcore_id = cpu_core_map_get_lcore_id(app->core_map,
p_kni->socket_id,
p_kni->core_id,
p_kni->hyper_th_id);
if (lcore_id < 0)
rte_panic("%s invalid CPU core\n", p_kni->name);
conf.core_id = (uint32_t) lcore_id;
}
conf.group_id = p_link->pmd_id;
conf.mbuf_size = mempool_params->buffer_size;
conf.addr = dev_info.pci_dev->addr;
conf.id = dev_info.pci_dev->id;
memset(&ops, 0, sizeof(ops));
ops.port_id = (uint8_t) p_link->pmd_id;
ops.change_mtu = kni_change_mtu;
ops.config_network_if = kni_config_network_interface;
APP_LOG(app, HIGH, "Initializing %s ...", p_kni->name);
app->kni[i] = rte_kni_alloc(mempool, &conf, &ops);
if (!app->kni[i])
rte_panic("%s init error\n", p_kni->name);
}
}
#endif /* RTE_LIBRTE_KNI */
static void static void
app_init_msgq(struct app_params *app) app_init_msgq(struct app_params *app)
{ {
@ -1281,10 +1386,21 @@ void app_pipeline_params_get(struct app_params *app,
break; break;
} }
case APP_PKTQ_IN_TM: case APP_PKTQ_IN_TM:
{
out->type = PIPELINE_PORT_IN_SCHED_READER; out->type = PIPELINE_PORT_IN_SCHED_READER;
out->params.sched.sched = app->tm[in->id]; out->params.sched.sched = app->tm[in->id];
out->burst_size = app->tm_params[in->id].burst_read; out->burst_size = app->tm_params[in->id].burst_read;
break; break;
}
#ifdef RTE_LIBRTE_KNI
case APP_PKTQ_IN_KNI:
{
out->type = PIPELINE_PORT_IN_KNI_READER;
out->params.kni.kni = app->kni[in->id];
out->burst_size = app->kni_params[in->id].burst_read;
break;
}
#endif /* RTE_LIBRTE_KNI */
case APP_PKTQ_IN_SOURCE: case APP_PKTQ_IN_SOURCE:
{ {
uint32_t mempool_id = uint32_t mempool_id =
@ -1409,7 +1525,8 @@ void app_pipeline_params_get(struct app_params *app,
} }
break; break;
} }
case APP_PKTQ_OUT_TM: { case APP_PKTQ_OUT_TM:
{
struct rte_port_sched_writer_params *params = struct rte_port_sched_writer_params *params =
&out->params.sched; &out->params.sched;
@ -1419,6 +1536,34 @@ void app_pipeline_params_get(struct app_params *app,
app->tm_params[in->id].burst_write; app->tm_params[in->id].burst_write;
break; break;
} }
#ifdef RTE_LIBRTE_KNI
case APP_PKTQ_OUT_KNI:
{
struct app_pktq_kni_params *p_kni =
&app->kni_params[in->id];
if (p_kni->dropless == 0) {
struct rte_port_kni_writer_params *params =
&out->params.kni;
out->type = PIPELINE_PORT_OUT_KNI_WRITER;
params->kni = app->kni[in->id];
params->tx_burst_sz =
app->kni_params[in->id].burst_write;
} else {
struct rte_port_kni_writer_nodrop_params
*params = &out->params.kni_nodrop;
out->type = PIPELINE_PORT_OUT_KNI_WRITER_NODROP;
params->kni = app->kni[in->id];
params->tx_burst_sz =
app->kni_params[in->id].burst_write;
params->n_retries =
app->kni_params[in->id].n_retries;
}
break;
}
#endif /* RTE_LIBRTE_KNI */
case APP_PKTQ_OUT_SINK: case APP_PKTQ_OUT_SINK:
{ {
out->type = PIPELINE_PORT_OUT_SINK; out->type = PIPELINE_PORT_OUT_SINK;
@ -1607,6 +1752,7 @@ int app_init(struct app_params *app)
app_init_link(app); app_init_link(app);
app_init_swq(app); app_init_swq(app);
app_init_tm(app); app_init_tm(app);
app_init_kni(app);
app_init_msgq(app); app_init_msgq(app);
app_pipeline_common_cmd_push(app); app_pipeline_common_cmd_push(app);

View File

@ -130,6 +130,33 @@ app_pipeline_track_pktq_out_to_link(struct app_params *app,
break; break;
} }
case APP_PKTQ_OUT_KNI:
{
struct pipeline_params pp;
struct pipeline_type *ptype;
struct app_pktq_kni_params *kni;
uint32_t pktq_in_id;
int status;
kni = &app->kni_params[pktq_out->id];
p = app_kni_get_reader(app, kni, &pktq_in_id);
if (p == NULL)
return NULL;
ptype = app_pipeline_type_find(app, p->type);
if ((ptype == NULL) || (ptype->fe_ops->f_track == NULL))
return NULL;
app_pipeline_params_get(app, p, &pp);
status = ptype->fe_ops->f_track(&pp,
pktq_in_id,
&pktq_out_id);
if (status)
return NULL;
break;
}
case APP_PKTQ_OUT_SINK: case APP_PKTQ_OUT_SINK:
default: default:
return NULL; return NULL;

View File

@ -106,6 +106,9 @@ pipeline_run(void *pipeline)
struct pipeline_master *p = (struct pipeline_master *) pipeline; struct pipeline_master *p = (struct pipeline_master *) pipeline;
struct app_params *app = p->app; struct app_params *app = p->app;
int status; int status;
#ifdef RTE_LIBRTE_KNI
uint32_t i;
#endif /* RTE_LIBRTE_KNI */
/* Application post-init phase */ /* Application post-init phase */
if (p->post_init_done == 0) { if (p->post_init_done == 0) {
@ -144,6 +147,12 @@ pipeline_run(void *pipeline)
rte_exit(0, "Bye!\n"); rte_exit(0, "Bye!\n");
} }
#ifdef RTE_LIBRTE_KNI
/* Handle KNI requests from Linux kernel */
for (i = 0; i < app->n_pktq_kni; i++)
rte_kni_handle_request(app->kni[i]);
#endif /* RTE_LIBRTE_KNI */
return 0; return 0;
} }

View File

@ -40,6 +40,9 @@
#include <rte_port_ras.h> #include <rte_port_ras.h>
#include <rte_port_sched.h> #include <rte_port_sched.h>
#include <rte_port_source_sink.h> #include <rte_port_source_sink.h>
#ifdef RTE_LIBRTE_KNI
#include <rte_port_kni.h>
#endif
#include <rte_pipeline.h> #include <rte_pipeline.h>
enum pipeline_port_in_type { enum pipeline_port_in_type {
@ -49,6 +52,7 @@ enum pipeline_port_in_type {
PIPELINE_PORT_IN_RING_READER_IPV4_FRAG, PIPELINE_PORT_IN_RING_READER_IPV4_FRAG,
PIPELINE_PORT_IN_RING_READER_IPV6_FRAG, PIPELINE_PORT_IN_RING_READER_IPV6_FRAG,
PIPELINE_PORT_IN_SCHED_READER, PIPELINE_PORT_IN_SCHED_READER,
PIPELINE_PORT_IN_KNI_READER,
PIPELINE_PORT_IN_SOURCE, PIPELINE_PORT_IN_SOURCE,
}; };
@ -61,6 +65,9 @@ struct pipeline_port_in_params {
struct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag; struct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag;
struct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag; struct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag;
struct rte_port_sched_reader_params sched; struct rte_port_sched_reader_params sched;
#ifdef RTE_LIBRTE_KNI
struct rte_port_kni_reader_params kni;
#endif
struct rte_port_source_params source; struct rte_port_source_params source;
} params; } params;
uint32_t burst_size; uint32_t burst_size;
@ -82,6 +89,10 @@ pipeline_port_in_params_convert(struct pipeline_port_in_params *p)
return (void *) &p->params.ring_ipv6_frag; return (void *) &p->params.ring_ipv6_frag;
case PIPELINE_PORT_IN_SCHED_READER: case PIPELINE_PORT_IN_SCHED_READER:
return (void *) &p->params.sched; return (void *) &p->params.sched;
#ifdef RTE_LIBRTE_KNI
case PIPELINE_PORT_IN_KNI_READER:
return (void *) &p->params.kni;
#endif
case PIPELINE_PORT_IN_SOURCE: case PIPELINE_PORT_IN_SOURCE:
return (void *) &p->params.source; return (void *) &p->params.source;
default: default:
@ -105,6 +116,10 @@ pipeline_port_in_params_get_ops(struct pipeline_port_in_params *p)
return &rte_port_ring_reader_ipv6_frag_ops; return &rte_port_ring_reader_ipv6_frag_ops;
case PIPELINE_PORT_IN_SCHED_READER: case PIPELINE_PORT_IN_SCHED_READER:
return &rte_port_sched_reader_ops; return &rte_port_sched_reader_ops;
#ifdef RTE_LIBRTE_KNI
case PIPELINE_PORT_IN_KNI_READER:
return &rte_port_kni_reader_ops;
#endif
case PIPELINE_PORT_IN_SOURCE: case PIPELINE_PORT_IN_SOURCE:
return &rte_port_source_ops; return &rte_port_source_ops;
default: default:
@ -122,6 +137,8 @@ enum pipeline_port_out_type {
PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS, PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS,
PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS, PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS,
PIPELINE_PORT_OUT_SCHED_WRITER, PIPELINE_PORT_OUT_SCHED_WRITER,
PIPELINE_PORT_OUT_KNI_WRITER,
PIPELINE_PORT_OUT_KNI_WRITER_NODROP,
PIPELINE_PORT_OUT_SINK, PIPELINE_PORT_OUT_SINK,
}; };
@ -137,6 +154,10 @@ struct pipeline_port_out_params {
struct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras; struct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras;
struct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras; struct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras;
struct rte_port_sched_writer_params sched; struct rte_port_sched_writer_params sched;
#ifdef RTE_LIBRTE_KNI
struct rte_port_kni_writer_params kni;
struct rte_port_kni_writer_nodrop_params kni_nodrop;
#endif
struct rte_port_sink_params sink; struct rte_port_sink_params sink;
} params; } params;
}; };
@ -163,6 +184,12 @@ pipeline_port_out_params_convert(struct pipeline_port_out_params *p)
return (void *) &p->params.ring_ipv6_ras; return (void *) &p->params.ring_ipv6_ras;
case PIPELINE_PORT_OUT_SCHED_WRITER: case PIPELINE_PORT_OUT_SCHED_WRITER:
return (void *) &p->params.sched; return (void *) &p->params.sched;
#ifdef RTE_LIBRTE_KNI
case PIPELINE_PORT_OUT_KNI_WRITER:
return (void *) &p->params.kni;
case PIPELINE_PORT_OUT_KNI_WRITER_NODROP:
return (void *) &p->params.kni_nodrop;
#endif
case PIPELINE_PORT_OUT_SINK: case PIPELINE_PORT_OUT_SINK:
return (void *) &p->params.sink; return (void *) &p->params.sink;
default: default:
@ -192,6 +219,12 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p)
return &rte_port_ring_writer_ipv6_ras_ops; return &rte_port_ring_writer_ipv6_ras_ops;
case PIPELINE_PORT_OUT_SCHED_WRITER: case PIPELINE_PORT_OUT_SCHED_WRITER:
return &rte_port_sched_writer_ops; return &rte_port_sched_writer_ops;
#ifdef RTE_LIBRTE_KNI
case PIPELINE_PORT_OUT_KNI_WRITER:
return &rte_port_kni_writer_ops;
case PIPELINE_PORT_OUT_KNI_WRITER_NODROP:
return &rte_port_kni_writer_nodrop_ops;
#endif
case PIPELINE_PORT_OUT_SINK: case PIPELINE_PORT_OUT_SINK:
return &rte_port_sink_ops; return &rte_port_sink_ops;
default: default: