[PATCH v19 22/25] net/pcap: add link status change support for iface mode
Stephen Hemminger
stephen at networkplumber.org
Tue Mar 10 03:47:57 CET 2026
Add LSC interrupt support for pass-through (iface=) mode so
applications can receive link state change notifications via
the standard ethdev callback mechanism.
Uses alarm-based polling to periodically check the underlying
interface state via osdep_iface_link_get(). The LSC flag is
advertised only for iface mode devices, and polling is gated
on the application enabling intr_conf.lsc in port configuration.
Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
doc/guides/nics/features/pcap.ini | 1 +
doc/guides/nics/pcap.rst | 5 +++
doc/guides/rel_notes/release_26_03.rst | 1 +
drivers/net/pcap/pcap_ethdev.c | 45 ++++++++++++++++++++++++++
4 files changed, 52 insertions(+)
diff --git a/doc/guides/nics/features/pcap.ini b/doc/guides/nics/features/pcap.ini
index ec7c91c650..b409ecd597 100644
--- a/doc/guides/nics/features/pcap.ini
+++ b/doc/guides/nics/features/pcap.ini
@@ -5,6 +5,7 @@
;
[Features]
Link status = Y
+Link status event = Y
Queue start/stop = Y
Timestamp offload = Y
Basic stats = Y
diff --git a/doc/guides/nics/pcap.rst b/doc/guides/nics/pcap.rst
index 2754e205c7..72f2250790 100644
--- a/doc/guides/nics/pcap.rst
+++ b/doc/guides/nics/pcap.rst
@@ -278,3 +278,8 @@ Features and Limitations
* The PMD will insert the pcap header packet timestamp with nanoseconds resolution and
UNIX origin, i.e. time since 1-JAN-1970 UTC, if ``RTE_ETH_RX_OFFLOAD_TIMESTAMP`` is enabled.
+
+* In ``iface`` mode, the PMD supports link status change (LSC) notifications.
+ When the application enables ``intr_conf.lsc`` in the port configuration,
+ the driver polls the underlying network interface once per second and generates an
+ ``RTE_ETH_EVENT_INTR_LSC`` callback when the link state changes.
diff --git a/doc/guides/rel_notes/release_26_03.rst b/doc/guides/rel_notes/release_26_03.rst
index 49e2c0cf2b..c1bb808195 100644
--- a/doc/guides/rel_notes/release_26_03.rst
+++ b/doc/guides/rel_notes/release_26_03.rst
@@ -112,6 +112,7 @@ New Features
* Added support for reporting link state in ``iface`` mode.
* Receive timestamps support nanosecond precision.
* Added ``snaplen`` devarg to configure packet capture snapshot length.
+ * Added support for Link State interrupt in ``iface`` mode.
Removed Items
diff --git a/drivers/net/pcap/pcap_ethdev.c b/drivers/net/pcap/pcap_ethdev.c
index d8a924b0cd..2d64032474 100644
--- a/drivers/net/pcap/pcap_ethdev.c
+++ b/drivers/net/pcap/pcap_ethdev.c
@@ -17,6 +17,7 @@
#include <pcap.h>
+#include <rte_alarm.h>
#include <rte_cycles.h>
#include <rte_ring.h>
#include <rte_ethdev.h>
@@ -48,6 +49,8 @@
/* This is defined in libpcap but not exposed in headers */
#define ETH_PCAP_MAXIMUM_SNAPLEN 262144
+#define ETH_PCAP_LSC_POLL_INTERVAL_US (1000 * 1000) /* 1 second */
+
#define ETH_PCAP_ARG_MAXLEN 64
#define RTE_PMD_PCAP_MAX_QUEUES 16
@@ -115,6 +118,7 @@ struct pmd_internals {
bool vlan_strip;
bool rx_scatter;
bool timestamp_offloading;
+ bool lsc_active;
};
struct pmd_process_private {
@@ -163,6 +167,9 @@ static const char *valid_arguments[] = {
RTE_LOG_REGISTER_DEFAULT(eth_pcap_logtype, NOTICE);
+/* Forward declarations */
+static int eth_link_update(struct rte_eth_dev *dev, int wait_to_complete);
+
static struct queue_missed_stat*
queue_missed_stat_update(struct rte_eth_dev *dev, unsigned int qid)
{
@@ -766,6 +773,28 @@ count_packets_in_pcap(pcap_t **pcap, struct pcap_rx_queue *pcap_q)
return pcap_pkt_count;
}
+/*
+ * Periodic alarm to poll link state.
+ * Enabled when link state interrupt is enabled in single_iface mode.
+ */
+static void
+eth_pcap_lsc_alarm(void *arg)
+{
+ struct rte_eth_dev *dev = arg;
+ struct pmd_internals *internals = dev->data->dev_private;
+ struct rte_eth_link old_link, new_link;
+
+ rte_eth_linkstatus_get(dev, &old_link);
+ eth_link_update(dev, 0);
+ rte_eth_linkstatus_get(dev, &new_link);
+
+ if (old_link.link_status != new_link.link_status)
+ rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
+
+ if (internals->lsc_active)
+ rte_eal_alarm_set(ETH_PCAP_LSC_POLL_INTERVAL_US, eth_pcap_lsc_alarm, dev);
+}
+
static int
set_iface_direction(const char *iface, pcap_t *pcap,
pcap_direction_t direction)
@@ -848,6 +877,13 @@ eth_dev_start(struct rte_eth_dev *dev)
dev->data->dev_link.link_status = RTE_ETH_LINK_UP;
+ /* Start LSC polling for iface mode if application requested it */
+ if (internals->single_iface && dev->data->dev_conf.intr_conf.lsc) {
+ internals->lsc_active = true;
+ rte_eal_alarm_set(ETH_PCAP_LSC_POLL_INTERVAL_US,
+ eth_pcap_lsc_alarm, dev);
+ }
+
return 0;
}
@@ -865,6 +901,12 @@ eth_dev_stop(struct rte_eth_dev *dev)
/* Special iface case. Single pcap is open and shared between tx/rx. */
if (internals->single_iface) {
+ /* Cancel LSC polling before closing pcap handles */
+ if (internals->lsc_active) {
+ internals->lsc_active = false;
+ rte_eal_alarm_cancel(eth_pcap_lsc_alarm, dev);
+ }
+
queue_missed_stat_on_stop_update(dev, 0);
if (pp->tx_pcap[0] != NULL) {
pcap_close(pp->tx_pcap[0]);
@@ -1661,6 +1703,9 @@ eth_from_pcaps(struct rte_vdev_device *vdev,
internals->if_index =
osdep_iface_index_get(rx_queues->queue[0].name);
+ /* Enable LSC interrupt support for iface mode */
+ eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
+
/* phy_mac arg is applied only if "iface" devarg is provided */
if (rx_queues->phy_mac) {
if (eth_pcap_update_mac(rx_queues->queue[0].name,
--
2.51.0
More information about the dev
mailing list