examples/kni: monitor and update link state continually
Update KNI example to add the command line flag '-m' to enable a function to continuously monitor the Ethernet link status of the physical link and update the link status of the corresponding interfaces with rte_kni_update_link(). Signed-off-by: Dan Gora <dg@adax.com> Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>
This commit is contained in:
parent
89397a01ce
commit
724beb913b
@ -31,18 +31,27 @@ This is done by creating one or more kernel net devices for each of the DPDK por
|
||||
The application allows the use of standard Linux tools (ethtool, ifconfig, tcpdump) with the DPDK ports and
|
||||
also the exchange of packets between the DPDK application and the Linux* kernel.
|
||||
|
||||
The Kernel NIC Interface sample application requires that the
|
||||
KNI kernel module ``rte_kni`` be loaded into the kernel. See
|
||||
:doc:`../prog_guide/kernel_nic_interface` for more information on loading
|
||||
the ``rte_kni`` kernel module.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The Kernel NIC Interface sample application uses two threads in user space for each physical NIC port being used,
|
||||
and allocates one or more KNI device for each physical NIC port with kernel module's support.
|
||||
For a physical NIC port, one thread reads from the port and writes to KNI devices,
|
||||
and another thread reads from KNI devices and writes the data unmodified to the physical NIC port.
|
||||
It is recommended to configure one KNI device for each physical NIC port.
|
||||
If configured with more than one KNI devices for a physical NIC port,
|
||||
it is just for performance testing, or it can work together with VMDq support in future.
|
||||
The Kernel NIC Interface sample application ``kni`` allocates one or more
|
||||
KNI interfaces for each physical NIC port. For each physical NIC port,
|
||||
``kni`` uses two DPDK threads in user space; one thread reads from the port and
|
||||
writes to the corresponding KNI interfaces and the other thread reads from
|
||||
the KNI interfaces and writes the data unmodified to the physical NIC port.
|
||||
|
||||
The packet flow through the Kernel NIC Interface application is as shown in the following figure.
|
||||
It is recommended to configure one KNI interface for each physical NIC port.
|
||||
The application can be configured with more than one KNI interface for
|
||||
each physical NIC port for performance testing or it can work together with
|
||||
VMDq support in future.
|
||||
|
||||
The packet flow through the Kernel NIC Interface application is as shown
|
||||
in the following figure.
|
||||
|
||||
.. _figure_kernel_nic:
|
||||
|
||||
@ -50,145 +59,221 @@ The packet flow through the Kernel NIC Interface application is as shown in the
|
||||
|
||||
Kernel NIC Application Packet Flow
|
||||
|
||||
If link monitoring is enabled with the ``-m`` command line flag, one
|
||||
additional pthread is launched which will check the link status of each
|
||||
physical NIC port and will update the carrier status of the corresponding
|
||||
KNI interface(s) to match the physical NIC port's state. This means that
|
||||
the KNI interface(s) will be disabled automatically when the Ethernet link
|
||||
goes down and enabled when the Ethernet link goes up.
|
||||
|
||||
If link monitoring is enabled, the ``rte_kni`` kernel module should be loaded
|
||||
such that the :ref:`default carrier state <kni_default_carrier_state>` is
|
||||
set to *off*. This ensures that the KNI interface is only enabled *after*
|
||||
the Ethernet link of the corresponding NIC port has reached the linkup state.
|
||||
|
||||
If link monitoring is not enabled, the ``rte_kni`` kernel module should be
|
||||
loaded with the :ref:`default carrier state <kni_default_carrier_state>`
|
||||
set to *on*. This sets the carrier state of the KNI interfaces to *on*
|
||||
when the KNI interfaces are enabled without regard to the actual link state
|
||||
of the corresponding NIC port. This is useful for testing in loopback
|
||||
mode where the NIC port may not be physically connected to anything.
|
||||
|
||||
Compiling the Application
|
||||
-------------------------
|
||||
|
||||
To compile the sample application see :doc:`compiling`.
|
||||
|
||||
The application is located in the ``kni`` sub-directory.
|
||||
The application is located in the ``examples/kni`` sub-directory.
|
||||
|
||||
.. note::
|
||||
|
||||
This application is intended as a linuxapp only.
|
||||
|
||||
Loading the Kernel Module
|
||||
-------------------------
|
||||
Running the kni Example Application
|
||||
-----------------------------------
|
||||
|
||||
Loading the KNI kernel module without any parameter is the typical way a DPDK application
|
||||
gets packets into and out of the kernel net stack.
|
||||
This way, only one kernel thread is created for all KNI devices for packet receiving in kernel side:
|
||||
The ``kni`` example application requires a number of command line options:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
#insmod rte_kni.ko
|
||||
|
||||
Pinning the kernel thread to a specific core can be done using a taskset command such as following:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
#taskset -p 100000 `pgrep --fl kni_thread | awk '{print $1}'`
|
||||
|
||||
This command line tries to pin the specific kni_thread on the 20th lcore (lcore numbering starts at 0),
|
||||
which means it needs to check if that lcore is available on the board.
|
||||
This command must be sent after the application has been launched, as insmod does not start the kni thread.
|
||||
|
||||
For optimum performance,
|
||||
the lcore in the mask must be selected to be on the same socket as the lcores used in the KNI application.
|
||||
|
||||
To provide flexibility of performance, the kernel module of the KNI,
|
||||
located in the kmod sub-directory of the DPDK target directory,
|
||||
can be loaded with parameter of kthread_mode as follows:
|
||||
|
||||
* #insmod rte_kni.ko kthread_mode=single
|
||||
|
||||
This mode will create only one kernel thread for all KNI devices for packet receiving in kernel side.
|
||||
By default, it is in this single kernel thread mode.
|
||||
It can set core affinity for this kernel thread by using Linux command taskset.
|
||||
|
||||
* #insmod rte_kni.ko kthread_mode =multiple
|
||||
|
||||
This mode will create a kernel thread for each KNI device for packet receiving in kernel side.
|
||||
The core affinity of each kernel thread is set when creating the KNI device.
|
||||
The lcore ID for each kernel thread is provided in the command line of launching the application.
|
||||
Multiple kernel thread mode can provide scalable higher performance.
|
||||
|
||||
To measure the throughput in a loopback mode, the kernel module of the KNI,
|
||||
located in the kmod sub-directory of the DPDK target directory,
|
||||
can be loaded with parameters as follows:
|
||||
|
||||
* #insmod rte_kni.ko lo_mode=lo_mode_fifo
|
||||
|
||||
This loopback mode will involve ring enqueue/dequeue operations in kernel space.
|
||||
|
||||
* #insmod rte_kni.ko lo_mode=lo_mode_fifo_skb
|
||||
|
||||
This loopback mode will involve ring enqueue/dequeue operations and sk buffer copies in kernel space.
|
||||
|
||||
Running the Application
|
||||
-----------------------
|
||||
|
||||
The application requires a number of command line options:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
kni [EAL options] -- -P -p PORTMASK --config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,port,lcore_rx,lcore_tx[,lcore_kthread,...]]"
|
||||
kni [EAL options] -- -p PORTMASK --config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]" [-P] [-m]
|
||||
|
||||
Where:
|
||||
|
||||
* -P: Set all ports to promiscuous mode so that packets are accepted regardless of the packet's Ethernet MAC destination address.
|
||||
Without this option, only packets with the Ethernet MAC destination address set to the Ethernet address of the port are accepted.
|
||||
* ``-p PORTMASK``:
|
||||
|
||||
* -p PORTMASK: Hexadecimal bitmask of ports to configure.
|
||||
Hexadecimal bitmask of ports to configure.
|
||||
|
||||
* --config="(port,lcore_rx, lcore_tx[,lcore_kthread, ...]) [, port,lcore_rx, lcore_tx[,lcore_kthread, ...]]":
|
||||
Determines which lcores of RX, TX, kernel thread are mapped to which ports.
|
||||
* ``--config="(port,lcore_rx,lcore_tx[,lcore_kthread,...])[,(port,lcore_rx,lcore_tx[,lcore_kthread,...])]"``:
|
||||
|
||||
Refer to *DPDK Getting Started Guide* for general information on running applications and the Environment Abstraction Layer (EAL) options.
|
||||
Determines which lcores the Rx and Tx DPDK tasks, and (optionally)
|
||||
the KNI kernel thread(s) are bound to for each physical port.
|
||||
|
||||
The -c coremask or -l corelist parameter of the EAL options should include the lcores indicated by the lcore_rx and lcore_tx,
|
||||
but does not need to include lcores indicated by lcore_kthread as they are used to pin the kernel thread on.
|
||||
The -p PORTMASK parameter should include the ports indicated by the port in --config, neither more nor less.
|
||||
* ``-P``:
|
||||
|
||||
The lcore_kthread in --config can be configured none, one or more lcore IDs.
|
||||
In multiple kernel thread mode, if configured none, a KNI device will be allocated for each port,
|
||||
while no specific lcore affinity will be set for its kernel thread.
|
||||
If configured one or more lcore IDs, one or more KNI devices will be allocated for each port,
|
||||
while specific lcore affinity will be set for its kernel thread.
|
||||
In single kernel thread mode, if configured none, a KNI device will be allocated for each port.
|
||||
If configured one or more lcore IDs,
|
||||
one or more KNI devices will be allocated for each port while
|
||||
no lcore affinity will be set as there is only one kernel thread for all KNI devices.
|
||||
Optional flag to set all ports to promiscuous mode so that packets are
|
||||
accepted regardless of the packet's Ethernet MAC destination address.
|
||||
Without this option, only packets with the Ethernet MAC destination
|
||||
address set to the Ethernet address of the port are accepted.
|
||||
|
||||
For example, to run the application with two ports served by six lcores, one lcore of RX, one lcore of TX,
|
||||
and one lcore of kernel thread for each port:
|
||||
* ``-m``:
|
||||
|
||||
Optional flag to enable monitoring and updating of the Ethernet
|
||||
carrier state. With this option set, a thread will be started which
|
||||
will periodically check the Ethernet link status of the physical
|
||||
Ethernet ports and set the carrier state of the corresponding KNI
|
||||
network interface to match it. This means that the KNI interface will
|
||||
be disabled automatically when the Ethernet link goes down and enabled
|
||||
when the Ethernet link goes up.
|
||||
|
||||
Refer to *DPDK Getting Started Guide* for general information on running
|
||||
applications and the Environment Abstraction Layer (EAL) options.
|
||||
|
||||
The ``-c coremask`` or ``-l corelist`` parameter of the EAL options must
|
||||
include the lcores specified by ``lcore_rx`` and ``lcore_tx`` for each port,
|
||||
but does not need to include lcores specified by ``lcore_kthread`` as those
|
||||
cores are used to pin the kernel threads in the ``rte_kni`` kernel module.
|
||||
|
||||
The ``--config`` parameter must include a set of
|
||||
``(port,lcore_rx,lcore_tx,[lcore_kthread,...])`` values for each physical
|
||||
port specified in the ``-p PORTMASK`` parameter.
|
||||
|
||||
The optional ``lcore_kthread`` lcore ID parameter in ``--config`` can be
|
||||
specified zero, one or more times for each physical port.
|
||||
|
||||
If no lcore ID is specified for ``lcore_kthread``, one KNI interface will
|
||||
be created for the physical port ``port`` and the KNI kernel thread(s)
|
||||
will have no specific core affinity.
|
||||
|
||||
If one or more lcore IDs are specified for ``lcore_kthread``, a KNI interface
|
||||
will be created for each lcore ID specified, bound to the physical port
|
||||
``port``. If the ``rte_kni`` kernel module is loaded in :ref:`multiple
|
||||
kernel thread <kni_kernel_thread_mode>` mode, a kernel thread will be created
|
||||
for each KNI interface and bound to the specified core. If the ``rte_kni``
|
||||
kernel module is loaded in :ref:`single kernel thread <kni_kernel_thread_mode>`
|
||||
mode, only one kernel thread is started for all KNI interfaces. The kernel
|
||||
thread will be bound to the first ``lcore_kthread`` lcore ID specified.
|
||||
|
||||
Example Configurations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following commands will first load the ``rte_kni`` kernel module in
|
||||
:ref:`multiple kernel thread <kni_kernel_thread_mode>` mode. The ``kni``
|
||||
application is then started using two ports; Port 0 uses lcore 4 for the
|
||||
Rx task, lcore 6 for the Tx task, and will create a single KNI interface
|
||||
``vEth0_0`` with the kernel thread bound to lcore 8. Port 1 uses lcore
|
||||
5 for the Rx task, lcore 7 for the Tx task, and will create a single KNI
|
||||
interface ``vEth1_0`` with the kernel thread bound to lcore 9.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
./build/kni -l 4-7 -n 4 -- -P -p 0x3 --config="(0,4,6,8),(1,5,7,9)"
|
||||
# rmmod rte_kni
|
||||
# insmod kmod/rte_kni.ko kthread_mode=multiple
|
||||
# ./build/kni -l 4-7 -n 4 -- -P -p 0x3 -m --config="(0,4,6,8),(1,5,7,9)"
|
||||
|
||||
The following example is identical, except an additional ``lcore_kthread``
|
||||
core is specified per physical port. In this case, ``kni`` will create
|
||||
four KNI interfaces: ``vEth0_0``/``vEth0_1`` bound to physical port 0 and
|
||||
``vEth1_0``/``vEth1_1`` bound to physical port 1.
|
||||
|
||||
The kernel thread for each interface will be bound as follows:
|
||||
|
||||
* ``vEth0_0`` - bound to lcore 8.
|
||||
* ``vEth0_1`` - bound to lcore 10.
|
||||
* ``vEth1_0`` - bound to lcore 9.
|
||||
* ``vEth1_1`` - bound to lcore 11
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# rmmod rte_kni
|
||||
# insmod kmod/rte_kni.ko kthread_mode=multiple
|
||||
# ./build/kni -l 4-7 -n 4 -- -P -p 0x3 -m --config="(0,4,6,8,10),(1,5,7,9,11)"
|
||||
|
||||
The following example can be used to test the interface between the ``kni``
|
||||
test application and the ``rte_kni`` kernel module. In this example,
|
||||
the ``rte_kni`` kernel module is loaded in :ref:`single kernel thread
|
||||
mode <kni_kernel_thread_mode>`, :ref:`loopback mode <kni_loopback_mode>`
|
||||
enabled, and the :ref:`default carrier state <kni_default_carrier_state>`
|
||||
is set to *on* so that the corresponding physical NIC port does not have
|
||||
to be connected in order to use the KNI interface. One KNI interface
|
||||
``vEth0_0`` is created for port 0 and one KNI interface ``vEth1_0`` is
|
||||
created for port 1. Since ``rte_kni`` is loaded in "single kernel thread"
|
||||
mode, the one kernel thread is bound to lcore 8.
|
||||
|
||||
Since the physical NIC ports are not being used, link monitoring can be
|
||||
disabled by **not** specifying the ``-m`` flag to ``kni``:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# rmmod rte_kni
|
||||
# insmod kmod/rte_kni.ko lo_mode=lo_mode_fifo carrier=on
|
||||
# ./build/kni -l 4-7 -n 4 -- -P -p 0x3 --config="(0,4,6,8),(1,5,7,9)"
|
||||
|
||||
KNI Operations
|
||||
--------------
|
||||
|
||||
Once the KNI application is started, one can use different Linux* commands to manage the net interfaces.
|
||||
If more than one KNI devices configured for a physical port,
|
||||
only the first KNI device will be paired to the physical device.
|
||||
Operations on other KNI devices will not affect the physical port handled in user space application.
|
||||
Once the ``kni`` application is started, the user can use the normal
|
||||
Linux commands to manage the KNI interfaces as if they were any other
|
||||
Linux network interface.
|
||||
|
||||
Assigning an IP address:
|
||||
Enable KNI interface and assign an IP address:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
#ifconfig vEth0_0 192.168.0.1
|
||||
# ifconfig vEth0_0 192.168.0.1
|
||||
|
||||
Displaying the NIC registers:
|
||||
Show KNI interface configuration and statistics:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
#ethtool -d vEth0_0
|
||||
# ifconfig vEth0_0
|
||||
|
||||
Dumping the network traffic:
|
||||
The user can also check and reset the packet statistics inside the ``kni``
|
||||
application by sending the app the USR1 and USR2 signals:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
#tcpdump -i vEth0_0
|
||||
# Print statistics
|
||||
# kill -SIGUSR1 `pidof kni`
|
||||
|
||||
# Zero statistics
|
||||
# kill -SIGUSR2 `pidof kni`
|
||||
|
||||
Dump network traffic:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# tcpdump -i vEth0_0
|
||||
|
||||
The normal Linux commands can also be used to change the MAC address and
|
||||
MTU size used by the physical NIC which corresponds to the KNI interface.
|
||||
However, if more than one KNI interface is configured for a physical port,
|
||||
these commands will only work on the first KNI interface for that port.
|
||||
|
||||
Change the MAC address:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
#ifconfig vEth0_0 hw ether 0C:01:02:03:04:08
|
||||
# ifconfig vEth0_0 hw ether 0C:01:02:03:04:08
|
||||
|
||||
When the DPDK userspace application is closed, all the KNI devices are deleted from Linux*.
|
||||
Change the MTU size:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# ifconfig vEth0_0 mtu 1450
|
||||
|
||||
If DPDK is compiled with ``CONFIG_RTE_KNI_KMOD_ETHTOOL=y`` and an Intel
|
||||
NIC is used, the user can use ``ethtool`` on the KNI interface as if it
|
||||
were a normal Linux kernel interface.
|
||||
|
||||
Displaying the NIC registers:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
# ethtool -d vEth0_0
|
||||
|
||||
When the ``kni`` application is closed, all the KNI interfaces are deleted
|
||||
from the Linux kernel.
|
||||
|
||||
Explanation
|
||||
-----------
|
||||
@ -227,7 +312,7 @@ 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 (``kni_ingress``),
|
||||
the packet reception is the same as in L2 Forwarding sample application
|
||||
(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.
|
||||
|
||||
For the other case that reads from kernel NIC interfaces
|
||||
@ -235,16 +320,3 @@ and writes to a physical NIC port (``kni_egress``),
|
||||
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
|
||||
(see :ref:`l2_fwd_app_rx_tx_packets`).
|
||||
|
||||
Callbacks for Kernel Requests
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To execute specific PMD operations in user space requested by some Linux* commands,
|
||||
callbacks must be implemented and filled in the struct rte_kni_ops structure.
|
||||
Currently, setting a new MTU, change in MAC address, configuring promiscusous mode and
|
||||
configuring the network interface(up/down) re supported.
|
||||
Default implementation for following is available in rte_kni library.
|
||||
Application may choose to not implement following callbacks:
|
||||
|
||||
- ``config_mac_address``
|
||||
- ``config_promiscusity``
|
||||
|
@ -20,6 +20,7 @@ static: build/$(APP)-static
|
||||
|
||||
PC_FILE := $(shell pkg-config --path libdpdk)
|
||||
CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
|
||||
CFLAGS += -DALLOW_EXPERIMENTAL_API
|
||||
LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
|
||||
LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
|
||||
|
||||
@ -54,6 +55,7 @@ please change the definition of the RTE_TARGET environment variable)
|
||||
endif
|
||||
|
||||
CFLAGS += -O3
|
||||
CFLAGS += -DALLOW_EXPERIMENTAL_API
|
||||
CFLAGS += $(WERROR_FLAGS)
|
||||
|
||||
include $(RTE_SDK)/mk/rte.extapp.mk
|
||||
|
@ -106,6 +106,8 @@ static struct rte_mempool * pktmbuf_pool = NULL;
|
||||
static uint32_t ports_mask = 0;
|
||||
/* Ports set in promiscuous mode off by default. */
|
||||
static int promiscuous_on = 0;
|
||||
/* Monitor link status continually. off by default. */
|
||||
static int monitor_links;
|
||||
|
||||
/* Structure type for recording kni interface specific stats */
|
||||
struct kni_interface_stats {
|
||||
@ -325,11 +327,12 @@ main_loop(__rte_unused void *arg)
|
||||
static void
|
||||
print_usage(const char *prgname)
|
||||
{
|
||||
RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P "
|
||||
RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P -m "
|
||||
"[--config (port,lcore_rx,lcore_tx,lcore_kthread...)"
|
||||
"[,(port,lcore_rx,lcore_tx,lcore_kthread...)]]\n"
|
||||
" -p PORTMASK: hex bitmask of ports to use\n"
|
||||
" -P : enable promiscuous mode\n"
|
||||
" -m : enable monitoring of port carrier state\n"
|
||||
" --config (port,lcore_rx,lcore_tx,lcore_kthread...): "
|
||||
"port and lcore configurations\n",
|
||||
prgname);
|
||||
@ -510,7 +513,7 @@ parse_args(int argc, char **argv)
|
||||
opterr = 0;
|
||||
|
||||
/* Parse command line */
|
||||
while ((opt = getopt_long(argc, argv, "p:P", longopts,
|
||||
while ((opt = getopt_long(argc, argv, "p:Pm", longopts,
|
||||
&longindex)) != EOF) {
|
||||
switch (opt) {
|
||||
case 'p':
|
||||
@ -519,6 +522,9 @@ parse_args(int argc, char **argv)
|
||||
case 'P':
|
||||
promiscuous_on = 1;
|
||||
break;
|
||||
case 'm':
|
||||
monitor_links = 1;
|
||||
break;
|
||||
case 0:
|
||||
if (!strncmp(longopts[longindex].name,
|
||||
CMDLINE_OPT_CONFIG,
|
||||
@ -674,6 +680,55 @@ check_all_ports_link_status(uint32_t port_mask)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
log_link_state(struct rte_kni *kni, int prev, struct rte_eth_link *link)
|
||||
{
|
||||
if (kni == NULL || link == NULL)
|
||||
return;
|
||||
|
||||
if (prev == ETH_LINK_DOWN && link->link_status == ETH_LINK_UP) {
|
||||
RTE_LOG(INFO, APP, "%s NIC Link is Up %d Mbps %s %s.\n",
|
||||
rte_kni_get_name(kni),
|
||||
link->link_speed,
|
||||
link->link_autoneg ? "(AutoNeg)" : "(Fixed)",
|
||||
link->link_duplex ? "Full Duplex" : "Half Duplex");
|
||||
} else if (prev == ETH_LINK_UP && link->link_status == ETH_LINK_DOWN) {
|
||||
RTE_LOG(INFO, APP, "%s NIC Link is Down.\n",
|
||||
rte_kni_get_name(kni));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Monitor the link status of all ports and update the
|
||||
* corresponding KNI interface(s)
|
||||
*/
|
||||
static void *
|
||||
monitor_all_ports_link_status(void *arg)
|
||||
{
|
||||
uint16_t portid;
|
||||
struct rte_eth_link link;
|
||||
unsigned int i;
|
||||
struct kni_port_params **p = kni_port_params_array;
|
||||
int prev;
|
||||
(void) arg;
|
||||
|
||||
while (monitor_links) {
|
||||
rte_delay_ms(500);
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
if ((ports_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
memset(&link, 0, sizeof(link));
|
||||
rte_eth_link_get_nowait(portid, &link);
|
||||
for (i = 0; i < p[portid]->nb_kni; i++) {
|
||||
prev = rte_kni_update_link(p[portid]->kni[i],
|
||||
link.link_status);
|
||||
log_link_state(p[portid]->kni[i], prev, &link);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Callback for request of changing MTU */
|
||||
static int
|
||||
kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
|
||||
@ -893,6 +948,8 @@ main(int argc, char** argv)
|
||||
int ret;
|
||||
uint16_t nb_sys_ports, port;
|
||||
unsigned i;
|
||||
void *retval;
|
||||
pthread_t kni_link_tid;
|
||||
|
||||
/* Associate signal_hanlder function with USR signals */
|
||||
signal(SIGUSR1, signal_handler);
|
||||
@ -949,12 +1006,21 @@ main(int argc, char** argv)
|
||||
}
|
||||
check_all_ports_link_status(ports_mask);
|
||||
|
||||
ret = rte_ctrl_thread_create(&kni_link_tid,
|
||||
"KNI link status check", NULL,
|
||||
monitor_all_ports_link_status, NULL);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Could not create link status thread!\n");
|
||||
|
||||
/* Launch per-lcore function on every lcore */
|
||||
rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER);
|
||||
RTE_LCORE_FOREACH_SLAVE(i) {
|
||||
if (rte_eal_wait_lcore(i) < 0)
|
||||
return -1;
|
||||
}
|
||||
monitor_links = 0;
|
||||
pthread_join(kni_link_tid, &retval);
|
||||
|
||||
/* Release resources */
|
||||
RTE_ETH_FOREACH_DEV(port) {
|
||||
|
@ -12,3 +12,4 @@ deps += ['kni', 'bus_pci']
|
||||
sources = files(
|
||||
'main.c'
|
||||
)
|
||||
allow_experimental_apis = true
|
||||
|
Loading…
x
Reference in New Issue
Block a user