doc: remove code from KNI example guide
The example code is showing how to use KNI, and can be found in examples/kni/ The documentation guide for this example is explaining the code to ease the understanding of the example. And inside this documentation, there are a lot of examples code which are copy/pasted. It is really too much and hard to maintain. The code inside this documentation is replaced by the name of the functions. Signed-off-by: Thomas Monjalon <thomas@monjalon.net> Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
parent
5697d0888e
commit
05096a8be5
@ -202,74 +202,8 @@ Setup of mbuf pool, driver and queues is similar to the setup done in the :doc:`
|
|||||||
In addition, one or more kernel NIC interfaces are allocated for each
|
In addition, one or more kernel NIC interfaces are allocated for each
|
||||||
of the configured ports according to the command line parameters.
|
of the configured ports according to the command line parameters.
|
||||||
|
|
||||||
The code for allocating the kernel NIC interfaces for a specific port is as follows:
|
The code for allocating the kernel NIC interfaces for a specific port is
|
||||||
|
in the function ``kni_alloc``.
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
static int
|
|
||||||
kni_alloc(uint16_t port_id)
|
|
||||||
{
|
|
||||||
uint8_t i;
|
|
||||||
struct rte_kni *kni;
|
|
||||||
struct rte_kni_conf conf;
|
|
||||||
struct kni_port_params **params = kni_port_params_array;
|
|
||||||
|
|
||||||
if (port_id >= RTE_MAX_ETHPORTS || !params[port_id])
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
params[port_id]->nb_kni = params[port_id]->nb_lcore_k ? params[port_id]->nb_lcore_k : 1;
|
|
||||||
|
|
||||||
for (i = 0; i < params[port_id]->nb_kni; i++) {
|
|
||||||
|
|
||||||
/* Clear conf at first */
|
|
||||||
|
|
||||||
memset(&conf, 0, sizeof(conf));
|
|
||||||
if (params[port_id]->nb_lcore_k) {
|
|
||||||
snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u_%u", port_id, i);
|
|
||||||
conf.core_id = params[port_id]->lcore_k[i];
|
|
||||||
conf.force_bind = 1;
|
|
||||||
} else
|
|
||||||
snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u", port_id);
|
|
||||||
conf.group_id = (uint16_t)port_id;
|
|
||||||
conf.mbuf_size = MAX_PACKET_SZ;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The first KNI device associated to a port
|
|
||||||
* is the master, for multiple kernel thread
|
|
||||||
* environment.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
struct rte_kni_ops ops;
|
|
||||||
struct rte_eth_dev_info dev_info;
|
|
||||||
|
|
||||||
memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(port_id, &dev_info);
|
|
||||||
|
|
||||||
conf.addr = dev_info.pci_dev->addr;
|
|
||||||
conf.id = dev_info.pci_dev->id;
|
|
||||||
|
|
||||||
/* Get the interface default mac address */
|
|
||||||
rte_eth_macaddr_get(port_id, (struct ether_addr *)&conf.mac_addr);
|
|
||||||
|
|
||||||
memset(&ops, 0, sizeof(ops));
|
|
||||||
|
|
||||||
ops.port_id = port_id;
|
|
||||||
ops.change_mtu = kni_change_mtu;
|
|
||||||
ops.config_network_if = kni_config_network_interface;
|
|
||||||
ops.config_mac_address = kni_config_mac_address;
|
|
||||||
|
|
||||||
kni = rte_kni_alloc(pktmbuf_pool, &conf, &ops);
|
|
||||||
} else
|
|
||||||
kni = rte_kni_alloc(pktmbuf_pool, &conf, NULL);
|
|
||||||
|
|
||||||
if (!kni)
|
|
||||||
rte_exit(EXIT_FAILURE, "Fail to create kni for "
|
|
||||||
"port: %d\n", port_id);
|
|
||||||
|
|
||||||
params[port_id]->kni[i] = kni;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
The other step in the initialization process that is unique to this sample application
|
The other step in the initialization process that is unique to this sample application
|
||||||
is the association of each port with lcores for RX, TX and kernel threads.
|
is the association of each port with lcores for RX, TX and kernel threads.
|
||||||
@ -280,105 +214,8 @@ is the association of each port with lcores for RX, TX and kernel threads.
|
|||||||
|
|
||||||
* Other lcores for pinning the kernel threads on one by one
|
* Other lcores for pinning the kernel threads on one by one
|
||||||
|
|
||||||
This is done by using the`kni_port_params_array[]` array, which is indexed by the port ID.
|
This is done by using the ``kni_port_params_array[]`` array, which is indexed by the port ID.
|
||||||
The code is as follows:
|
The code is in the function ``parse_config``.
|
||||||
|
|
||||||
.. code-block:: console
|
|
||||||
|
|
||||||
static int
|
|
||||||
parse_config(const char *arg)
|
|
||||||
{
|
|
||||||
const char *p, *p0 = arg;
|
|
||||||
char s[256], *end;
|
|
||||||
unsigned size;
|
|
||||||
enum fieldnames {
|
|
||||||
FLD_PORT = 0,
|
|
||||||
FLD_LCORE_RX,
|
|
||||||
FLD_LCORE_TX,
|
|
||||||
_NUM_FLD = KNI_MAX_KTHREAD + 3,
|
|
||||||
};
|
|
||||||
int i, j, nb_token;
|
|
||||||
char *str_fld[_NUM_FLD];
|
|
||||||
unsigned long int_fld[_NUM_FLD];
|
|
||||||
uint16_t port_id, nb_kni_port_params = 0;
|
|
||||||
|
|
||||||
memset(&kni_port_params_array, 0, sizeof(kni_port_params_array));
|
|
||||||
|
|
||||||
while (((p = strchr(p0, '(')) != NULL) && nb_kni_port_params < RTE_MAX_ETHPORTS) {
|
|
||||||
p++;
|
|
||||||
if ((p0 = strchr(p, ')')) == NULL)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
size = p0 - p;
|
|
||||||
|
|
||||||
if (size >= sizeof(s)) {
|
|
||||||
printf("Invalid config parameters\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(s, sizeof(s), "%.*s", size, p);
|
|
||||||
nb_token = rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',');
|
|
||||||
|
|
||||||
if (nb_token <= FLD_LCORE_TX) {
|
|
||||||
printf("Invalid config parameters\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < nb_token; i++) {
|
|
||||||
errno = 0;
|
|
||||||
int_fld[i] = strtoul(str_fld[i], &end, 0);
|
|
||||||
if (errno != 0 || end == str_fld[i]) {
|
|
||||||
printf("Invalid config parameters\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
port_id = (uint8_t)int_fld[i++];
|
|
||||||
|
|
||||||
if (port_id >= RTE_MAX_ETHPORTS) {
|
|
||||||
printf("Port ID %u could not exceed the maximum %u\n", port_id, RTE_MAX_ETHPORTS);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kni_port_params_array[port_id]) {
|
|
||||||
printf("Port %u has been configured\n", port_id);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
kni_port_params_array[port_id] = (struct kni_port_params*)rte_zmalloc("KNI_port_params", sizeof(struct kni_port_params), RTE_CACHE_LINE_SIZE);
|
|
||||||
kni_port_params_array[port_id]->port_id = port_id;
|
|
||||||
kni_port_params_array[port_id]->lcore_rx = (uint8_t)int_fld[i++];
|
|
||||||
kni_port_params_array[port_id]->lcore_tx = (uint8_t)int_fld[i++];
|
|
||||||
|
|
||||||
if (kni_port_params_array[port_id]->lcore_rx >= RTE_MAX_LCORE || kni_port_params_array[port_id]->lcore_tx >= RTE_MAX_LCORE) {
|
|
||||||
printf("lcore_rx %u or lcore_tx %u ID could not "
|
|
||||||
"exceed the maximum %u\n",
|
|
||||||
kni_port_params_array[port_id]->lcore_rx, kni_port_params_array[port_id]->lcore_tx, RTE_MAX_LCORE);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; i < nb_token && j < KNI_MAX_KTHREAD; i++, j++)
|
|
||||||
kni_port_params_array[port_id]->lcore_k[j] = (uint8_t)int_fld[i];
|
|
||||||
kni_port_params_array[port_id]->nb_lcore_k = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
print_config();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
|
|
||||||
for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
|
|
||||||
if (kni_port_params_array[i]) {
|
|
||||||
rte_free(kni_port_params_array[i]);
|
|
||||||
kni_port_params_array[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Packet Forwarding
|
Packet Forwarding
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
@ -387,99 +224,18 @@ After the initialization steps are completed, the main_loop() function is run on
|
|||||||
This function first checks the lcore_id against the user provided lcore_rx and lcore_tx
|
This function first checks the lcore_id against the user provided lcore_rx and lcore_tx
|
||||||
to see if this lcore is reading from or writing to kernel NIC interfaces.
|
to see if this lcore is reading from or writing to kernel NIC interfaces.
|
||||||
|
|
||||||
For the case that reads from a NIC port and writes to the kernel NIC interfaces,
|
For the case that reads from a NIC port and writes to the kernel NIC interfaces (``kni_ingress``),
|
||||||
the packet reception is the same as in L2 Forwarding sample application
|
the packet reception is the same as in L2 Forwarding sample application
|
||||||
(see :ref:`l2_fwd_app_rx_tx_packets`).
|
(see :ref:`l2_fwd_app_rx_tx_packets`).
|
||||||
The packet transmission is done by sending mbufs into the kernel NIC interfaces by rte_kni_tx_burst().
|
The packet transmission is done by sending mbufs into the kernel NIC interfaces by rte_kni_tx_burst().
|
||||||
The KNI library automatically frees the mbufs after the kernel successfully copied the mbufs.
|
The KNI library automatically frees the mbufs after the kernel successfully copied the mbufs.
|
||||||
|
|
||||||
.. code-block:: c
|
For the other case that reads from kernel NIC interfaces
|
||||||
|
and writes to a physical NIC port (``kni_egress``),
|
||||||
/**
|
packets are retrieved by reading mbufs from kernel NIC interfaces by ``rte_kni_rx_burst()``.
|
||||||
* Interface to burst rx and enqueue mbufs into rx_q
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
kni_ingress(struct kni_port_params *p)
|
|
||||||
{
|
|
||||||
uint8_t i, nb_kni, port_id;
|
|
||||||
unsigned nb_rx, num;
|
|
||||||
struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
|
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nb_kni = p->nb_kni;
|
|
||||||
port_id = p->port_id;
|
|
||||||
|
|
||||||
for (i = 0; i < nb_kni; i++) {
|
|
||||||
/* Burst rx from eth */
|
|
||||||
nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, PKT_BURST_SZ);
|
|
||||||
if (unlikely(nb_rx > PKT_BURST_SZ)) {
|
|
||||||
RTE_LOG(ERR, APP, "Error receiving from eth\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Burst tx to kni */
|
|
||||||
num = rte_kni_tx_burst(p->kni[i], pkts_burst, nb_rx);
|
|
||||||
kni_stats[port_id].rx_packets += num;
|
|
||||||
rte_kni_handle_request(p->kni[i]);
|
|
||||||
|
|
||||||
if (unlikely(num < nb_rx)) {
|
|
||||||
/* Free mbufs not tx to kni interface */
|
|
||||||
kni_burst_free_mbufs(&pkts_burst[num], nb_rx - num);
|
|
||||||
kni_stats[port_id].rx_dropped += nb_rx - num;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
For the other case that reads from kernel NIC interfaces and writes to a physical NIC port, packets are retrieved by reading
|
|
||||||
mbufs from kernel NIC interfaces by `rte_kni_rx_burst()`.
|
|
||||||
The packet transmission is the same as in the L2 Forwarding sample application
|
The packet transmission is the same as in the L2 Forwarding sample application
|
||||||
(see :ref:`l2_fwd_app_rx_tx_packets`).
|
(see :ref:`l2_fwd_app_rx_tx_packets`).
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface to dequeue mbufs from tx_q and burst tx
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void
|
|
||||||
|
|
||||||
kni_egress(struct kni_port_params *p)
|
|
||||||
{
|
|
||||||
uint8_t i, nb_kni, port_id;
|
|
||||||
unsigned nb_tx, num;
|
|
||||||
struct rte_mbuf *pkts_burst[PKT_BURST_SZ];
|
|
||||||
|
|
||||||
if (p == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nb_kni = p->nb_kni;
|
|
||||||
port_id = p->port_id;
|
|
||||||
|
|
||||||
for (i = 0; i < nb_kni; i++) {
|
|
||||||
/* Burst rx from kni */
|
|
||||||
num = rte_kni_rx_burst(p->kni[i], pkts_burst, PKT_BURST_SZ);
|
|
||||||
if (unlikely(num > PKT_BURST_SZ)) {
|
|
||||||
RTE_LOG(ERR, APP, "Error receiving from KNI\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Burst tx to eth */
|
|
||||||
|
|
||||||
nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num);
|
|
||||||
|
|
||||||
kni_stats[port_id].tx_packets += nb_tx;
|
|
||||||
|
|
||||||
if (unlikely(nb_tx < num)) {
|
|
||||||
/* Free mbufs not tx to NIC */
|
|
||||||
kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx);
|
|
||||||
kni_stats[port_id].tx_dropped += num - nb_tx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Callbacks for Kernel Requests
|
Callbacks for Kernel Requests
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -492,96 +248,3 @@ Application may choose to not implement following callbacks:
|
|||||||
|
|
||||||
- ``config_mac_address``
|
- ``config_mac_address``
|
||||||
- ``config_promiscusity``
|
- ``config_promiscusity``
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
static struct rte_kni_ops kni_ops = {
|
|
||||||
.change_mtu = kni_change_mtu,
|
|
||||||
.config_network_if = kni_config_network_interface,
|
|
||||||
.config_mac_address = kni_config_mac_address,
|
|
||||||
.config_promiscusity = kni_config_promiscusity,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Callback for request of changing MTU */
|
|
||||||
|
|
||||||
static int
|
|
||||||
kni_change_mtu(uint16_t port_id, unsigned new_mtu)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
struct rte_eth_conf conf;
|
|
||||||
|
|
||||||
RTE_LOG(INFO, APP, "Change MTU of port %d to %u\n", port_id, new_mtu);
|
|
||||||
|
|
||||||
/* Stop specific port */
|
|
||||||
|
|
||||||
rte_eth_dev_stop(port_id);
|
|
||||||
|
|
||||||
memcpy(&conf, &port_conf, sizeof(conf));
|
|
||||||
|
|
||||||
/* Set new MTU */
|
|
||||||
|
|
||||||
if (new_mtu > ETHER_MAX_LEN)
|
|
||||||
conf.rxmode.jumbo_frame = 1;
|
|
||||||
else
|
|
||||||
conf.rxmode.jumbo_frame = 0;
|
|
||||||
|
|
||||||
/* mtu + length of header + length of FCS = max pkt length */
|
|
||||||
|
|
||||||
conf.rxmode.max_rx_pkt_len = new_mtu + KNI_ENET_HEADER_SIZE + KNI_ENET_FCS_SIZE;
|
|
||||||
|
|
||||||
ret = rte_eth_dev_configure(port_id, 1, 1, &conf);
|
|
||||||
if (ret < 0) {
|
|
||||||
RTE_LOG(ERR, APP, "Fail to reconfigure port %d\n", port_id);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Restart specific port */
|
|
||||||
|
|
||||||
ret = rte_eth_dev_start(port_id);
|
|
||||||
if (ret < 0) {
|
|
||||||
RTE_LOG(ERR, APP, "Fail to restart port %d\n", port_id);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback for request of configuring network interface up/down */
|
|
||||||
|
|
||||||
static int
|
|
||||||
kni_config_network_interface(uint16_t port_id, uint8_t if_up)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
RTE_LOG(INFO, APP, "Configure network interface of %d %s\n",
|
|
||||||
|
|
||||||
port_id, if_up ? "up" : "down");
|
|
||||||
|
|
||||||
if (if_up != 0) {
|
|
||||||
/* Configure network interface up */
|
|
||||||
rte_eth_dev_stop(port_id);
|
|
||||||
ret = rte_eth_dev_start(port_id);
|
|
||||||
} else /* Configure network interface down */
|
|
||||||
rte_eth_dev_stop(port_id);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback for request of configuring device mac address */
|
|
||||||
|
|
||||||
static int
|
|
||||||
kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[])
|
|
||||||
{
|
|
||||||
.....
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Callback for request of configuring promiscuous mode */
|
|
||||||
|
|
||||||
static int
|
|
||||||
kni_config_promiscusity(uint16_t port_id, uint8_t to_on)
|
|
||||||
{
|
|
||||||
.....
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user