* [PATCH v1 0/7] migrate threads to DPDK service framework
@ 2025-09-08 11:04 Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 1/7] net/ntnic: introduce service API for NTNIC PMD Serhii Iliushyk
` (7 more replies)
0 siblings, 8 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 11:04 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This modification provides better resource (CPU) management for NTNIC PMD.
The following threads are migrated:
* FLM update thread
* Statistic thread
* Port event thread
* Adapter monitoring thread
Additionally, a warning is added to inform users about the importance of
dedicating lcores to the DPDK service framework when using the NTNIC PMD.
The code is also cleaned up to use pthreads and rte_thread APIs.
After this patch series, an each application using NTNIC PMD should
dedicate at least five(5) cores for DPDK service framework to ensure
proper operation of the NTNIC PMD.
The sercvice cores can be dedicated by EAL options:
* s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores
* S SERVICE CORELIST List of cores to run services on
Or with special API by application itself.
* rte_pmd_ntnic_service_set_lcore to map a service to a specific lcore
* rte_pmd_ntnic_service_get_id to get a service ID.
Serhii Iliushyk (7):
net/ntnic: introduce service API for NTNIC PMD
net/ntnic: migrate flm update thread to service
net/ntnic: migrate statistic thread to service
net/ntnic: migrate port event thread to service
net/ntnic: migrate adapter mon thread to service
net/ntnic: add warning about service cores
net/ntnic: cleanup using pthreads and rte_thread
doc/guides/nics/ntnic.rst | 112 ++++
drivers/net/ntnic/adapter/nt4ga_adapter.c | 27 +-
.../net/ntnic/include/common_adapter_defs.h | 15 -
drivers/net/ntnic/include/nt4ga_adapter.h | 4 -
drivers/net/ntnic/include/ntdrv_4ga.h | 4 -
drivers/net/ntnic/include/ntnic_stat.h | 2 +-
drivers/net/ntnic/include/ntos_drv.h | 4 +-
.../link_mgmt/link_100g/nt4ga_link_100g.c | 303 +++++-----
.../link_agx_100g/nt4ga_agx_link_100g.c | 306 ++++++-----
drivers/net/ntnic/meson.build | 2 +
drivers/net/ntnic/nthw/core/nthw_pca9532.c | 2 -
drivers/net/ntnic/nthw/core/nthw_pcal6416a.c | 1 -
.../net/ntnic/nthw/core/nthw_si5332_si5156.c | 1 -
.../profile_inline/flow_api_profile_inline.c | 2 +-
drivers/net/ntnic/ntnic_ethdev.c | 520 ++++++++++--------
drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 17 +
drivers/net/ntnic/ntutil/nt_service.c | 127 +++++
drivers/net/ntnic/ntutil/nt_service.h | 62 +++
drivers/net/ntnic/ntutil/nt_util.c | 2 +-
drivers/net/ntnic/rte_pmd_ntnic.c | 104 ++++
drivers/net/ntnic/rte_pmd_ntnic.h | 26 +
21 files changed, 1073 insertions(+), 570 deletions(-)
delete mode 100644 drivers/net/ntnic/include/common_adapter_defs.h
create mode 100644 drivers/net/ntnic/ntutil/nt_service.c
create mode 100644 drivers/net/ntnic/ntutil/nt_service.h
create mode 100644 drivers/net/ntnic/rte_pmd_ntnic.c
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 1/7] net/ntnic: introduce service API for NTNIC PMD
2025-09-08 11:04 [PATCH v1 0/7] migrate threads to DPDK service framework Serhii Iliushyk
@ 2025-09-08 11:04 ` Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 2/7] net/ntnic: migrate flm update thread to service Serhii Iliushyk
` (6 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 11:04 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This commit adds a common service API for the NTNIC PMD,
which includes functions for service management: add or delete a service
and retrieve information about a service.
The API is designed to facilitate the interaction with services within
the NTNIC driver, allowing for better control
and monitoring of service states.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
doc/guides/nics/ntnic.rst | 112 ++++++++++++++++++++++++++
drivers/net/ntnic/meson.build | 2 +
drivers/net/ntnic/ntutil/nt_service.c | 103 +++++++++++++++++++++++
drivers/net/ntnic/ntutil/nt_service.h | 62 ++++++++++++++
drivers/net/ntnic/rte_pmd_ntnic.c | 104 ++++++++++++++++++++++++
drivers/net/ntnic/rte_pmd_ntnic.h | 21 +++++
6 files changed, 404 insertions(+)
create mode 100644 drivers/net/ntnic/ntutil/nt_service.c
create mode 100644 drivers/net/ntnic/ntutil/nt_service.h
create mode 100644 drivers/net/ntnic/rte_pmd_ntnic.c
diff --git a/doc/guides/nics/ntnic.rst b/doc/guides/nics/ntnic.rst
index b3d6ad70c1..a173eaa2ac 100644
--- a/doc/guides/nics/ntnic.rst
+++ b/doc/guides/nics/ntnic.rst
@@ -185,3 +185,115 @@ There are list of characteristics that age timeout action has:
- after flow is aged-out it's not automatically deleted;
- aged-out flow can be updated with ``flow update`` command,
and its aged-out status will be reverted;
+
+Service API
+-----------
+
+**nthw_service_add**
+**nthw_service_del**
+**nthw_service_get_info**
+
+The NTNIC PMD provides a service API that allows applications to configure services
+
+The services are responsible for handling the vital functionality of the NTNIC PMD:
+
+- **FLM Update**: is responsible for creating and destroying flows;
+- **Statistics**: is responsible for collecting statistics;
+- **Port event**: is responsible for handling port events: aging, port load, and flow load;
+- **Adapter monitor** is responsible for link control;
+
+**NOTE**: Use next EAL options to configure set service cores
+ * -s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores;
+ * -S SERVICE CORELIST List of cores to run services on;
+
+**NOTE**: **At least 5 lcores must be reserved** for the ntnic services by EAL options. above.
+
+For example
+
+.. code-block:: console
+
+ dpdk-testpmd -S 8,9,10,11,12
+
+The PMD registers each service during initialization by function:
+
+.. code-block:: c
+
+ int nthw_service_add(struct rte_service_spec *srv_spec, const enum rte_ntnic_service_tag tag)
+
+and unregistered by the PMD during deinitialization by the function:
+
+.. code-block:: c
+
+ int nthw_service_del(const enum rte_ntnic_service_tag tag)
+
+The service info may be retrieved by function:
+
+.. code-block:: c
+
+ struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
+
+The service info includes the service ID, assigned lcore, and initialization state.
+
+Service API for user applications
+---------------------------------
+**rte_pmd_ntnic_service_set_lcore**
+**rte_pmd_ntnic_service_get_id**
+
+The exported service API is available for applications to configure the services.
+
+By API function:
+
+.. code-block:: c
+
+ int rte_pmd_ntnic_service_set_lcore(enum rte_ntnic_service_tag tag, uint32_t lcore_id)
+
+For example to assign lcores 8,9,10,11,12 to the services, the application can use:
+
+.. code-block:: c
+
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_STAT, 8);
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_ADAPTER_MON, 9);
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_PORT_0_EVENT, 10);
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_PORT_1_EVENT,11);
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_FLM_UPDATE, 12);
+
+The API will automatically lcore to service core list and map the service to the lcore.
+
+.. note:: Use `rte_service_lcore_start` to start the lcore after mapping it to the service.
+
+Each service has its own tag to identify it.
+
+.. code-block:: c
+
+ enum rte_ntnic_service_tag {
+ RTE_NTNIC_SERVICE_FLM_UPDATE = 0,
+ RTE_NTNIC_SERVICE_STAT = 1,
+ RTE_NTNIC_SERVICE_PORT_0_EVENT = 2,
+ RTE_NTNIC_SERVICE_PORT_1_EVENT = 3,
+ RTE_NTNIC_SERVICE_ADAPTER_MON = 4,
+ RTE_NTNIC_SERVICE_MAX
+ };
+
+The application may use next API function to retrieve the service id:
+
+.. code-block:: c
+
+ int rte_pmd_ntnic_service_get_id(enum rte_ntnic_service_tag tag);
+
+
+For example, to enable statistics for flm_update service, the application can use:
+
+.. code-block:: c
+
+ int flm_update_id = rte_pmd_ntnic_service_get_id(RTE_NTNIC_SERVICE_FLM_UPDATE);
+ rte_service_set_stats_enable(flm_update_id, 1);
+
+All other manipulations with the service can be done with the service ID and rte_service* API.
+
+To use the service API, an application must have included the header file:
+
+.. code-block:: c
+
+ #include <rte_pmd_ntnic.h>
+
+And linked with the library: `librte_net_ntnic.so` or `librte_net_ntnic.a` for static linking.
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index b4c6cfe7de..9467684f04 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -120,7 +120,9 @@ sources = files(
'ntlog/ntlog.c',
'ntnic_filter/ntnic_filter.c',
'ntutil/nt_util.c',
+ 'ntutil/nt_service.c',
'ntnic_mod_reg.c',
'ntnic_vfio.c',
'ntnic_ethdev.c',
+ 'rte_pmd_ntnic.c'
)
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
new file mode 100644
index 0000000000..4ef1233f12
--- /dev/null
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -0,0 +1,103 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2025 Napatech A/S
+ */
+
+#include <rte_service.h>
+#include <rte_cycles.h>
+
+#include "nt_service.h"
+#include "ntlog.h"
+
+#define NT_SERVICE_UNKNOWN_ID (-1)
+
+static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
+ [0] = {
+ .tag = RTE_NTNIC_SERVICE_MAX,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
+};
+
+inline struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
+{
+ if (tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX)
+ return NULL;
+
+ return &g_nt_services[tag];
+}
+
+int nthw_service_add(struct rte_service_spec *srv_spec, const enum rte_ntnic_service_tag tag)
+{
+ if (srv_spec == NULL || tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX) {
+ NT_LOG(ERR, NTNIC, "Invalid service specification or service tag");
+ return -1;
+ }
+
+ int ret = rte_service_component_register(srv_spec, &g_nt_services[tag].id);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to register service %s: error: %d",
+ srv_spec->name, ret);
+ return ret;
+ }
+
+ const uint32_t service_id = g_nt_services[tag].id;
+
+ NT_LOG(DBG, NTNIC, "Service %s registered with ID %u",
+ srv_spec->name, service_id);
+
+ rte_service_component_runstate_set(service_id, 1);
+
+ ret = rte_service_runstate_set(service_id, 1);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to start service %s: error: %d",
+ srv_spec->name, ret);
+ rte_service_component_unregister(service_id);
+ return ret;
+ }
+
+ return 0;
+}
+
+int nthw_service_del(const enum rte_ntnic_service_tag tag)
+{
+ if (tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX) {
+ NT_LOG(ERR, NTNIC, "Invalid service tag");
+ return -1;
+ }
+
+ struct nt_service *info = &g_nt_services[tag];
+
+ const char *service_name = rte_service_get_name(info->id);
+
+ rte_service_component_runstate_set(info->id, 0);
+
+ const uint32_t timeout_count = 10000;
+
+ for (uint32_t i = 0; i < timeout_count; i++) {
+ if (rte_service_may_be_active(info->id) == 0)
+ break;
+ rte_delay_ms(1);
+ }
+
+ int ret = rte_service_runstate_set(info->id, 0);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to stop service %s: error: %d",
+ service_name, ret);
+ return ret;
+ }
+
+ ret = rte_service_component_unregister(info->id);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to unregister service %s: error: %d",
+ service_name, ret);
+ return ret;
+ }
+
+ NT_LOG(DBG, NTNIC, "Service ID %d unregistered", info->id);
+
+ g_nt_services[tag].id = NT_SERVICE_UNKNOWN_ID;
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/ntutil/nt_service.h b/drivers/net/ntnic/ntutil/nt_service.h
new file mode 100644
index 0000000000..73c9076c2e
--- /dev/null
+++ b/drivers/net/ntnic/ntutil/nt_service.h
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2025 Napatech A/S
+ */
+
+#ifndef __NT_SERVICE_H__
+#define __NT_SERVICE_H__
+
+#include <stdint.h>
+#include <rte_service_component.h>
+#include <rte_stdatomic.h>
+#include <rte_pmd_ntnic.h>
+
+#define NT_SERVICE_GET_STATE(srv) \
+ rte_atomic_load_explicit(&(srv)->initialized, rte_memory_order_seq_cst)
+
+#define NT_SERVICE_SET_STATE(srv, state) \
+ rte_atomic_store_explicit(&(srv)->initialized, state, rte_memory_order_seq_cst)
+
+
+struct nt_service {
+ const enum rte_ntnic_service_tag tag;
+ uint32_t id;
+ uint32_t lcore;
+ RTE_ATOMIC(bool) initialized;
+};
+
+/**
+ * Get service information by tag.
+ *
+ * This function retrieves the service information based on the provided tag.
+ * It returns a pointer to the nt_service structure containing the service ID
+ * and other relevant information.
+ *
+ * @param tag The tag of the service to retrieve.
+ * @return Pointer to the nt_service structure or NULL if not found.
+ */
+struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag);
+
+/**
+ * Register and start a service with the specified tag.
+ *
+ * @srv_spec: Pointer to the service specification structure.
+ * @tag: Tag of the service to be registered.
+ *
+ * Returns 0 on success, or a negative error code on failure.
+ */
+int nthw_service_add(struct rte_service_spec *srv_spec, const enum rte_ntnic_service_tag tag);
+
+/**
+ * Unregisters a service by its tag.
+ *
+ * This function stops the service, waits for it to become inactive, and then
+ * unregisters it from the service component.
+ *
+ * @param tag The tag of the service to be unregistered.
+ * @return 0 on success, negative value on failure.
+ */
+
+int nthw_service_del(const enum rte_ntnic_service_tag tag);
+
+#endif /* __NT_SERVICE_H__ */
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.c b/drivers/net/ntnic/rte_pmd_ntnic.c
new file mode 100644
index 0000000000..fcc06a1ea0
--- /dev/null
+++ b/drivers/net/ntnic/rte_pmd_ntnic.c
@@ -0,0 +1,104 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2025 Napatech A/S
+ */
+
+#include <eal_export.h>
+#include <rte_service.h>
+#include <rte_pmd_ntnic.h>
+
+#include <stdint.h>
+
+#include "nt_service.h"
+#include "ntlog.h"
+
+static int nthw_service_is_mapped_to_lcore(enum rte_ntnic_service_tag tag)
+{
+ struct nt_service *service = nthw_service_get_info(tag);
+
+ uint32_t cores[RTE_MAX_LCORE] = {0};
+ int32_t lcore_count = rte_service_lcore_list(cores, RTE_MAX_LCORE);
+
+ for (int32_t i = 0; i < lcore_count; i++) {
+ if (rte_service_map_lcore_get(service->id, cores[i]))
+ return cores[i];
+ }
+ return RTE_MAX_LCORE;
+}
+
+
+RTE_EXPORT_SYMBOL(rte_pmd_ntnic_service_set_lcore)
+int rte_pmd_ntnic_service_set_lcore(enum rte_ntnic_service_tag tag, uint32_t lcore_id)
+{
+ if (tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX || lcore_id >= RTE_MAX_LCORE) {
+ NT_LOG(ERR, NTNIC, "Invalid service tag or lcore ID");
+ return -1;
+ }
+
+ struct nt_service *srv = nthw_service_get_info(tag);
+ const char *service_name = rte_service_get_name(srv->id);
+
+ uint32_t service_core = nthw_service_is_mapped_to_lcore(tag);
+
+ if (service_core != RTE_MAX_LCORE) {
+ NT_LOG(WRN, NTNIC, "Service %s[id=%u] is already mapped to lcore: %u", service_name,
+ srv->id, service_core);
+ /* Mapping by application has higher priority then 1:1 default mapping.
+ * Disable previous mapping and do remapping to new lcore.
+ */
+
+ rte_service_runstate_set(srv->id, 0);
+
+ NT_SERVICE_SET_STATE(srv, false);
+
+ int timeout_count = 10000;
+
+ while (rte_service_may_be_active(srv->id) != 0) {
+ if (--timeout_count <= 0) {
+ NT_LOG(ERR, NTNIC, "Failed to stop service %s[id=%d] on lcore %u",
+ service_name, srv->id, service_core);
+ return -1;
+ }
+ rte_delay_ms(1);
+ }
+
+ rte_service_map_lcore_set(srv->id, service_core, 0);
+ rte_service_runstate_set(srv->id, 1);
+ }
+
+ int ret = rte_service_lcore_add(lcore_id);
+ if (ret < 0 && ret != -EALREADY) {
+ NT_LOG(ERR, NTNIC, "Failed to add service lcore %u for service %s: error: %d",
+ lcore_id, service_name, ret);
+ return ret;
+ }
+
+ ret = rte_service_map_lcore_set(srv->id, lcore_id, 1);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to map service %s to lcore %u: error: %d",
+ service_name, lcore_id, ret);
+ return ret;
+ }
+
+ NT_LOG(DBG, NTNIC, "Service %s[id=%d] is mapped to lcore %u", service_name, srv->id,
+ lcore_id);
+
+ return 0;
+}
+
+RTE_EXPORT_SYMBOL(rte_pmd_ntnic_service_get_id)
+int rte_pmd_ntnic_service_get_id(enum rte_ntnic_service_tag tag)
+{
+ if (tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX) {
+ NT_LOG(ERR, NTNIC, "Invalid service tag");
+ return -1;
+ }
+
+ struct nt_service *service = nthw_service_get_info(tag);
+ if (service == NULL) {
+ NT_LOG(ERR, NTNIC, "Service with tag %d not found", tag);
+ return -1;
+ }
+
+ return service->id;
+}
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index 4a1ba18a5e..7a491319fa 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -40,4 +40,25 @@ enum rte_ntnic_event_type {
RTE_NTNIC_FLM_STATS_EVENT,
};
+enum rte_ntnic_service_tag {
+ RTE_NTNIC_SERVICE_MAX = 1
+};
+
+/**
+ * Set the lcore for a specific service.
+ *
+ * @param tag The service tag to set the lcore for.
+ * @param lcore_id The lcore ID to set for the service.
+ * @return 0 on success, negative value on failure.
+ */
+int rte_pmd_ntnic_service_set_lcore(enum rte_ntnic_service_tag tag, uint32_t lcore_id);
+
+/**
+ * Get the ID of a specific service.
+ *
+ * @param tag The service tag to get the ID for.
+ * @return The service ID on success, negative value on failure.
+ */
+int rte_pmd_ntnic_service_get_id(enum rte_ntnic_service_tag tag);
+
#endif /* NTNIC_EVENT_H_ */
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 2/7] net/ntnic: migrate flm update thread to service
2025-09-08 11:04 [PATCH v1 0/7] migrate threads to DPDK service framework Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 1/7] net/ntnic: introduce service API for NTNIC PMD Serhii Iliushyk
@ 2025-09-08 11:04 ` Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 3/7] net/ntnic: migrate statistic " Serhii Iliushyk
` (5 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 11:04 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This commit adds the FLM update service to the NTNIC PMD.
The service is responsible for handling creating/destroying flows.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/include/ntdrv_4ga.h | 1 -
drivers/net/ntnic/ntnic_ethdev.c | 67 ++++++++++++-------
drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 17 +++++
drivers/net/ntnic/ntutil/nt_service.c | 4 +-
drivers/net/ntnic/rte_pmd_ntnic.h | 3 +-
5 files changed, 62 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h
index 78cf10368a..35afcd546c 100644
--- a/drivers/net/ntnic/include/ntdrv_4ga.h
+++ b/drivers/net/ntnic/include/ntdrv_4ga.h
@@ -15,7 +15,6 @@ typedef struct ntdrv_4ga_s {
char *p_drv_name;
volatile bool b_shutdown;
- rte_thread_t flm_thread;
rte_spinlock_t stat_lck;
rte_thread_t stat_thread;
rte_thread_t port_event_thread;
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index 79ef9e7e7c..c114017db8 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -31,6 +31,7 @@
#include "profile_inline/flm_age_queue.h"
#include "profile_inline/flm_evt_queue.h"
#include "rte_pmd_ntnic.h"
+#include "nt_service.h"
const rte_thread_attr_t thread_attr = { .priority = RTE_THREAD_PRIORITY_NORMAL };
#define THREAD_CREATE(a, b, c) rte_thread_create(a, &thread_attr, b, c)
@@ -1546,7 +1547,7 @@ drv_deinit(struct drv_s *p_drv)
THREAD_JOIN(p_nt_drv->stat_thread);
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
- THREAD_JOIN(p_nt_drv->flm_thread);
+ nthw_service_del(RTE_NTNIC_SERVICE_FLM_UPDATE);
profile_inline_ops->flm_free_queues();
THREAD_JOIN(p_nt_drv->port_event_thread);
/* Free all local flm event queues */
@@ -1980,40 +1981,46 @@ THREAD_FUNC port_event_thread_fn(void *context)
}
/*
- * Adapter flm stat thread
+ * Adapter flm update service
*/
-THREAD_FUNC adapter_flm_update_thread_fn(void *context)
+static int adapter_flm_update_service(void *context)
{
- const struct profile_inline_ops *profile_inline_ops = get_profile_inline_ops();
+ static struct flow_eth_dev *dev;
+ static const struct profile_inline_ops *profile_inline_ops;
- if (profile_inline_ops == NULL) {
- NT_LOG(ERR, NTNIC, "%s: profile_inline module uninitialized", __func__);
- return THREAD_RETURN;
- }
+ struct nt_service *flm_update_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_FLM_UPDATE);
+ RTE_ASSERT(flm_update_srv != NULL);
- struct drv_s *p_drv = context;
+ if (!NT_SERVICE_GET_STATE(flm_update_srv)) {
+ struct drv_s *p_drv = context;
+ RTE_ASSERT(p_drv != NULL);
- struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
- struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info;
- struct nt4ga_filter_s *p_nt4ga_filter = &p_adapter_info->nt4ga_filter;
- struct flow_nic_dev *p_flow_nic_dev = p_nt4ga_filter->mp_flow_device;
+ struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
+ struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info;
+ struct nt4ga_filter_s *p_nt4ga_filter = &p_adapter_info->nt4ga_filter;
+ struct flow_nic_dev *p_flow_nic_dev = p_nt4ga_filter->mp_flow_device;
- NT_LOG(DBG, NTNIC, "%s: %s: waiting for port configuration",
- p_adapter_info->mp_adapter_id_str, __func__);
+ NT_LOG(DBG, NTNIC, "%s: %s: waiting for port configuration",
+ p_adapter_info->mp_adapter_id_str, __func__);
- while (p_flow_nic_dev->eth_base == NULL)
- nt_os_wait_usec(1 * 1000 * 1000);
+ if (p_flow_nic_dev->eth_base == NULL)
+ return -1;
- struct flow_eth_dev *dev = p_flow_nic_dev->eth_base;
+ dev = p_flow_nic_dev->eth_base;
- NT_LOG(DBG, NTNIC, "%s: %s: begin", p_adapter_info->mp_adapter_id_str, __func__);
+ profile_inline_ops = get_profile_inline_ops();
+ RTE_ASSERT(profile_inline_ops != NULL);
- while (!p_drv->ntdrv.b_shutdown)
- if (profile_inline_ops->flm_update(dev) == 0)
- nt_os_wait_usec(10);
+ NT_LOG(INF, NTNIC, "flm update service started on lcore %i", rte_lcore_id());
+ flm_update_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(flm_update_srv, true);
+ return 0;
+ }
- NT_LOG(DBG, NTNIC, "%s: %s: end", p_adapter_info->mp_adapter_id_str, __func__);
- return THREAD_RETURN;
+ if (profile_inline_ops->flm_update(dev) == 0)
+ nt_os_wait_usec(10);
+
+ return 0;
}
/*
@@ -2346,8 +2353,16 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
if (profile_inline_ops != NULL && fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
profile_inline_ops->flm_setup_queues();
- res = THREAD_CTRL_CREATE(&p_nt_drv->flm_thread, "ntnic-nt_flm_update_thr",
- adapter_flm_update_thread_fn, (void *)p_drv);
+
+ struct rte_service_spec flm_update_spec = {
+ .name = "ntnic-flm_update_service",
+ .callback = adapter_flm_update_service,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = p_drv
+ };
+
+ res = nthw_service_add(&flm_update_spec, RTE_NTNIC_SERVICE_FLM_UPDATE);
if (res) {
NT_LOG_DBGX(ERR, NTNIC, "%s: error=%d",
diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
index fc06cf12c3..c6c448312f 100644
--- a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
+++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
@@ -6,6 +6,7 @@
#include <rte_flow_driver.h>
#include <rte_pci.h>
#include <rte_version.h>
+#include <rte_pmd_ntnic.h>
#include "ntlog.h"
#include "nt_util.h"
@@ -13,6 +14,8 @@
#include "ntnic_mod_reg.h"
#include "ntos_system.h"
#include "ntos_drv.h"
+#include "nt_service.h"
+#include "rte_service.h"
#define MAX_RTE_FLOWS 8192
@@ -543,6 +546,13 @@ eth_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *flow, struct rte_
return -1;
}
+ struct nt_service *srv = nthw_service_get_info(RTE_NTNIC_SERVICE_FLM_UPDATE);
+
+ if (!srv || !NT_SERVICE_GET_STATE(srv) || !rte_service_runstate_get(srv->id)) {
+ NT_LOG(ERR, FILTER, "flm update service is not started. Flow cannot be destroyed");
+ return -1;
+ }
+
struct pmd_internals *internals = eth_dev->data->dev_private;
error->type = RTE_FLOW_ERROR_TYPE_NONE;
@@ -580,6 +590,13 @@ static struct rte_flow *eth_flow_create(struct rte_eth_dev *eth_dev,
return NULL;
}
+ struct nt_service *srv = nthw_service_get_info(RTE_NTNIC_SERVICE_FLM_UPDATE);
+
+ if (!srv || !NT_SERVICE_GET_STATE(srv) || !rte_service_runstate_get(srv->id)) {
+ NT_LOG(ERR, FILTER, "flm update service is not started. Flow cannot be created");
+ return NULL;
+ }
+
struct pmd_internals *internals = eth_dev->data->dev_private;
struct fpga_info_s *fpga_info = &internals->p_drv->ntdrv.adapter_info.fpga_info;
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
index 4ef1233f12..86f709e401 100644
--- a/drivers/net/ntnic/ntutil/nt_service.c
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -12,8 +12,8 @@
#define NT_SERVICE_UNKNOWN_ID (-1)
static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
- [0] = {
- .tag = RTE_NTNIC_SERVICE_MAX,
+ [RTE_NTNIC_SERVICE_FLM_UPDATE] = {
+ .tag = RTE_NTNIC_SERVICE_FLM_UPDATE,
.id = NT_SERVICE_UNKNOWN_ID,
.lcore = RTE_MAX_LCORE,
.initialized = false,
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index 7a491319fa..d6236dae32 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -41,7 +41,8 @@ enum rte_ntnic_event_type {
};
enum rte_ntnic_service_tag {
- RTE_NTNIC_SERVICE_MAX = 1
+ RTE_NTNIC_SERVICE_FLM_UPDATE = 0,
+ RTE_NTNIC_SERVICE_MAX
};
/**
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 3/7] net/ntnic: migrate statistic thread to service
2025-09-08 11:04 [PATCH v1 0/7] migrate threads to DPDK service framework Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 1/7] net/ntnic: introduce service API for NTNIC PMD Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 2/7] net/ntnic: migrate flm update thread to service Serhii Iliushyk
@ 2025-09-08 11:04 ` Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 4/7] net/ntnic: migrate port event " Serhii Iliushyk
` (4 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 11:04 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
The statistic service is responsible for collecting statistics.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/include/ntdrv_4ga.h | 1 -
drivers/net/ntnic/ntnic_ethdev.c | 146 ++++++++++++++------------
drivers/net/ntnic/ntutil/nt_service.c | 6 ++
drivers/net/ntnic/rte_pmd_ntnic.h | 1 +
4 files changed, 84 insertions(+), 70 deletions(-)
diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h
index 35afcd546c..c143c0c2b6 100644
--- a/drivers/net/ntnic/include/ntdrv_4ga.h
+++ b/drivers/net/ntnic/include/ntdrv_4ga.h
@@ -16,7 +16,6 @@ typedef struct ntdrv_4ga_s {
volatile bool b_shutdown;
rte_spinlock_t stat_lck;
- rte_thread_t stat_thread;
rte_thread_t port_event_thread;
} ntdrv_4ga_t;
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index c114017db8..54c9e218bc 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -1542,9 +1542,9 @@ drv_deinit(struct drv_s *p_drv)
clear_pdrv(p_drv);
nt_os_wait_usec(1000000);
- /* stop statistics threads */
+ /* stop statistics service */
p_drv->ntdrv.b_shutdown = true;
- THREAD_JOIN(p_nt_drv->stat_thread);
+ nthw_service_del(RTE_NTNIC_SERVICE_STAT);
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
nthw_service_del(RTE_NTNIC_SERVICE_FLM_UPDATE);
@@ -2024,84 +2024,86 @@ static int adapter_flm_update_service(void *context)
}
/*
- * Adapter stat thread
+ * Adapter stat service
*/
-THREAD_FUNC adapter_stat_thread_fn(void *context)
+static int adapter_stat_service(void *context)
{
- const struct nt4ga_stat_ops *nt4ga_stat_ops = get_nt4ga_stat_ops();
+ static struct ntdrv_4ga_s *p_nt_drv;
+ static nt4ga_stat_t *p_nt4ga_stat;
+ static nthw_stat_t *p_nthw_stat;
+ static const struct nt4ga_stat_ops *nt4ga_stat_ops;
- if (nt4ga_stat_ops == NULL) {
- NT_LOG_DBGX(ERR, NTNIC, "Statistics module uninitialized");
- return THREAD_RETURN;
- }
+ struct nt_service *stat_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_STAT);
+ RTE_ASSERT(stat_srv != NULL);
- struct drv_s *p_drv = context;
+ if (!NT_SERVICE_GET_STATE(stat_srv)) {
+ struct drv_s *p_drv = context;
+ RTE_ASSERT(p_drv != NULL);
- ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
- nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
- nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
- const char *const p_adapter_id_str = p_nt_drv->adapter_info.mp_adapter_id_str;
- (void)p_adapter_id_str;
+ nt4ga_stat_ops = get_nt4ga_stat_ops();
+ RTE_ASSERT(nt4ga_stat_ops != NULL);
- if (!p_nthw_stat)
- return THREAD_RETURN;
+ p_nt_drv = &p_drv->ntdrv;
+ p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
- NT_LOG_DBGX(DBG, NTNIC, "%s: begin", p_adapter_id_str);
+ if (!p_nthw_stat)
+ return 0;
- RTE_ASSERT(p_nthw_stat);
+ NT_LOG(INF, NTNIC, "statistic service started on lcore %u", rte_lcore_id());
+ stat_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(stat_srv, true);
+ return 0;
+ }
- while (!p_drv->ntdrv.b_shutdown) {
- nt_os_wait_usec(10 * 1000);
-
- nthw_stat_trigger(p_nthw_stat);
-
- uint32_t loop = 0;
-
- while ((!p_drv->ntdrv.b_shutdown) &&
- (*p_nthw_stat->mp_timestamp == (uint64_t)-1)) {
- nt_os_wait_usec(1 * 100);
-
- if (rte_log_get_level(nt_log_ntnic) == RTE_LOG_DEBUG &&
- (++loop & 0x3fff) == 0) {
- if (p_nt4ga_stat->mp_nthw_rpf) {
- NT_LOG(ERR, NTNIC, "Statistics DMA frozen");
-
- } else if (p_nt4ga_stat->mp_nthw_rmc) {
- uint32_t sf_ram_of =
- nthw_rmc_get_status_sf_ram_of(p_nt4ga_stat
- ->mp_nthw_rmc);
- uint32_t descr_fifo_of =
- nthw_rmc_get_status_descr_fifo_of(p_nt4ga_stat
- ->mp_nthw_rmc);
-
- uint32_t dbg_merge =
- nthw_rmc_get_dbg_merge(p_nt4ga_stat->mp_nthw_rmc);
- uint32_t mac_if_err =
- nthw_rmc_get_mac_if_err(p_nt4ga_stat->mp_nthw_rmc);
-
- NT_LOG(ERR, NTNIC, "Statistics DMA frozen");
- NT_LOG(ERR, NTNIC, "SF RAM Overflow : %08x",
- sf_ram_of);
- NT_LOG(ERR, NTNIC, "Descr Fifo Overflow : %08x",
- descr_fifo_of);
- NT_LOG(ERR, NTNIC, "DBG Merge : %08x",
- dbg_merge);
- NT_LOG(ERR, NTNIC, "MAC If Errors : %08x",
- mac_if_err);
- }
+ nt_os_wait_usec(10 * 1000);
+
+ nthw_stat_trigger(p_nthw_stat);
+
+ uint32_t loop = 0;
+
+ while (rte_service_runstate_get(stat_srv->id) &&
+ (*p_nthw_stat->mp_timestamp == (uint64_t)-1)) {
+ nt_os_wait_usec(1 * 100);
+
+ if ((++loop & 0x3fff) == 0) {
+ if (p_nt4ga_stat->mp_nthw_rpf) {
+ NT_LOG(DBG, NTNIC, "Statistics DMA frozen");
+
+ } else if (p_nt4ga_stat->mp_nthw_rmc) {
+ uint32_t sf_ram_of =
+ nthw_rmc_get_status_sf_ram_of(p_nt4ga_stat
+ ->mp_nthw_rmc);
+ uint32_t descr_fifo_of =
+ nthw_rmc_get_status_descr_fifo_of(p_nt4ga_stat
+ ->mp_nthw_rmc);
+
+ uint32_t dbg_merge =
+ nthw_rmc_get_dbg_merge(p_nt4ga_stat->mp_nthw_rmc);
+ uint32_t mac_if_err =
+ nthw_rmc_get_mac_if_err(p_nt4ga_stat->mp_nthw_rmc);
+
+ NT_LOG(DBG, NTNIC, "Statistics DMA frozen");
+ NT_LOG(DBG, NTNIC, "SF RAM Overflow : %08x",
+ sf_ram_of);
+ NT_LOG(DBG, NTNIC, "Descr Fifo Overflow : %08x",
+ descr_fifo_of);
+ NT_LOG(DBG, NTNIC, "DBG Merge : %08x",
+ dbg_merge);
+ NT_LOG(DBG, NTNIC, "MAC If Errors : %08x",
+ mac_if_err);
}
}
+ }
- /* Check then collect */
- {
- rte_spinlock_lock(&p_nt_drv->stat_lck);
- nt4ga_stat_ops->nt4ga_stat_collect(&p_nt_drv->adapter_info, p_nt4ga_stat);
- rte_spinlock_unlock(&p_nt_drv->stat_lck);
- }
+ /* Check then collect */
+ {
+ rte_spinlock_lock(&p_nt_drv->stat_lck);
+ nt4ga_stat_ops->nt4ga_stat_collect(&p_nt_drv->adapter_info, p_nt4ga_stat);
+ rte_spinlock_unlock(&p_nt_drv->stat_lck);
}
- NT_LOG_DBGX(DBG, NTNIC, "%s: end", p_adapter_id_str);
- return THREAD_RETURN;
+ return 0;
}
static int
@@ -2371,9 +2373,15 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
}
}
- rte_spinlock_init(&p_nt_drv->stat_lck);
- res = THREAD_CTRL_CREATE(&p_nt_drv->stat_thread, "nt4ga_stat_thr", adapter_stat_thread_fn,
- (void *)p_drv);
+ struct rte_service_spec stat_spec = {
+ .name = "ntnic-stat_collect_service",
+ .callback = adapter_stat_service,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = p_drv
+ };
+
+ res = nthw_service_add(&stat_spec, RTE_NTNIC_SERVICE_STAT);
if (res) {
NT_LOG(ERR, NTNIC, "%s: error=%d",
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
index 86f709e401..c109b44483 100644
--- a/drivers/net/ntnic/ntutil/nt_service.c
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -18,6 +18,12 @@ static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
.lcore = RTE_MAX_LCORE,
.initialized = false,
},
+ [RTE_NTNIC_SERVICE_STAT] = {
+ .tag = RTE_NTNIC_SERVICE_STAT,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
};
inline struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index d6236dae32..6fe6541984 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -42,6 +42,7 @@ enum rte_ntnic_event_type {
enum rte_ntnic_service_tag {
RTE_NTNIC_SERVICE_FLM_UPDATE = 0,
+ RTE_NTNIC_SERVICE_STAT = 1,
RTE_NTNIC_SERVICE_MAX
};
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 4/7] net/ntnic: migrate port event thread to service
2025-09-08 11:04 [PATCH v1 0/7] migrate threads to DPDK service framework Serhii Iliushyk
` (2 preceding siblings ...)
2025-09-08 11:04 ` [PATCH v1 3/7] net/ntnic: migrate statistic " Serhii Iliushyk
@ 2025-09-08 11:04 ` Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 5/7] net/ntnic: migrate adapter mon " Serhii Iliushyk
` (3 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 11:04 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
The port event service is responsible for handling port events.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/include/ntdrv_4ga.h | 1 -
drivers/net/ntnic/include/ntos_drv.h | 2 +-
drivers/net/ntnic/ntnic_ethdev.c | 271 +++++++++++++++-----------
drivers/net/ntnic/ntutil/nt_service.c | 12 ++
drivers/net/ntnic/rte_pmd_ntnic.h | 2 +
5 files changed, 174 insertions(+), 114 deletions(-)
diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h
index c143c0c2b6..ee0e66c4d4 100644
--- a/drivers/net/ntnic/include/ntdrv_4ga.h
+++ b/drivers/net/ntnic/include/ntdrv_4ga.h
@@ -16,7 +16,6 @@ typedef struct ntdrv_4ga_s {
volatile bool b_shutdown;
rte_spinlock_t stat_lck;
- rte_thread_t port_event_thread;
} ntdrv_4ga_t;
#endif /* __NTDRV_4GA_H__ */
diff --git a/drivers/net/ntnic/include/ntos_drv.h b/drivers/net/ntnic/include/ntos_drv.h
index 047c077057..e6e46f8cc1 100644
--- a/drivers/net/ntnic/include/ntos_drv.h
+++ b/drivers/net/ntnic/include/ntos_drv.h
@@ -21,7 +21,7 @@
#define NUM_MULTICAST_ADDRS_PER_PORT (16U)
#define NUM_ADAPTER_MAX (8)
-#define NUM_ADAPTER_PORTS_MAX (128)
+#define NUM_ADAPTER_PORTS_MAX (2)
/* Max RSS queues */
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index 54c9e218bc..7ec1c94a14 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -1549,7 +1549,8 @@ drv_deinit(struct drv_s *p_drv)
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
nthw_service_del(RTE_NTNIC_SERVICE_FLM_UPDATE);
profile_inline_ops->flm_free_queues();
- THREAD_JOIN(p_nt_drv->port_event_thread);
+ nthw_service_del(RTE_NTNIC_SERVICE_PORT_0_EVENT);
+ nthw_service_del(RTE_NTNIC_SERVICE_PORT_1_EVENT);
/* Free all local flm event queues */
nthw_flm_inf_sta_queue_free_all(FLM_INFO_LOCAL);
/* Free all remote flm event queues */
@@ -1849,135 +1850,168 @@ static struct eth_dev_ops nthw_eth_dev_ops = {
};
/*
- * Port event thread
+ * Port event service
*/
-THREAD_FUNC port_event_thread_fn(void *context)
+static int port_event_service(void *context)
{
struct pmd_internals *internals = context;
- struct drv_s *p_drv = internals->p_drv;
- ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
- struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info;
- struct flow_nic_dev *ndev = p_adapter_info->nt4ga_filter.mp_flow_device;
+ RTE_ASSERT(internals != NULL);
- nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
- struct rte_eth_dev *eth_dev = &rte_eth_devices[internals->port_id];
- uint8_t port_no = internals->port;
+ const uint8_t port_no = internals->port;
+ if (port_no >= NUM_ADAPTER_PORTS_MAX) {
+ NT_LOG(ERR, NTNIC, "Invalid Port number");
+ return -1;
+ }
- ntnic_flm_load_t flmdata;
- ntnic_port_load_t portdata;
+ static ntdrv_4ga_t *p_nt_drv[NUM_ADAPTER_PORTS_MAX] = {NULL, NULL};
+ static struct rte_eth_dev *eth_dev[NUM_ADAPTER_PORTS_MAX] = {NULL, NULL};
+ static nt4ga_stat_t *p_nt4ga_stat[NUM_ADAPTER_PORTS_MAX] = {NULL, NULL};
+ static ntnic_flm_load_t flmdata[NUM_ADAPTER_PORTS_MAX];
+ static ntnic_port_load_t portdata[NUM_ADAPTER_PORTS_MAX];
- memset(&flmdata, 0, sizeof(flmdata));
- memset(&portdata, 0, sizeof(portdata));
+ const int port_srv_tag[2] = {
+ RTE_NTNIC_SERVICE_PORT_0_EVENT,
+ RTE_NTNIC_SERVICE_PORT_1_EVENT
+ };
- while (ndev != NULL && ndev->eth_base == NULL)
- nt_os_wait_usec(1 * 1000 * 1000);
+ struct nt_service *port_event_srv = nthw_service_get_info(port_srv_tag[port_no]);
+ RTE_ASSERT(port_event_srv != NULL);
+
+ if (!NT_SERVICE_GET_STATE(port_event_srv)) {
+ struct drv_s *p_drv = internals->p_drv;
+ p_nt_drv[port_no] = &p_drv->ntdrv;
+ struct adapter_info_s *p_adapter_info = &p_nt_drv[port_no]->adapter_info;
+ struct flow_nic_dev *ndev = p_adapter_info->nt4ga_filter.mp_flow_device;
+ p_nt4ga_stat[port_no] = &p_nt_drv[port_no]->adapter_info.nt4ga_stat;
+ eth_dev[port_no] = &rte_eth_devices[internals->port_id];
+ if (ndev != NULL && ndev->eth_base == NULL)
+ return -1;
- while (!p_drv->ntdrv.b_shutdown) {
- /*
- * FLM load measurement
- * Do only send event, if there has been a change
- */
- if (p_nt4ga_stat->flm_stat_ver > 22 && p_nt4ga_stat->mp_stat_structs_flm) {
- if (flmdata.lookup != p_nt4ga_stat->mp_stat_structs_flm->load_lps ||
- flmdata.access != p_nt4ga_stat->mp_stat_structs_flm->load_aps) {
- rte_spinlock_lock(&p_nt_drv->stat_lck);
- flmdata.lookup = p_nt4ga_stat->mp_stat_structs_flm->load_lps;
- flmdata.access = p_nt4ga_stat->mp_stat_structs_flm->load_aps;
- flmdata.lookup_maximum =
- p_nt4ga_stat->mp_stat_structs_flm->max_lps;
- flmdata.access_maximum =
- p_nt4ga_stat->mp_stat_structs_flm->max_aps;
- rte_spinlock_unlock(&p_nt_drv->stat_lck);
-
- if (eth_dev && eth_dev->data && eth_dev->data->dev_private) {
- rte_eth_dev_callback_process(eth_dev,
- (enum rte_eth_event_type)RTE_NTNIC_FLM_LOAD_EVENT,
- &flmdata);
- }
+ memset(&flmdata, 0, sizeof(flmdata));
+ memset(&portdata, 0, sizeof(portdata));
+
+
+ NT_LOG(INF, NTNIC, "port[%u] event service started on lcore %i",
+ port_no, rte_lcore_id());
+ port_event_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(port_event_srv, true);
+ return 0;
+ }
+
+ /*
+ * FLM load measurement
+ * Do only send event, if there has been a change
+ */
+
+ nt4ga_stat_t *port_stat = p_nt4ga_stat[port_no];
+ ntnic_flm_load_t *port_flm_load = &flmdata[port_no];
+ ntnic_port_load_t *port_load = &portdata[port_no];
+
+ if (port_stat->flm_stat_ver > 22 && port_stat->mp_stat_structs_flm) {
+ if (port_flm_load->lookup != port_stat->mp_stat_structs_flm->load_lps ||
+ port_flm_load->access != port_stat->mp_stat_structs_flm->load_aps) {
+ rte_spinlock_lock(&p_nt_drv[port_no]->stat_lck);
+ port_flm_load->lookup = port_stat->mp_stat_structs_flm->load_lps;
+ port_flm_load->access = port_stat->mp_stat_structs_flm->load_aps;
+ port_flm_load->lookup_maximum =
+ port_stat->mp_stat_structs_flm->max_lps;
+ port_flm_load->access_maximum =
+ port_stat->mp_stat_structs_flm->max_aps;
+ rte_spinlock_unlock(&p_nt_drv[port_no]->stat_lck);
+
+ if (eth_dev[port_no] &&
+ eth_dev[port_no]->data &&
+ eth_dev[port_no]->data->dev_private) {
+ rte_eth_dev_callback_process(eth_dev[port_no],
+ (enum rte_eth_event_type)RTE_NTNIC_FLM_LOAD_EVENT,
+ &flmdata);
}
}
+ }
- /*
- * Port load measurement
- * Do only send event, if there has been a change.
- */
- if (p_nt4ga_stat->mp_port_load) {
- if (portdata.rx_bps != p_nt4ga_stat->mp_port_load[port_no].rx_bps ||
- portdata.tx_bps != p_nt4ga_stat->mp_port_load[port_no].tx_bps) {
- rte_spinlock_lock(&p_nt_drv->stat_lck);
- portdata.rx_bps = p_nt4ga_stat->mp_port_load[port_no].rx_bps;
- portdata.tx_bps = p_nt4ga_stat->mp_port_load[port_no].tx_bps;
- portdata.rx_pps = p_nt4ga_stat->mp_port_load[port_no].rx_pps;
- portdata.tx_pps = p_nt4ga_stat->mp_port_load[port_no].tx_pps;
- portdata.rx_pps_maximum =
- p_nt4ga_stat->mp_port_load[port_no].rx_pps_max;
- portdata.tx_pps_maximum =
- p_nt4ga_stat->mp_port_load[port_no].tx_pps_max;
- portdata.rx_bps_maximum =
- p_nt4ga_stat->mp_port_load[port_no].rx_bps_max;
- portdata.tx_bps_maximum =
- p_nt4ga_stat->mp_port_load[port_no].tx_bps_max;
- rte_spinlock_unlock(&p_nt_drv->stat_lck);
-
- if (eth_dev && eth_dev->data && eth_dev->data->dev_private) {
- rte_eth_dev_callback_process(eth_dev,
- (enum rte_eth_event_type)RTE_NTNIC_PORT_LOAD_EVENT,
- &portdata);
- }
+ /*
+ * Port load measurement
+ * Do only send event, if there has been a change.
+ */
+ if (port_stat->mp_port_load) {
+ if (port_load->rx_bps != port_stat->mp_port_load[port_no].rx_bps ||
+ port_load->tx_bps != port_stat->mp_port_load[port_no].tx_bps) {
+ rte_spinlock_lock(&p_nt_drv[port_no]->stat_lck);
+ port_load->rx_bps = port_stat->mp_port_load[port_no].rx_bps;
+ port_load->tx_bps = port_stat->mp_port_load[port_no].tx_bps;
+ port_load->rx_pps = port_stat->mp_port_load[port_no].rx_pps;
+ port_load->tx_pps = port_stat->mp_port_load[port_no].tx_pps;
+ port_load->rx_pps_maximum =
+ port_stat->mp_port_load[port_no].rx_pps_max;
+ port_load->tx_pps_maximum =
+ port_stat->mp_port_load[port_no].tx_pps_max;
+ port_load->rx_bps_maximum =
+ port_stat->mp_port_load[port_no].rx_bps_max;
+ port_load->tx_bps_maximum =
+ port_stat->mp_port_load[port_no].tx_bps_max;
+ rte_spinlock_unlock(&p_nt_drv[port_no]->stat_lck);
+
+ if (eth_dev[port_no] && eth_dev[port_no]->data &&
+ eth_dev[port_no]->data->dev_private) {
+ rte_eth_dev_callback_process(eth_dev[port_no],
+ (enum rte_eth_event_type)RTE_NTNIC_PORT_LOAD_EVENT,
+ &portdata);
}
}
+ }
- /* Process events */
- {
- int count = 0;
- bool do_wait = true;
-
- while (count < 5000) {
- /* Local FLM statistic events */
- struct flm_info_event_s data;
-
- if (nthw_flm_inf_queue_get(port_no, FLM_INFO_LOCAL, &data) == 0) {
- if (eth_dev && eth_dev->data &&
- eth_dev->data->dev_private) {
- struct ntnic_flm_statistic_s event_data;
- event_data.bytes = data.bytes;
- event_data.packets = data.packets;
- event_data.cause = data.cause;
- event_data.id = data.id;
- event_data.timestamp = data.timestamp;
- rte_eth_dev_callback_process(eth_dev,
- (enum rte_eth_event_type)
- RTE_NTNIC_FLM_STATS_EVENT,
- &event_data);
- do_wait = false;
- }
- }
-
- /* AGED event */
- /* Note: RTE_FLOW_PORT_FLAG_STRICT_QUEUE flag is not supported so
- * event is always generated
- */
- int aged_event_count = flm_age_event_get(port_no);
-
- if (aged_event_count > 0 && eth_dev && eth_dev->data &&
- eth_dev->data->dev_private) {
- rte_eth_dev_callback_process(eth_dev,
- RTE_ETH_EVENT_FLOW_AGED,
- NULL);
- flm_age_event_clear(port_no);
+ /* Process events */
+ {
+ int count = 0;
+ bool do_wait = true;
+
+ while (count < 5000) {
+ /* Local FLM statistic events */
+ struct flm_info_event_s data;
+
+ if (nthw_flm_inf_queue_get(port_no, FLM_INFO_LOCAL, &data) == 0) {
+ if (eth_dev[port_no] && eth_dev[port_no]->data &&
+ eth_dev[port_no]->data->dev_private) {
+ struct ntnic_flm_statistic_s event_data;
+ event_data.bytes = data.bytes;
+ event_data.packets = data.packets;
+ event_data.cause = data.cause;
+ event_data.id = data.id;
+ event_data.timestamp = data.timestamp;
+ rte_eth_dev_callback_process(eth_dev[port_no],
+ (enum rte_eth_event_type)
+ RTE_NTNIC_FLM_STATS_EVENT,
+ &event_data);
do_wait = false;
}
+ }
- if (do_wait)
- nt_os_wait_usec(10);
-
- count++;
- do_wait = true;
+ /* AGED event */
+ /* Note: RTE_FLOW_PORT_FLAG_STRICT_QUEUE flag is not supported so
+ * event is always generated
+ */
+ int aged_event_count = flm_age_event_get(port_no);
+
+ if (aged_event_count > 0 &&
+ eth_dev[port_no] &&
+ eth_dev[port_no]->data &&
+ eth_dev[port_no]->data->dev_private) {
+ rte_eth_dev_callback_process(eth_dev[port_no],
+ RTE_ETH_EVENT_FLOW_AGED,
+ NULL);
+ flm_age_event_clear(port_no);
+ do_wait = false;
}
+
+ if (do_wait)
+ nt_os_wait_usec(10);
+
+ count++;
+ do_wait = true;
}
}
- return THREAD_RETURN;
+ return 0;
}
/*
@@ -2547,10 +2581,23 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
}
}
- /* Port event thread */
+ /* Port event service */
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
- res = THREAD_CTRL_CREATE(&p_nt_drv->port_event_thread, "nt_port_event_thr",
- port_event_thread_fn, (void *)internals);
+ struct rte_service_spec port_event_spec = {
+ .callback = port_event_service,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = internals
+ };
+
+ sprintf(port_event_spec.name, "ntnic-port_%d_event_service", n_intf_no);
+
+ const int port_srv_tag[2] = {
+ RTE_NTNIC_SERVICE_PORT_0_EVENT,
+ RTE_NTNIC_SERVICE_PORT_1_EVENT
+ };
+
+ res = nthw_service_add(&port_event_spec, port_srv_tag[n_intf_no]);
if (res) {
NT_LOG(ERR, NTNIC, "%s: error=%d",
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
index c109b44483..9f22ee2bba 100644
--- a/drivers/net/ntnic/ntutil/nt_service.c
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -24,6 +24,18 @@ static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
.lcore = RTE_MAX_LCORE,
.initialized = false,
},
+ [RTE_NTNIC_SERVICE_PORT_0_EVENT] = {
+ .tag = RTE_NTNIC_SERVICE_PORT_0_EVENT,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
+ [RTE_NTNIC_SERVICE_PORT_1_EVENT] = {
+ .tag = RTE_NTNIC_SERVICE_PORT_1_EVENT,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
};
inline struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index 6fe6541984..1a68cb8e37 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -43,6 +43,8 @@ enum rte_ntnic_event_type {
enum rte_ntnic_service_tag {
RTE_NTNIC_SERVICE_FLM_UPDATE = 0,
RTE_NTNIC_SERVICE_STAT = 1,
+ RTE_NTNIC_SERVICE_PORT_0_EVENT = 2,
+ RTE_NTNIC_SERVICE_PORT_1_EVENT = 3,
RTE_NTNIC_SERVICE_MAX
};
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 5/7] net/ntnic: migrate adapter mon thread to service
2025-09-08 11:04 [PATCH v1 0/7] migrate threads to DPDK service framework Serhii Iliushyk
` (3 preceding siblings ...)
2025-09-08 11:04 ` [PATCH v1 4/7] net/ntnic: migrate port event " Serhii Iliushyk
@ 2025-09-08 11:04 ` Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 6/7] net/ntnic: add warning about service cores Serhii Iliushyk
` (2 subsequent siblings)
7 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 11:04 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
The adapter monitor service is responsible for link state management.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/adapter/nt4ga_adapter.c | 25 +-
.../net/ntnic/include/common_adapter_defs.h | 15 -
drivers/net/ntnic/include/nt4ga_adapter.h | 3 -
drivers/net/ntnic/include/ntnic_stat.h | 2 +-
drivers/net/ntnic/include/ntos_drv.h | 2 +-
.../link_mgmt/link_100g/nt4ga_link_100g.c | 303 +++++++++--------
.../link_agx_100g/nt4ga_agx_link_100g.c | 306 ++++++++++--------
drivers/net/ntnic/ntutil/nt_service.c | 6 +
drivers/net/ntnic/rte_pmd_ntnic.h | 1 +
9 files changed, 334 insertions(+), 329 deletions(-)
delete mode 100644 drivers/net/ntnic/include/common_adapter_defs.h
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c
index 526ecc8089..363874c85f 100644
--- a/drivers/net/ntnic/adapter/nt4ga_adapter.c
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c
@@ -5,6 +5,7 @@
#include <rte_thread.h>
+#include "nt_service.h"
#include "ntlog.h"
#include "nthw_fpga.h"
#include "ntnic_mod_reg.h"
@@ -12,28 +13,6 @@
/*
* Global variables shared by NT adapter types
*/
-rte_thread_t monitor_tasks[NUM_ADAPTER_MAX];
-volatile int monitor_task_is_running[NUM_ADAPTER_MAX];
-
-/*
- * Signal-handler to stop all monitor threads
- */
-static void stop_monitor_tasks(int signum)
-{
- const size_t N = ARRAY_SIZE(monitor_task_is_running);
- size_t i;
-
- /* Stop all monitor tasks */
- for (i = 0; i < N; i++) {
- const int is_running = monitor_task_is_running[i];
- monitor_task_is_running[i] = 0;
-
- if (signum == -1 && is_running != 0) {
- rte_thread_join(monitor_tasks[i], NULL);
- memset(&monitor_tasks[i], 0, sizeof(monitor_tasks[0]));
- }
- }
-}
static int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE *pfh)
{
@@ -255,7 +234,7 @@ static int nt4ga_adapter_deinit(struct adapter_info_s *p_adapter_info)
int i;
int res = -1;
- stop_monitor_tasks(-1);
+ nthw_service_del(RTE_NTNIC_SERVICE_ADAPTER_MON);
/* Nt4ga Deinit Filter */
nt4ga_filter_t *p_filter = &p_adapter_info->nt4ga_filter;
diff --git a/drivers/net/ntnic/include/common_adapter_defs.h b/drivers/net/ntnic/include/common_adapter_defs.h
deleted file mode 100644
index 6ed9121f0f..0000000000
--- a/drivers/net/ntnic/include/common_adapter_defs.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Napatech A/S
- */
-
-#ifndef _COMMON_ADAPTER_DEFS_H_
-#define _COMMON_ADAPTER_DEFS_H_
-
-/*
- * Declarations shared by NT adapter types.
- */
-#define NUM_ADAPTER_MAX (8)
-#define NUM_ADAPTER_PORTS_MAX (128)
-
-#endif /* _COMMON_ADAPTER_DEFS_H_ */
diff --git a/drivers/net/ntnic/include/nt4ga_adapter.h b/drivers/net/ntnic/include/nt4ga_adapter.h
index 7396b8ab65..6c701b601f 100644
--- a/drivers/net/ntnic/include/nt4ga_adapter.h
+++ b/drivers/net/ntnic/include/nt4ga_adapter.h
@@ -47,8 +47,5 @@ typedef struct adapter_info_s {
int n_tx_host_buffers;
} adapter_info_t;
-extern rte_thread_t monitor_tasks[NUM_ADAPTER_MAX];
-extern volatile int monitor_task_is_running[NUM_ADAPTER_MAX];
-
#endif /* _NT4GA_ADAPTER_H_ */
diff --git a/drivers/net/ntnic/include/ntnic_stat.h b/drivers/net/ntnic/include/ntnic_stat.h
index 1b53f6c347..928c629fb2 100644
--- a/drivers/net/ntnic/include/ntnic_stat.h
+++ b/drivers/net/ntnic/include/ntnic_stat.h
@@ -6,7 +6,7 @@
#ifndef NTNIC_STAT_H_
#define NTNIC_STAT_H_
-#include "common_adapter_defs.h"
+#include "ntos_drv.h"
#include "nthw_rmc.h"
#include "nthw_rpf.h"
#include "nthw_fpga_model.h"
diff --git a/drivers/net/ntnic/include/ntos_drv.h b/drivers/net/ntnic/include/ntos_drv.h
index e6e46f8cc1..f353a5eca8 100644
--- a/drivers/net/ntnic/include/ntos_drv.h
+++ b/drivers/net/ntnic/include/ntos_drv.h
@@ -20,7 +20,7 @@
#define NUM_MAC_ADDRS_PER_PORT (16U)
#define NUM_MULTICAST_ADDRS_PER_PORT (16U)
-#define NUM_ADAPTER_MAX (8)
+#define NUM_ADAPTER_MAX (1)
#define NUM_ADAPTER_PORTS_MAX (2)
diff --git a/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c b/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c
index adb187d322..21e95d84bd 100644
--- a/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c
@@ -9,6 +9,7 @@
#include "ntlog.h"
#include "i2c_nim.h"
#include "ntnic_mod_reg.h"
+#include "nt_service.h"
/*
* Swap tx/rx polarity
@@ -478,170 +479,178 @@ static int _port_init(adapter_info_t *drv, nthw_fpga_t *fpga, int port)
*/
static int _common_ptp_nim_state_machine(void *data)
{
- adapter_info_t *drv = (adapter_info_t *)data;
- fpga_info_t *fpga_info = &drv->fpga_info;
- nt4ga_link_t *link_info = &drv->nt4ga_link;
- nthw_fpga_t *fpga = fpga_info->mp_fpga;
- const int adapter_no = drv->adapter_no;
- const int nb_ports = fpga_info->n_phy_ports;
- uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
+ static adapter_info_t *drv;
+ static nt4ga_link_t *link_info;
+ static nthw_fpga_t *fpga;
+ static int nb_ports;
+ static nim_i2c_ctx_t *nim_ctx;
+ static link_state_t *link_state;
+ static nthw_mac_pcs_t *mac_pcs;
+ static nthw_gpio_phy_t *gpio_phy;
+ static uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
+
+ struct nt_service *adapter_mon_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_ADAPTER_MON);
+ RTE_ASSERT(adapter_mon_srv != NULL);
+
+ if (!NT_SERVICE_GET_STATE(adapter_mon_srv)) {
+ drv = (adapter_info_t *)data;
+ RTE_ASSERT(drv != NULL);
+
+ fpga_info_t *fpga_info = &drv->fpga_info;
+ int adapter_no = drv->adapter_no;
+
+ link_info = &drv->nt4ga_link;
+ fpga = fpga_info->mp_fpga;
+ nb_ports = fpga_info->n_phy_ports;
+
+ if (!fpga) {
+ NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
+ return -1;
+ }
- nim_i2c_ctx_t *nim_ctx;
- link_state_t *link_state;
- nthw_mac_pcs_t *mac_pcs;
- nthw_gpio_phy_t *gpio_phy;
+ RTE_ASSERT(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
+ nim_ctx = link_info->u.var100g.nim_ctx;
+ link_state = link_info->link_state;
+ mac_pcs = link_info->u.var100g.mac_pcs100g;
+ gpio_phy = link_info->u.var100g.gpio_phy;
- if (!fpga) {
- NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
- goto NT4GA_LINK_100G_MON_EXIT;
- }
+ memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
- RTE_ASSERT(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
- nim_ctx = link_info->u.var100g.nim_ctx;
- link_state = link_info->link_state;
- mac_pcs = link_info->u.var100g.mac_pcs100g;
- gpio_phy = link_info->u.var100g.gpio_phy;
+ NT_LOG(DBG, NTNIC, "%s: link state machine running...", drv->mp_adapter_id_str);
- monitor_task_is_running[adapter_no] = 1;
- memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
+ NT_LOG(INF, NTNIC, "Adapter monitor service started on lcore %i", rte_lcore_id());
+ adapter_mon_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(adapter_mon_srv, true);
+ return 0;
+ }
- if (monitor_task_is_running[adapter_no])
- NT_LOG(DBG, NTNIC, "%s: link state machine running...", drv->mp_adapter_id_str);
+ int i;
+ static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
- while (monitor_task_is_running[adapter_no]) {
- int i;
- static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
+ for (i = 0; i < nb_ports; i++) {
+ link_state_t new_link_state;
+ const bool is_port_disabled = link_info->port_action[i].port_disable;
+ const bool was_port_disabled = link_state[i].link_disabled;
+ const bool disable_port = is_port_disabled && !was_port_disabled;
+ const bool enable_port = !is_port_disabled && was_port_disabled;
- for (i = 0; i < nb_ports; i++) {
- link_state_t new_link_state;
- const bool is_port_disabled = link_info->port_action[i].port_disable;
- const bool was_port_disabled = link_state[i].link_disabled;
- const bool disable_port = is_port_disabled && !was_port_disabled;
- const bool enable_port = !is_port_disabled && was_port_disabled;
+ if (!rte_service_runstate_get(adapter_mon_srv->id)) /* stop quickly */
+ break;
- if (!monitor_task_is_running[adapter_no]) /* stop quickly */
- break;
+ /* Has the administrative port state changed? */
+ RTE_ASSERT(!(disable_port && enable_port));
+
+ if (disable_port) {
+ memset(&link_state[i], 0, sizeof(link_state[i]));
+ link_info->link_info[i].link_speed = NT_LINK_SPEED_UNKNOWN;
+ link_state[i].link_disabled = true;
+ reported_link[i] = false;
+ /* Turn off laser and LED, etc. */
+ (void)_create_nim(drv, i, false);
+ NT_LOG(DBG, NTNIC, "%s: Port %i is disabled",
+ drv->mp_port_id_str[i], i);
+ continue;
+ }
- /* Has the administrative port state changed? */
- RTE_ASSERT(!(disable_port && enable_port));
-
- if (disable_port) {
- memset(&link_state[i], 0, sizeof(link_state[i]));
- link_info->link_info[i].link_speed = NT_LINK_SPEED_UNKNOWN;
- link_state[i].link_disabled = true;
- reported_link[i] = false;
- /* Turn off laser and LED, etc. */
- (void)_create_nim(drv, i, false);
- NT_LOG(DBG, NTNIC, "%s: Port %i is disabled",
- drv->mp_port_id_str[i], i);
- continue;
- }
+ if (enable_port) {
+ link_state[i].link_disabled = false;
+ NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
+ drv->mp_port_id_str[i], i);
+ }
- if (enable_port) {
- link_state[i].link_disabled = false;
- NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
- drv->mp_port_id_str[i], i);
+ if (is_port_disabled)
+ continue;
+
+ if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
+ /* Loopback mode has changed. Do something */
+ if (!_nim_is_present(&gpio_phy[i], (uint8_t)i)) {
+ /*
+ * If there is no Nim present, we need to initialize the
+ * port anyway
+ */
+ _port_init(drv, fpga, i);
}
- if (is_port_disabled)
- continue;
+ NT_LOG(INF, NTNIC, "%s: Loopback mode changed=%u",
+ drv->mp_port_id_str[i],
+ link_info->port_action[i].port_lpbk_mode);
+ _set_loopback(drv,
+ &mac_pcs[i],
+ i,
+ link_info->port_action[i].port_lpbk_mode,
+ last_lpbk_mode[i]);
- if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
- /* Loopback mode has changed. Do something */
- if (!_nim_is_present(&gpio_phy[i], (uint8_t)i)) {
- /*
- * If there is no Nim present, we need to initialize the
- * port anyway
- */
- _port_init(drv, fpga, i);
- }
-
- NT_LOG(INF, NTNIC, "%s: Loopback mode changed=%u",
- drv->mp_port_id_str[i],
- link_info->port_action[i].port_lpbk_mode);
- _set_loopback(drv,
- &mac_pcs[i],
- i,
- link_info->port_action[i].port_lpbk_mode,
- last_lpbk_mode[i]);
-
- if (link_info->port_action[i].port_lpbk_mode == 1)
- link_state[i].link_up = true;
-
- last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode;
- continue;
- }
+ if (link_info->port_action[i].port_lpbk_mode == 1)
+ link_state[i].link_up = true;
- (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i, &new_link_state,
- is_port_disabled);
+ last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode;
+ continue;
+ }
- if (!new_link_state.nim_present) {
- if (link_state[i].nim_present) {
- NT_LOG(INF, NTNIC, "%s: NIM module removed",
- drv->mp_port_id_str[i]);
- }
+ (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i, &new_link_state,
+ is_port_disabled);
- link_state[i] = new_link_state;
- continue;
+ if (!new_link_state.nim_present) {
+ if (link_state[i].nim_present) {
+ NT_LOG(INF, NTNIC, "%s: NIM module removed",
+ drv->mp_port_id_str[i]);
}
- /* NIM module is present */
- if (new_link_state.lh_nim_absent || !link_state[i].nim_present) {
- sfp_nim_state_t new_state;
+ link_state[i] = new_link_state;
+ continue;
+ }
- NT_LOG(DBG, NTNIC, "%s: NIM module inserted",
- drv->mp_port_id_str[i]);
+ /* NIM module is present */
+ if (new_link_state.lh_nim_absent || !link_state[i].nim_present) {
+ sfp_nim_state_t new_state;
+
+ NT_LOG(DBG, NTNIC, "%s: NIM module inserted",
+ drv->mp_port_id_str[i]);
- if (_port_init(drv, fpga, i)) {
- NT_LOG(ERR, NTNIC,
- "%s: Failed to initialize NIM module",
- drv->mp_port_id_str[i]);
- continue;
- }
-
- if (nthw_nim_state_build(&nim_ctx[i], &new_state)) {
- NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data",
- drv->mp_port_id_str[i]);
- continue;
- }
-
- RTE_ASSERT(new_state.br); /* Cannot be zero if NIM is present */
- NT_LOG(DBG, NTNIC,
- "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
- drv->mp_port_id_str[i], nim_ctx->nim_id,
- nthw_nim_id_to_text(nim_ctx->nim_id),
- (unsigned int)new_state.br, nim_ctx->vendor_name,
- nim_ctx->prod_no, nim_ctx->serial_no);
-
- (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i,
- &link_state[i], is_port_disabled);
-
- NT_LOG(DBG, NTNIC, "%s: NIM module initialized",
+ if (_port_init(drv, fpga, i)) {
+ NT_LOG(ERR, NTNIC,
+ "%s: Failed to initialize NIM module",
drv->mp_port_id_str[i]);
continue;
}
- if (reported_link[i] != new_link_state.link_up) {
- NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
- (new_link_state.link_up ? "up" : "down"));
- link_info->link_info[i].link_speed =
- (new_link_state.link_up ? NT_LINK_SPEED_100G
- : NT_LINK_SPEED_UNKNOWN);
- link_state[i].link_up = new_link_state.link_up;
- reported_link[i] = new_link_state.link_up;
+ if (nthw_nim_state_build(&nim_ctx[i], &new_state)) {
+ NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data",
+ drv->mp_port_id_str[i]);
+ continue;
}
- check_link_state(drv, &mac_pcs[i]);
- } /* end-for */
+ RTE_ASSERT(new_state.br); /* Cannot be zero if NIM is present */
+ NT_LOG(DBG, NTNIC,
+ "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
+ drv->mp_port_id_str[i], nim_ctx->nim_id,
+ nthw_nim_id_to_text(nim_ctx->nim_id),
+ (unsigned int)new_state.br, nim_ctx->vendor_name,
+ nim_ctx->prod_no, nim_ctx->serial_no);
- if (monitor_task_is_running[adapter_no])
- nt_os_wait_usec(5 * 100000U); /* 5 x 0.1s = 0.5s */
- }
+ (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i,
+ &link_state[i], is_port_disabled);
-NT4GA_LINK_100G_MON_EXIT:
+ NT_LOG(DBG, NTNIC, "%s: NIM module initialized",
+ drv->mp_port_id_str[i]);
+ continue;
+ }
- NT_LOG(DBG, NTNIC, "%s: Stopped NT4GA 100 Gbps link monitoring thread.",
- drv->mp_adapter_id_str);
+ if (reported_link[i] != new_link_state.link_up) {
+ NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
+ (new_link_state.link_up ? "up" : "down"));
+ link_info->link_info[i].link_speed =
+ (new_link_state.link_up ? NT_LINK_SPEED_100G
+ : NT_LINK_SPEED_UNKNOWN);
+ link_state[i].link_up = new_link_state.link_up;
+ reported_link[i] = new_link_state.link_up;
+ }
+
+ check_link_state(drv, &mac_pcs[i]);
+ } /* end-for */
+
+ if (rte_service_runstate_get(adapter_mon_srv->id))
+ nt_os_wait_usec(5 * 100000U); /* 5 x 0.1s = 0.5s */
return 0;
}
@@ -649,11 +658,9 @@ static int _common_ptp_nim_state_machine(void *data)
/*
* Userland NIM state machine
*/
-static uint32_t nt4ga_link_100g_mon(void *data)
+static int nt4ga_link_100g_mon(void *data)
{
- (void)_common_ptp_nim_state_machine(data);
-
- return 0;
+ return _common_ptp_nim_state_machine(data);
}
/*
@@ -710,11 +717,21 @@ static int nt4ga_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nth
}
}
- /* Create state-machine thread */
+ /* Create state-machine service */
if (res == 0) {
- if (!monitor_task_is_running[adapter_no]) {
- res = rte_thread_create(&monitor_tasks[adapter_no], NULL,
- nt4ga_link_100g_mon, p_adapter_info);
+ struct rte_service_spec adapter_monitor_service = {
+ .name = "ntnic-adapter-monitor",
+ .callback = nt4ga_link_100g_mon,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = p_adapter_info,
+ };
+
+ res = nthw_service_add(&adapter_monitor_service, RTE_NTNIC_SERVICE_ADAPTER_MON);
+ if (res) {
+ NT_LOG(ERR, NTNIC, "%s: Failed to create adapter monitor service",
+ p_adapter_info->mp_adapter_id_str);
+ return res;
}
}
diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index 75a7504510..c8b7912e26 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -13,6 +13,7 @@
#include "nim_defines.h"
#include "nthw_gfg.h"
#include "nthw_phy_tile.h"
+#include "nt_service.h"
typedef enum {
LOOPBACK_HOST_NONE,
@@ -768,179 +769,186 @@ static int _port_init(adapter_info_t *p_info, nthw_fpga_t *fpga, int port)
/*
* Link state machine
*/
-static void *_common_ptp_nim_state_machine(void *data)
+static int _common_ptp_nim_state_machine(void *data)
{
- adapter_info_t *drv = (adapter_info_t *)data;
- fpga_info_t *fpga_info = &drv->fpga_info;
- nt4ga_link_t *link_info = &drv->nt4ga_link;
- nthw_fpga_t *fpga = fpga_info->mp_fpga;
- const int adapter_no = drv->adapter_no;
- const int nb_ports = fpga_info->n_phy_ports;
- uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
- /* link_state_t new_link_state; */
-
- link_state_t *link_state = link_info->link_state;
- nim_i2c_ctx_t *nim_ctx = link_info->u.var_a100g.nim_ctx;
+ static adapter_info_t *drv;
+ static nt4ga_link_t *link_info;
+ static nthw_fpga_t *fpga;
+ static int nb_ports;
+ static link_state_t *link_state;
+ static nim_i2c_ctx_t *nim_ctx;
+ static uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
+
+ struct nt_service *adapter_mon_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_ADAPTER_MON);
+ RTE_ASSERT(adapter_mon_srv != NULL);
+
+ if (!NT_SERVICE_GET_STATE(adapter_mon_srv)) {
+ drv = (adapter_info_t *)data;
+ RTE_ASSERT(drv != NULL);
+
+ fpga_info_t *fpga_info = &drv->fpga_info;
+ link_info = &drv->nt4ga_link;
+ fpga = fpga_info->mp_fpga;
+ int adapter_no = drv->adapter_no;
+
+ nb_ports = fpga_info->n_phy_ports;
+ link_state = link_info->link_state;
+ nim_ctx = link_info->u.var_a100g.nim_ctx;
+
+ if (!fpga) {
+ NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
+ return -1;
+ }
- if (!fpga) {
- NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
- goto NT4GA_LINK_100G_MON_EXIT;
- }
+ RTE_ASSERT(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
- RTE_ASSERT(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
+ memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
- monitor_task_is_running[adapter_no] = 1;
- memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
+ /* Initialize link state */
+ for (int i = 0; i < nb_ports; i++) {
+ link_state[i].link_disabled = true;
+ link_state[i].nim_present = false;
+ link_state[i].lh_nim_absent = true;
+ link_state[i].link_up = false;
+ link_state[i].link_state = NT_LINK_STATE_UNKNOWN;
+ link_state[i].link_state_latched = NT_LINK_STATE_UNKNOWN;
+ }
- /* Initialize link state */
- for (int i = 0; i < nb_ports; i++) {
- link_state[i].link_disabled = true;
- link_state[i].nim_present = false;
- link_state[i].lh_nim_absent = true;
- link_state[i].link_up = false;
- link_state[i].link_state = NT_LINK_STATE_UNKNOWN;
- link_state[i].link_state_latched = NT_LINK_STATE_UNKNOWN;
+ NT_LOG(INF, NTNIC, "Adapter monitor service started on lcore %i", rte_lcore_id());
+ adapter_mon_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(adapter_mon_srv, true);
+ return 0;
}
- if (monitor_task_is_running[adapter_no])
- NT_LOG(DBG, NTNIC, "%s: link state machine running...", drv->mp_adapter_id_str);
+ int i;
+ static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
- while (monitor_task_is_running[adapter_no]) {
- int i;
- static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
+ for (i = 0; i < nb_ports; i++) {
+ const bool is_port_disabled = link_info->port_action[i].port_disable;
+ const bool was_port_disabled = link_state[i].link_disabled;
+ const bool disable_port = is_port_disabled && !was_port_disabled;
+ const bool enable_port = !is_port_disabled && was_port_disabled;
- for (i = 0; i < nb_ports; i++) {
- const bool is_port_disabled = link_info->port_action[i].port_disable;
- const bool was_port_disabled = link_state[i].link_disabled;
- const bool disable_port = is_port_disabled && !was_port_disabled;
- const bool enable_port = !is_port_disabled && was_port_disabled;
-
- if (!monitor_task_is_running[adapter_no])
- break;
-
- /*
- * Has the administrative port state changed?
- */
- RTE_ASSERT(!(disable_port && enable_port));
-
- if (disable_port) {
- memset(&link_state[i], 0, sizeof(link_state[i]));
- link_state[i].link_disabled = true;
- link_state[i].lh_nim_absent = true;
- reported_link[i] = false;
- port_disable(drv, i);
- NT_LOG(INF, NTNIC, "%s: Port %i is disabled",
- drv->mp_port_id_str[i], i);
- continue;
- }
+ if (!rte_service_runstate_get(adapter_mon_srv->id))
+ break;
- if (enable_port) {
- link_state[i].link_disabled = false;
- NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
- drv->mp_port_id_str[i], i);
- }
+ /*
+ * Has the administrative port state changed?
+ */
+ RTE_ASSERT(!(disable_port && enable_port));
+
+ if (disable_port) {
+ memset(&link_state[i], 0, sizeof(link_state[i]));
+ link_state[i].link_disabled = true;
+ link_state[i].lh_nim_absent = true;
+ reported_link[i] = false;
+ port_disable(drv, i);
+ NT_LOG(INF, NTNIC, "%s: Port %i is disabled",
+ drv->mp_port_id_str[i], i);
+ continue;
+ }
- if (is_port_disabled)
- continue;
+ if (enable_port) {
+ link_state[i].link_disabled = false;
+ NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
+ drv->mp_port_id_str[i], i);
+ }
- if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
- /* Loopback mode has changed. Do something */
- if (!nim_is_present(&nim_ctx[i], i)) {
- /*
- * If there is no Nim present, we need to initialize the
- * port anyway
- */
- _port_init(drv, fpga, i);
- }
-
- set_loopback(drv,
- i,
- link_info->port_action[i].port_lpbk_mode,
- last_lpbk_mode[i]);
-
- if (link_info->port_action[i].port_lpbk_mode == 1)
- link_state[i].link_up = true;
-
- last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode;
- continue;
+ if (is_port_disabled)
+ continue;
+
+ if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
+ /* Loopback mode has changed. Do something */
+ if (!nim_is_present(&nim_ctx[i], i)) {
+ /*
+ * If there is no Nim present, we need to initialize the
+ * port anyway
+ */
+ _port_init(drv, fpga, i);
}
- get_link_state(drv, nim_ctx, &link_state[i], i);
- link_state[i].link_disabled = is_port_disabled;
+ set_loopback(drv,
+ i,
+ link_info->port_action[i].port_lpbk_mode,
+ last_lpbk_mode[i]);
- if (!link_state[i].nim_present) {
- if (!link_state[i].lh_nim_absent) {
- NT_LOG(INF, NTNIC, "%s: NIM module removed",
- drv->mp_port_id_str[i]);
- reported_link[i] = false;
- link_state[i].link_up = false;
- link_state[i].lh_nim_absent = true;
+ if (link_info->port_action[i].port_lpbk_mode == 1)
+ link_state[i].link_up = true;
- } else {
- NT_LOG(DBG, NTNIC, "%s: No NIM module, skip",
- drv->mp_port_id_str[i]);
- }
+ last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode;
+ continue;
+ }
- continue;
- }
+ get_link_state(drv, nim_ctx, &link_state[i], i);
+ link_state[i].link_disabled = is_port_disabled;
- /*
- * NIM module is present
- */
- if (link_state[i].lh_nim_absent && link_state[i].nim_present) {
- sfp_nim_state_t new_state;
- NT_LOG(INF, NTNIC, "%s: NIM module inserted",
+ if (!link_state[i].nim_present) {
+ if (!link_state[i].lh_nim_absent) {
+ NT_LOG(INF, NTNIC, "%s: NIM module removed",
drv->mp_port_id_str[i]);
+ reported_link[i] = false;
+ link_state[i].link_up = false;
+ link_state[i].lh_nim_absent = true;
- if (_port_init(drv, fpga, i)) {
- NT_LOG(ERR, NTNIC,
- "%s: Failed to initialize NIM module",
- drv->mp_port_id_str[i]);
- continue;
- }
+ } else {
+ NT_LOG(DBG, NTNIC, "%s: No NIM module, skip",
+ drv->mp_port_id_str[i]);
+ }
- if (nthw_nim_state_build(&nim_ctx[i], &new_state)) {
- NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data",
- drv->mp_port_id_str[i]);
- continue;
- }
+ continue;
+ }
- RTE_ASSERT(new_state.br); /* Cannot be zero if NIM is present */
- NT_LOG(DBG, NTNIC,
- "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
- drv->mp_port_id_str[i], nim_ctx[i].nim_id,
- nthw_nim_id_to_text(nim_ctx[i].nim_id),
- (unsigned int)new_state.br, nim_ctx[i].vendor_name,
- nim_ctx[i].prod_no, nim_ctx[i].serial_no);
- link_state[i].lh_nim_absent = false;
- NT_LOG(DBG, NTNIC, "%s: NIM module initialized",
+ /*
+ * NIM module is present
+ */
+ if (link_state[i].lh_nim_absent && link_state[i].nim_present) {
+ sfp_nim_state_t new_state;
+ NT_LOG(INF, NTNIC, "%s: NIM module inserted",
+ drv->mp_port_id_str[i]);
+
+ if (_port_init(drv, fpga, i)) {
+ NT_LOG(ERR, NTNIC,
+ "%s: Failed to initialize NIM module",
drv->mp_port_id_str[i]);
continue;
}
- if (reported_link[i] != link_state[i].link_up) {
- NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
- (link_state[i].link_up ? "up" : "down"));
- reported_link[i] = link_state[i].link_up;
- set_link_state(drv, nim_ctx, &link_state[i], i);
+ if (nthw_nim_state_build(&nim_ctx[i], &new_state)) {
+ NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data",
+ drv->mp_port_id_str[i]);
+ continue;
}
+
+ RTE_ASSERT(new_state.br); /* Cannot be zero if NIM is present */
+ NT_LOG(DBG, NTNIC,
+ "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
+ drv->mp_port_id_str[i], nim_ctx[i].nim_id,
+ nthw_nim_id_to_text(nim_ctx[i].nim_id),
+ (unsigned int)new_state.br, nim_ctx[i].vendor_name,
+ nim_ctx[i].prod_no, nim_ctx[i].serial_no);
+ link_state[i].lh_nim_absent = false;
+ NT_LOG(DBG, NTNIC, "%s: NIM module initialized",
+ drv->mp_port_id_str[i]);
+ continue;
}
- if (monitor_task_is_running[adapter_no])
- nt_os_wait_usec(5 * 100000U); /* 5 x 0.1s = 0.5s */
+ if (reported_link[i] != link_state[i].link_up) {
+ NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
+ (link_state[i].link_up ? "up" : "down"));
+ reported_link[i] = link_state[i].link_up;
+ set_link_state(drv, nim_ctx, &link_state[i], i);
+ }
}
-NT4GA_LINK_100G_MON_EXIT:
- NT_LOG(DBG, NTNIC, "%s: Stopped NT4GA 100 Gbps link monitoring thread.",
- drv->mp_adapter_id_str);
- return NULL;
+ if (rte_service_runstate_get(adapter_mon_srv->id))
+ nt_os_wait_usec(5 * 100000U); /* 5 x 0.1s = 0.5s */
+
+ return 0;
}
-static uint32_t nt4ga_agx_link_100g_mon(void *data)
+static int nt4ga_agx_link_100g_mon(void *data)
{
- (void)_common_ptp_nim_state_machine(data);
-
- return 0;
+ return _common_ptp_nim_state_machine(data);
}
/*
@@ -1009,12 +1017,24 @@ int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nthw_f
}
/*
- * Create state-machine thread
+ * Create state-machine service
*/
- if (!monitor_task_is_running[adapter_no]) {
- res = rte_thread_create(&monitor_tasks[adapter_no], NULL,
- nt4ga_agx_link_100g_mon, p_adapter_info);
+ if (res == 0) {
+ struct rte_service_spec adapter_monitor_service = {
+ .name = "ntnic-adapter_agx-monitor",
+ .callback = nt4ga_agx_link_100g_mon,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = p_adapter_info,
+ };
+
+ res = nthw_service_add(&adapter_monitor_service, RTE_NTNIC_SERVICE_ADAPTER_MON);
+ if (res) {
+ NT_LOG(ERR, NTNIC, "%s: Failed to create adapter monitor service",
+ p_adapter_info->mp_adapter_id_str);
+ return res;
+ }
}
return res;
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
index 9f22ee2bba..c39771acc2 100644
--- a/drivers/net/ntnic/ntutil/nt_service.c
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -36,6 +36,12 @@ static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
.lcore = RTE_MAX_LCORE,
.initialized = false,
},
+ [RTE_NTNIC_SERVICE_ADAPTER_MON] = {
+ .tag = RTE_NTNIC_SERVICE_ADAPTER_MON,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
};
inline struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index 1a68cb8e37..08e7958acd 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -45,6 +45,7 @@ enum rte_ntnic_service_tag {
RTE_NTNIC_SERVICE_STAT = 1,
RTE_NTNIC_SERVICE_PORT_0_EVENT = 2,
RTE_NTNIC_SERVICE_PORT_1_EVENT = 3,
+ RTE_NTNIC_SERVICE_ADAPTER_MON = 4,
RTE_NTNIC_SERVICE_MAX
};
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 6/7] net/ntnic: add warning about service cores
2025-09-08 11:04 [PATCH v1 0/7] migrate threads to DPDK service framework Serhii Iliushyk
` (4 preceding siblings ...)
2025-09-08 11:04 ` [PATCH v1 5/7] net/ntnic: migrate adapter mon " Serhii Iliushyk
@ 2025-09-08 11:04 ` Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 7/7] net/ntnic: cleanup using pthreads and rte_thread Serhii Iliushyk
2025-09-08 20:08 ` [PATCH v1 0/7] migrate threads to DPDK service framework Stephen Hemminger
7 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 11:04 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This commit adds a warning message if the service cores are not available.
This warning notifies a user about potential issues with ntnic services.
There in no error because the service cores may be added
by application itself after the pcie_probe.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/ntnic_ethdev.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index 7ec1c94a14..664112f67e 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -2607,6 +2607,14 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
}
}
+ uint32_t cores[RTE_MAX_LCORE] = {0};
+ int32_t lcore_count = rte_service_lcore_list(cores, RTE_MAX_LCORE);
+
+ if (lcore_count <= 0) {
+ NT_LOG(WRN, NTNIC, "No service cores available. "
+ "Please check if all NTNIC services are started");
+ }
+
return 0;
}
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 7/7] net/ntnic: cleanup using pthreads and rte_thread
2025-09-08 11:04 [PATCH v1 0/7] migrate threads to DPDK service framework Serhii Iliushyk
` (5 preceding siblings ...)
2025-09-08 11:04 ` [PATCH v1 6/7] net/ntnic: add warning about service cores Serhii Iliushyk
@ 2025-09-08 11:04 ` Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 0/7] migrate threads to DPDK service framework Serhii Iliushyk
2025-09-08 20:08 ` [PATCH v1 0/7] migrate threads to DPDK service framework Stephen Hemminger
7 siblings, 1 reply; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 11:04 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This patch cleans up the code to use pthreads and rte_thread APIs.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/adapter/nt4ga_adapter.c | 2 --
drivers/net/ntnic/include/nt4ga_adapter.h | 1 -
drivers/net/ntnic/include/ntdrv_4ga.h | 1 -
drivers/net/ntnic/nthw/core/nthw_pca9532.c | 2 --
drivers/net/ntnic/nthw/core/nthw_pcal6416a.c | 1 -
.../net/ntnic/nthw/core/nthw_si5332_si5156.c | 1 -
.../profile_inline/flow_api_profile_inline.c | 2 +-
drivers/net/ntnic/ntnic_ethdev.c | 22 +++++--------------
drivers/net/ntnic/ntutil/nt_util.c | 2 +-
9 files changed, 7 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c
index 363874c85f..de4e8707bf 100644
--- a/drivers/net/ntnic/adapter/nt4ga_adapter.c
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c
@@ -3,8 +3,6 @@
* Copyright(c) 2023 Napatech A/S
*/
-#include <rte_thread.h>
-
#include "nt_service.h"
#include "ntlog.h"
#include "nthw_fpga.h"
diff --git a/drivers/net/ntnic/include/nt4ga_adapter.h b/drivers/net/ntnic/include/nt4ga_adapter.h
index 6c701b601f..0598e62b7b 100644
--- a/drivers/net/ntnic/include/nt4ga_adapter.h
+++ b/drivers/net/ntnic/include/nt4ga_adapter.h
@@ -40,7 +40,6 @@ typedef struct adapter_info_s {
char *mp_port_id_str[NUM_ADAPTER_PORTS_MAX];
char *mp_adapter_id_str;
char *p_dev_name;
- volatile bool *pb_shutdown;
int adapter_no;
int n_rx_host_buffers;
diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h
index ee0e66c4d4..4ff1f115f4 100644
--- a/drivers/net/ntnic/include/ntdrv_4ga.h
+++ b/drivers/net/ntnic/include/ntdrv_4ga.h
@@ -14,7 +14,6 @@ typedef struct ntdrv_4ga_s {
struct adapter_info_s adapter_info;
char *p_drv_name;
- volatile bool b_shutdown;
rte_spinlock_t stat_lck;
} ntdrv_4ga_t;
diff --git a/drivers/net/ntnic/nthw/core/nthw_pca9532.c b/drivers/net/ntnic/nthw/core/nthw_pca9532.c
index af14cd6d06..805e0275e8 100644
--- a/drivers/net/ntnic/nthw/core/nthw_pca9532.c
+++ b/drivers/net/ntnic/nthw/core/nthw_pca9532.c
@@ -3,8 +3,6 @@
* Copyright(c) 2023 Napatech A/S
*/
-#include <pthread.h>
-
#include "nt_util.h"
#include "ntlog.h"
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
index 2fca469497..f7efc196f4 100644
--- a/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
+++ b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
@@ -2,7 +2,6 @@
* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2023 Napatech A/S
*/
-#include <pthread.h>
#include "nt_util.h"
#include "ntlog.h"
diff --git a/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
index eb11ebc67a..537d58afb7 100644
--- a/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
+++ b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
@@ -3,7 +3,6 @@
* Copyright(c) 2023 Napatech A/S
*/
-#include <pthread.h>
#include "generic/rte_spinlock.h"
#include "nt_util.h"
#include "ntlog.h"
diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
index eaaf681ac6..2291642ca9 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
@@ -5276,7 +5276,7 @@ struct flow_handle *flow_async_create_profile_inline(struct flow_eth_dev *dev,
} while (status == CELL_STATUS_INITIALIZING);
/* error handling in case that create_flow_filter() will fail in the other
- * thread
+ * service
*/
if (status == CELL_STATUS_UNINITIALIZED)
goto err_exit;
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index 664112f67e..0f70462f3d 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -6,8 +6,6 @@
#include <stdint.h>
#include <stdarg.h>
-#include <signal.h>
-
#include <rte_eal.h>
#include <rte_dev.h>
#include <rte_vfio.h>
@@ -33,12 +31,6 @@
#include "rte_pmd_ntnic.h"
#include "nt_service.h"
-const rte_thread_attr_t thread_attr = { .priority = RTE_THREAD_PRIORITY_NORMAL };
-#define THREAD_CREATE(a, b, c) rte_thread_create(a, &thread_attr, b, c)
-#define THREAD_CTRL_CREATE(a, b, c, d) rte_thread_create_internal_control(a, b, c, d)
-#define THREAD_JOIN(a) rte_thread_join(a, NULL)
-#define THREAD_FUNC static uint32_t
-#define THREAD_RETURN (0)
#define HW_MAX_PKT_LEN (10000)
#define MAX_MTU (HW_MAX_PKT_LEN - RTE_ETHER_HDR_LEN - RTE_ETHER_CRC_LEN)
#define MIN_MTU_INLINE 512
@@ -1536,14 +1528,13 @@ drv_deinit(struct drv_s *p_drv)
fpga_info_t *fpga_info = &p_nt_drv->adapter_info.fpga_info;
/*
- * Mark the global pdrv for cleared. Used by some threads to terminate.
- * 1 second to give the threads a chance to see the termonation.
+ * Mark the global pdrv for cleared. Used by some services to terminate.
+ * 1 second to give the services a chance to see the termonation.
*/
clear_pdrv(p_drv);
nt_os_wait_usec(1000000);
/* stop statistics service */
- p_drv->ntdrv.b_shutdown = true;
nthw_service_del(RTE_NTNIC_SERVICE_STAT);
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
@@ -2323,9 +2314,6 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
p_nt_drv->adapter_info.hw_info.pci_sub_vendor_id,
p_nt_drv->adapter_info.hw_info.pci_sub_device_id);
- p_nt_drv->b_shutdown = false;
- p_nt_drv->adapter_info.pb_shutdown = &p_nt_drv->b_shutdown;
-
/* store context */
store_pdrv(p_drv);
@@ -2366,7 +2354,7 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
NT_LOG_DBGX(DBG, NTNIC, "SG module is not initialized");
}
- /* Start ctrl, monitor, stat thread only for primary process. */
+ /* Start ctrl, monitor, stat service only for primary process. */
if (err == 0) {
/* mp_adapter_id_str is initialized after nt4ga_adapter_init(p_nt_drv) */
const char *const p_adapter_id_str = p_nt_drv->adapter_info.mp_adapter_id_str;
@@ -2631,7 +2619,7 @@ nthw_pci_dev_deinit(struct rte_eth_dev *eth_dev __rte_unused)
fpga_info_t *fpga_info = &p_ntdrv->adapter_info.fpga_info;
const int n_phy_ports = fpga_info->n_phy_ports;
- /* let running threads end Rx and Tx activity */
+ /* let running services end Rx and Tx activity */
if (sg_ops != NULL) {
nt_os_wait_usec(1 * 1000 * 1000);
@@ -2706,7 +2694,7 @@ nthw_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
/*
* 1 time calculation of 1 sec stat update rtc cycles to prevent stat poll
- * flooding by OVS from multiple virtual port threads - no need to be precise
+ * flooding by OVS from multiple virtual port services - no need to be precise
*/
uint64_t now_rtc = rte_get_tsc_cycles();
nt_os_wait_usec(10 * 1000);
diff --git a/drivers/net/ntnic/ntutil/nt_util.c b/drivers/net/ntnic/ntutil/nt_util.c
index df382e7a24..a4d30d8ca4 100644
--- a/drivers/net/ntnic/ntutil/nt_util.c
+++ b/drivers/net/ntnic/ntutil/nt_util.c
@@ -16,7 +16,7 @@
static struct nt_util_vfio_impl vfio_cb;
-/* uses usleep which schedules out the calling thread */
+/* uses usleep which schedules out the calling service */
void nt_os_wait_usec(int val)
{
rte_delay_us_sleep(val);
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 0/7] migrate threads to DPDK service framework
2025-09-08 11:04 ` [PATCH v1 7/7] net/ntnic: cleanup using pthreads and rte_thread Serhii Iliushyk
@ 2025-09-08 14:17 ` Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 1/7] net/ntnic: introduce service API for NTNIC PMD Serhii Iliushyk
` (6 more replies)
0 siblings, 7 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 14:17 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This modification provides better resource (CPU) management for NTNIC PMD.
The following threads are migrated:
* FLM update thread
* Statistic thread
* Port event thread
* Adapter monitoring thread
Additionally, a warning is added to inform users about the importance of
dedicating lcores to the DPDK service framework when using the NTNIC PMD.
The code is also cleaned up to use pthreads and rte_thread APIs.
After this patch series, an each application using NTNIC PMD should
dedicate at least five(5) cores for DPDK service framework to ensure
proper operation of the NTNIC PMD.
The sercvice cores can be dedicated by EAL options:
* s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores
* S SERVICE CORELIST List of cores to run services on
Or with special API by application itself.
* rte_pmd_ntnic_service_set_lcore to map a service to a specific lcore
* rte_pmd_ntnic_service_get_id to get a service ID.
Serhii Iliushyk (7):
net/ntnic: introduce service API for NTNIC PMD
net/ntnic: migrate flm update thread to service
net/ntnic: migrate statistic thread to service
net/ntnic: migrate port event thread to service
net/ntnic: migrate adapter mon thread to service
net/ntnic: add warning about service cores
net/ntnic: cleanup using pthreads and rte_thread
doc/guides/nics/ntnic.rst | 112 ++++
drivers/net/ntnic/adapter/nt4ga_adapter.c | 27 +-
.../net/ntnic/include/common_adapter_defs.h | 15 -
drivers/net/ntnic/include/nt4ga_adapter.h | 4 -
drivers/net/ntnic/include/ntdrv_4ga.h | 4 -
drivers/net/ntnic/include/ntnic_stat.h | 2 +-
drivers/net/ntnic/include/ntos_drv.h | 4 +-
.../link_mgmt/link_100g/nt4ga_link_100g.c | 303 +++++-----
.../link_agx_100g/nt4ga_agx_link_100g.c | 306 ++++++-----
drivers/net/ntnic/meson.build | 2 +
drivers/net/ntnic/nthw/core/nthw_pca9532.c | 2 -
drivers/net/ntnic/nthw/core/nthw_pcal6416a.c | 1 -
.../net/ntnic/nthw/core/nthw_si5332_si5156.c | 1 -
.../profile_inline/flow_api_profile_inline.c | 2 +-
drivers/net/ntnic/ntnic_ethdev.c | 520 ++++++++++--------
drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 17 +
drivers/net/ntnic/ntutil/nt_service.c | 127 +++++
drivers/net/ntnic/ntutil/nt_service.h | 62 +++
drivers/net/ntnic/ntutil/nt_util.c | 2 +-
drivers/net/ntnic/rte_pmd_ntnic.c | 104 ++++
drivers/net/ntnic/rte_pmd_ntnic.h | 26 +
21 files changed, 1073 insertions(+), 570 deletions(-)
delete mode 100644 drivers/net/ntnic/include/common_adapter_defs.h
create mode 100644 drivers/net/ntnic/ntutil/nt_service.c
create mode 100644 drivers/net/ntnic/ntutil/nt_service.h
create mode 100644 drivers/net/ntnic/rte_pmd_ntnic.c
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 1/7] net/ntnic: introduce service API for NTNIC PMD
2025-09-08 14:17 ` [PATCH v2 0/7] migrate threads to DPDK service framework Serhii Iliushyk
@ 2025-09-08 14:17 ` Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 2/7] net/ntnic: migrate flm update thread to service Serhii Iliushyk
` (5 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 14:17 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This commit adds a common service API for the NTNIC PMD,
which includes functions for service management: add or delete a service
and retrieve information about a service.
The API is designed to facilitate the interaction with services within
the NTNIC driver, allowing for better control
and monitoring of service states.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
doc/guides/nics/ntnic.rst | 112 ++++++++++++++++++++++++++
drivers/net/ntnic/meson.build | 2 +
drivers/net/ntnic/ntutil/nt_service.c | 103 +++++++++++++++++++++++
drivers/net/ntnic/ntutil/nt_service.h | 62 ++++++++++++++
drivers/net/ntnic/rte_pmd_ntnic.c | 104 ++++++++++++++++++++++++
drivers/net/ntnic/rte_pmd_ntnic.h | 21 +++++
6 files changed, 404 insertions(+)
create mode 100644 drivers/net/ntnic/ntutil/nt_service.c
create mode 100644 drivers/net/ntnic/ntutil/nt_service.h
create mode 100644 drivers/net/ntnic/rte_pmd_ntnic.c
diff --git a/doc/guides/nics/ntnic.rst b/doc/guides/nics/ntnic.rst
index b3d6ad70c1..a173eaa2ac 100644
--- a/doc/guides/nics/ntnic.rst
+++ b/doc/guides/nics/ntnic.rst
@@ -185,3 +185,115 @@ There are list of characteristics that age timeout action has:
- after flow is aged-out it's not automatically deleted;
- aged-out flow can be updated with ``flow update`` command,
and its aged-out status will be reverted;
+
+Service API
+-----------
+
+**nthw_service_add**
+**nthw_service_del**
+**nthw_service_get_info**
+
+The NTNIC PMD provides a service API that allows applications to configure services
+
+The services are responsible for handling the vital functionality of the NTNIC PMD:
+
+- **FLM Update**: is responsible for creating and destroying flows;
+- **Statistics**: is responsible for collecting statistics;
+- **Port event**: is responsible for handling port events: aging, port load, and flow load;
+- **Adapter monitor** is responsible for link control;
+
+**NOTE**: Use next EAL options to configure set service cores
+ * -s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores;
+ * -S SERVICE CORELIST List of cores to run services on;
+
+**NOTE**: **At least 5 lcores must be reserved** for the ntnic services by EAL options. above.
+
+For example
+
+.. code-block:: console
+
+ dpdk-testpmd -S 8,9,10,11,12
+
+The PMD registers each service during initialization by function:
+
+.. code-block:: c
+
+ int nthw_service_add(struct rte_service_spec *srv_spec, const enum rte_ntnic_service_tag tag)
+
+and unregistered by the PMD during deinitialization by the function:
+
+.. code-block:: c
+
+ int nthw_service_del(const enum rte_ntnic_service_tag tag)
+
+The service info may be retrieved by function:
+
+.. code-block:: c
+
+ struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
+
+The service info includes the service ID, assigned lcore, and initialization state.
+
+Service API for user applications
+---------------------------------
+**rte_pmd_ntnic_service_set_lcore**
+**rte_pmd_ntnic_service_get_id**
+
+The exported service API is available for applications to configure the services.
+
+By API function:
+
+.. code-block:: c
+
+ int rte_pmd_ntnic_service_set_lcore(enum rte_ntnic_service_tag tag, uint32_t lcore_id)
+
+For example to assign lcores 8,9,10,11,12 to the services, the application can use:
+
+.. code-block:: c
+
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_STAT, 8);
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_ADAPTER_MON, 9);
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_PORT_0_EVENT, 10);
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_PORT_1_EVENT,11);
+ rte_pmd_ntnic_service_set_lcore(RTE_NTNIC_SERVICE_FLM_UPDATE, 12);
+
+The API will automatically lcore to service core list and map the service to the lcore.
+
+.. note:: Use `rte_service_lcore_start` to start the lcore after mapping it to the service.
+
+Each service has its own tag to identify it.
+
+.. code-block:: c
+
+ enum rte_ntnic_service_tag {
+ RTE_NTNIC_SERVICE_FLM_UPDATE = 0,
+ RTE_NTNIC_SERVICE_STAT = 1,
+ RTE_NTNIC_SERVICE_PORT_0_EVENT = 2,
+ RTE_NTNIC_SERVICE_PORT_1_EVENT = 3,
+ RTE_NTNIC_SERVICE_ADAPTER_MON = 4,
+ RTE_NTNIC_SERVICE_MAX
+ };
+
+The application may use next API function to retrieve the service id:
+
+.. code-block:: c
+
+ int rte_pmd_ntnic_service_get_id(enum rte_ntnic_service_tag tag);
+
+
+For example, to enable statistics for flm_update service, the application can use:
+
+.. code-block:: c
+
+ int flm_update_id = rte_pmd_ntnic_service_get_id(RTE_NTNIC_SERVICE_FLM_UPDATE);
+ rte_service_set_stats_enable(flm_update_id, 1);
+
+All other manipulations with the service can be done with the service ID and rte_service* API.
+
+To use the service API, an application must have included the header file:
+
+.. code-block:: c
+
+ #include <rte_pmd_ntnic.h>
+
+And linked with the library: `librte_net_ntnic.so` or `librte_net_ntnic.a` for static linking.
diff --git a/drivers/net/ntnic/meson.build b/drivers/net/ntnic/meson.build
index b4c6cfe7de..785ac4836d 100644
--- a/drivers/net/ntnic/meson.build
+++ b/drivers/net/ntnic/meson.build
@@ -120,7 +120,9 @@ sources = files(
'ntlog/ntlog.c',
'ntnic_filter/ntnic_filter.c',
'ntutil/nt_util.c',
+ 'ntutil/nt_service.c',
'ntnic_mod_reg.c',
'ntnic_vfio.c',
'ntnic_ethdev.c',
+ 'rte_pmd_ntnic.c',
)
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
new file mode 100644
index 0000000000..4ef1233f12
--- /dev/null
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -0,0 +1,103 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2025 Napatech A/S
+ */
+
+#include <rte_service.h>
+#include <rte_cycles.h>
+
+#include "nt_service.h"
+#include "ntlog.h"
+
+#define NT_SERVICE_UNKNOWN_ID (-1)
+
+static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
+ [0] = {
+ .tag = RTE_NTNIC_SERVICE_MAX,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
+};
+
+inline struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
+{
+ if (tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX)
+ return NULL;
+
+ return &g_nt_services[tag];
+}
+
+int nthw_service_add(struct rte_service_spec *srv_spec, const enum rte_ntnic_service_tag tag)
+{
+ if (srv_spec == NULL || tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX) {
+ NT_LOG(ERR, NTNIC, "Invalid service specification or service tag");
+ return -1;
+ }
+
+ int ret = rte_service_component_register(srv_spec, &g_nt_services[tag].id);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to register service %s: error: %d",
+ srv_spec->name, ret);
+ return ret;
+ }
+
+ const uint32_t service_id = g_nt_services[tag].id;
+
+ NT_LOG(DBG, NTNIC, "Service %s registered with ID %u",
+ srv_spec->name, service_id);
+
+ rte_service_component_runstate_set(service_id, 1);
+
+ ret = rte_service_runstate_set(service_id, 1);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to start service %s: error: %d",
+ srv_spec->name, ret);
+ rte_service_component_unregister(service_id);
+ return ret;
+ }
+
+ return 0;
+}
+
+int nthw_service_del(const enum rte_ntnic_service_tag tag)
+{
+ if (tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX) {
+ NT_LOG(ERR, NTNIC, "Invalid service tag");
+ return -1;
+ }
+
+ struct nt_service *info = &g_nt_services[tag];
+
+ const char *service_name = rte_service_get_name(info->id);
+
+ rte_service_component_runstate_set(info->id, 0);
+
+ const uint32_t timeout_count = 10000;
+
+ for (uint32_t i = 0; i < timeout_count; i++) {
+ if (rte_service_may_be_active(info->id) == 0)
+ break;
+ rte_delay_ms(1);
+ }
+
+ int ret = rte_service_runstate_set(info->id, 0);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to stop service %s: error: %d",
+ service_name, ret);
+ return ret;
+ }
+
+ ret = rte_service_component_unregister(info->id);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to unregister service %s: error: %d",
+ service_name, ret);
+ return ret;
+ }
+
+ NT_LOG(DBG, NTNIC, "Service ID %d unregistered", info->id);
+
+ g_nt_services[tag].id = NT_SERVICE_UNKNOWN_ID;
+
+ return 0;
+}
diff --git a/drivers/net/ntnic/ntutil/nt_service.h b/drivers/net/ntnic/ntutil/nt_service.h
new file mode 100644
index 0000000000..73c9076c2e
--- /dev/null
+++ b/drivers/net/ntnic/ntutil/nt_service.h
@@ -0,0 +1,62 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2025 Napatech A/S
+ */
+
+#ifndef __NT_SERVICE_H__
+#define __NT_SERVICE_H__
+
+#include <stdint.h>
+#include <rte_service_component.h>
+#include <rte_stdatomic.h>
+#include <rte_pmd_ntnic.h>
+
+#define NT_SERVICE_GET_STATE(srv) \
+ rte_atomic_load_explicit(&(srv)->initialized, rte_memory_order_seq_cst)
+
+#define NT_SERVICE_SET_STATE(srv, state) \
+ rte_atomic_store_explicit(&(srv)->initialized, state, rte_memory_order_seq_cst)
+
+
+struct nt_service {
+ const enum rte_ntnic_service_tag tag;
+ uint32_t id;
+ uint32_t lcore;
+ RTE_ATOMIC(bool) initialized;
+};
+
+/**
+ * Get service information by tag.
+ *
+ * This function retrieves the service information based on the provided tag.
+ * It returns a pointer to the nt_service structure containing the service ID
+ * and other relevant information.
+ *
+ * @param tag The tag of the service to retrieve.
+ * @return Pointer to the nt_service structure or NULL if not found.
+ */
+struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag);
+
+/**
+ * Register and start a service with the specified tag.
+ *
+ * @srv_spec: Pointer to the service specification structure.
+ * @tag: Tag of the service to be registered.
+ *
+ * Returns 0 on success, or a negative error code on failure.
+ */
+int nthw_service_add(struct rte_service_spec *srv_spec, const enum rte_ntnic_service_tag tag);
+
+/**
+ * Unregisters a service by its tag.
+ *
+ * This function stops the service, waits for it to become inactive, and then
+ * unregisters it from the service component.
+ *
+ * @param tag The tag of the service to be unregistered.
+ * @return 0 on success, negative value on failure.
+ */
+
+int nthw_service_del(const enum rte_ntnic_service_tag tag);
+
+#endif /* __NT_SERVICE_H__ */
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.c b/drivers/net/ntnic/rte_pmd_ntnic.c
new file mode 100644
index 0000000000..fcc06a1ea0
--- /dev/null
+++ b/drivers/net/ntnic/rte_pmd_ntnic.c
@@ -0,0 +1,104 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2025 Napatech A/S
+ */
+
+#include <eal_export.h>
+#include <rte_service.h>
+#include <rte_pmd_ntnic.h>
+
+#include <stdint.h>
+
+#include "nt_service.h"
+#include "ntlog.h"
+
+static int nthw_service_is_mapped_to_lcore(enum rte_ntnic_service_tag tag)
+{
+ struct nt_service *service = nthw_service_get_info(tag);
+
+ uint32_t cores[RTE_MAX_LCORE] = {0};
+ int32_t lcore_count = rte_service_lcore_list(cores, RTE_MAX_LCORE);
+
+ for (int32_t i = 0; i < lcore_count; i++) {
+ if (rte_service_map_lcore_get(service->id, cores[i]))
+ return cores[i];
+ }
+ return RTE_MAX_LCORE;
+}
+
+
+RTE_EXPORT_SYMBOL(rte_pmd_ntnic_service_set_lcore)
+int rte_pmd_ntnic_service_set_lcore(enum rte_ntnic_service_tag tag, uint32_t lcore_id)
+{
+ if (tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX || lcore_id >= RTE_MAX_LCORE) {
+ NT_LOG(ERR, NTNIC, "Invalid service tag or lcore ID");
+ return -1;
+ }
+
+ struct nt_service *srv = nthw_service_get_info(tag);
+ const char *service_name = rte_service_get_name(srv->id);
+
+ uint32_t service_core = nthw_service_is_mapped_to_lcore(tag);
+
+ if (service_core != RTE_MAX_LCORE) {
+ NT_LOG(WRN, NTNIC, "Service %s[id=%u] is already mapped to lcore: %u", service_name,
+ srv->id, service_core);
+ /* Mapping by application has higher priority then 1:1 default mapping.
+ * Disable previous mapping and do remapping to new lcore.
+ */
+
+ rte_service_runstate_set(srv->id, 0);
+
+ NT_SERVICE_SET_STATE(srv, false);
+
+ int timeout_count = 10000;
+
+ while (rte_service_may_be_active(srv->id) != 0) {
+ if (--timeout_count <= 0) {
+ NT_LOG(ERR, NTNIC, "Failed to stop service %s[id=%d] on lcore %u",
+ service_name, srv->id, service_core);
+ return -1;
+ }
+ rte_delay_ms(1);
+ }
+
+ rte_service_map_lcore_set(srv->id, service_core, 0);
+ rte_service_runstate_set(srv->id, 1);
+ }
+
+ int ret = rte_service_lcore_add(lcore_id);
+ if (ret < 0 && ret != -EALREADY) {
+ NT_LOG(ERR, NTNIC, "Failed to add service lcore %u for service %s: error: %d",
+ lcore_id, service_name, ret);
+ return ret;
+ }
+
+ ret = rte_service_map_lcore_set(srv->id, lcore_id, 1);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC, "Failed to map service %s to lcore %u: error: %d",
+ service_name, lcore_id, ret);
+ return ret;
+ }
+
+ NT_LOG(DBG, NTNIC, "Service %s[id=%d] is mapped to lcore %u", service_name, srv->id,
+ lcore_id);
+
+ return 0;
+}
+
+RTE_EXPORT_SYMBOL(rte_pmd_ntnic_service_get_id)
+int rte_pmd_ntnic_service_get_id(enum rte_ntnic_service_tag tag)
+{
+ if (tag < 0 || tag >= RTE_NTNIC_SERVICE_MAX) {
+ NT_LOG(ERR, NTNIC, "Invalid service tag");
+ return -1;
+ }
+
+ struct nt_service *service = nthw_service_get_info(tag);
+ if (service == NULL) {
+ NT_LOG(ERR, NTNIC, "Service with tag %d not found", tag);
+ return -1;
+ }
+
+ return service->id;
+}
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index 4a1ba18a5e..7a491319fa 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -40,4 +40,25 @@ enum rte_ntnic_event_type {
RTE_NTNIC_FLM_STATS_EVENT,
};
+enum rte_ntnic_service_tag {
+ RTE_NTNIC_SERVICE_MAX = 1
+};
+
+/**
+ * Set the lcore for a specific service.
+ *
+ * @param tag The service tag to set the lcore for.
+ * @param lcore_id The lcore ID to set for the service.
+ * @return 0 on success, negative value on failure.
+ */
+int rte_pmd_ntnic_service_set_lcore(enum rte_ntnic_service_tag tag, uint32_t lcore_id);
+
+/**
+ * Get the ID of a specific service.
+ *
+ * @param tag The service tag to get the ID for.
+ * @return The service ID on success, negative value on failure.
+ */
+int rte_pmd_ntnic_service_get_id(enum rte_ntnic_service_tag tag);
+
#endif /* NTNIC_EVENT_H_ */
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 2/7] net/ntnic: migrate flm update thread to service
2025-09-08 14:17 ` [PATCH v2 0/7] migrate threads to DPDK service framework Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 1/7] net/ntnic: introduce service API for NTNIC PMD Serhii Iliushyk
@ 2025-09-08 14:17 ` Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 3/7] net/ntnic: migrate statistic " Serhii Iliushyk
` (4 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 14:17 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This commit adds the FLM update service to the NTNIC PMD.
The service is responsible for handling creating/destroying flows.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/include/ntdrv_4ga.h | 1 -
drivers/net/ntnic/ntnic_ethdev.c | 67 ++++++++++++-------
drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 17 +++++
drivers/net/ntnic/ntutil/nt_service.c | 4 +-
drivers/net/ntnic/rte_pmd_ntnic.h | 3 +-
5 files changed, 62 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h
index 78cf10368a..35afcd546c 100644
--- a/drivers/net/ntnic/include/ntdrv_4ga.h
+++ b/drivers/net/ntnic/include/ntdrv_4ga.h
@@ -15,7 +15,6 @@ typedef struct ntdrv_4ga_s {
char *p_drv_name;
volatile bool b_shutdown;
- rte_thread_t flm_thread;
rte_spinlock_t stat_lck;
rte_thread_t stat_thread;
rte_thread_t port_event_thread;
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index 79ef9e7e7c..c114017db8 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -31,6 +31,7 @@
#include "profile_inline/flm_age_queue.h"
#include "profile_inline/flm_evt_queue.h"
#include "rte_pmd_ntnic.h"
+#include "nt_service.h"
const rte_thread_attr_t thread_attr = { .priority = RTE_THREAD_PRIORITY_NORMAL };
#define THREAD_CREATE(a, b, c) rte_thread_create(a, &thread_attr, b, c)
@@ -1546,7 +1547,7 @@ drv_deinit(struct drv_s *p_drv)
THREAD_JOIN(p_nt_drv->stat_thread);
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
- THREAD_JOIN(p_nt_drv->flm_thread);
+ nthw_service_del(RTE_NTNIC_SERVICE_FLM_UPDATE);
profile_inline_ops->flm_free_queues();
THREAD_JOIN(p_nt_drv->port_event_thread);
/* Free all local flm event queues */
@@ -1980,40 +1981,46 @@ THREAD_FUNC port_event_thread_fn(void *context)
}
/*
- * Adapter flm stat thread
+ * Adapter flm update service
*/
-THREAD_FUNC adapter_flm_update_thread_fn(void *context)
+static int adapter_flm_update_service(void *context)
{
- const struct profile_inline_ops *profile_inline_ops = get_profile_inline_ops();
+ static struct flow_eth_dev *dev;
+ static const struct profile_inline_ops *profile_inline_ops;
- if (profile_inline_ops == NULL) {
- NT_LOG(ERR, NTNIC, "%s: profile_inline module uninitialized", __func__);
- return THREAD_RETURN;
- }
+ struct nt_service *flm_update_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_FLM_UPDATE);
+ RTE_ASSERT(flm_update_srv != NULL);
- struct drv_s *p_drv = context;
+ if (!NT_SERVICE_GET_STATE(flm_update_srv)) {
+ struct drv_s *p_drv = context;
+ RTE_ASSERT(p_drv != NULL);
- struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
- struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info;
- struct nt4ga_filter_s *p_nt4ga_filter = &p_adapter_info->nt4ga_filter;
- struct flow_nic_dev *p_flow_nic_dev = p_nt4ga_filter->mp_flow_device;
+ struct ntdrv_4ga_s *p_nt_drv = &p_drv->ntdrv;
+ struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info;
+ struct nt4ga_filter_s *p_nt4ga_filter = &p_adapter_info->nt4ga_filter;
+ struct flow_nic_dev *p_flow_nic_dev = p_nt4ga_filter->mp_flow_device;
- NT_LOG(DBG, NTNIC, "%s: %s: waiting for port configuration",
- p_adapter_info->mp_adapter_id_str, __func__);
+ NT_LOG(DBG, NTNIC, "%s: %s: waiting for port configuration",
+ p_adapter_info->mp_adapter_id_str, __func__);
- while (p_flow_nic_dev->eth_base == NULL)
- nt_os_wait_usec(1 * 1000 * 1000);
+ if (p_flow_nic_dev->eth_base == NULL)
+ return -1;
- struct flow_eth_dev *dev = p_flow_nic_dev->eth_base;
+ dev = p_flow_nic_dev->eth_base;
- NT_LOG(DBG, NTNIC, "%s: %s: begin", p_adapter_info->mp_adapter_id_str, __func__);
+ profile_inline_ops = get_profile_inline_ops();
+ RTE_ASSERT(profile_inline_ops != NULL);
- while (!p_drv->ntdrv.b_shutdown)
- if (profile_inline_ops->flm_update(dev) == 0)
- nt_os_wait_usec(10);
+ NT_LOG(INF, NTNIC, "flm update service started on lcore %i", rte_lcore_id());
+ flm_update_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(flm_update_srv, true);
+ return 0;
+ }
- NT_LOG(DBG, NTNIC, "%s: %s: end", p_adapter_info->mp_adapter_id_str, __func__);
- return THREAD_RETURN;
+ if (profile_inline_ops->flm_update(dev) == 0)
+ nt_os_wait_usec(10);
+
+ return 0;
}
/*
@@ -2346,8 +2353,16 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
if (profile_inline_ops != NULL && fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
profile_inline_ops->flm_setup_queues();
- res = THREAD_CTRL_CREATE(&p_nt_drv->flm_thread, "ntnic-nt_flm_update_thr",
- adapter_flm_update_thread_fn, (void *)p_drv);
+
+ struct rte_service_spec flm_update_spec = {
+ .name = "ntnic-flm_update_service",
+ .callback = adapter_flm_update_service,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = p_drv
+ };
+
+ res = nthw_service_add(&flm_update_spec, RTE_NTNIC_SERVICE_FLM_UPDATE);
if (res) {
NT_LOG_DBGX(ERR, NTNIC, "%s: error=%d",
diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
index fc06cf12c3..c6c448312f 100644
--- a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
+++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
@@ -6,6 +6,7 @@
#include <rte_flow_driver.h>
#include <rte_pci.h>
#include <rte_version.h>
+#include <rte_pmd_ntnic.h>
#include "ntlog.h"
#include "nt_util.h"
@@ -13,6 +14,8 @@
#include "ntnic_mod_reg.h"
#include "ntos_system.h"
#include "ntos_drv.h"
+#include "nt_service.h"
+#include "rte_service.h"
#define MAX_RTE_FLOWS 8192
@@ -543,6 +546,13 @@ eth_flow_destroy(struct rte_eth_dev *eth_dev, struct rte_flow *flow, struct rte_
return -1;
}
+ struct nt_service *srv = nthw_service_get_info(RTE_NTNIC_SERVICE_FLM_UPDATE);
+
+ if (!srv || !NT_SERVICE_GET_STATE(srv) || !rte_service_runstate_get(srv->id)) {
+ NT_LOG(ERR, FILTER, "flm update service is not started. Flow cannot be destroyed");
+ return -1;
+ }
+
struct pmd_internals *internals = eth_dev->data->dev_private;
error->type = RTE_FLOW_ERROR_TYPE_NONE;
@@ -580,6 +590,13 @@ static struct rte_flow *eth_flow_create(struct rte_eth_dev *eth_dev,
return NULL;
}
+ struct nt_service *srv = nthw_service_get_info(RTE_NTNIC_SERVICE_FLM_UPDATE);
+
+ if (!srv || !NT_SERVICE_GET_STATE(srv) || !rte_service_runstate_get(srv->id)) {
+ NT_LOG(ERR, FILTER, "flm update service is not started. Flow cannot be created");
+ return NULL;
+ }
+
struct pmd_internals *internals = eth_dev->data->dev_private;
struct fpga_info_s *fpga_info = &internals->p_drv->ntdrv.adapter_info.fpga_info;
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
index 4ef1233f12..86f709e401 100644
--- a/drivers/net/ntnic/ntutil/nt_service.c
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -12,8 +12,8 @@
#define NT_SERVICE_UNKNOWN_ID (-1)
static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
- [0] = {
- .tag = RTE_NTNIC_SERVICE_MAX,
+ [RTE_NTNIC_SERVICE_FLM_UPDATE] = {
+ .tag = RTE_NTNIC_SERVICE_FLM_UPDATE,
.id = NT_SERVICE_UNKNOWN_ID,
.lcore = RTE_MAX_LCORE,
.initialized = false,
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index 7a491319fa..d6236dae32 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -41,7 +41,8 @@ enum rte_ntnic_event_type {
};
enum rte_ntnic_service_tag {
- RTE_NTNIC_SERVICE_MAX = 1
+ RTE_NTNIC_SERVICE_FLM_UPDATE = 0,
+ RTE_NTNIC_SERVICE_MAX
};
/**
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 3/7] net/ntnic: migrate statistic thread to service
2025-09-08 14:17 ` [PATCH v2 0/7] migrate threads to DPDK service framework Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 1/7] net/ntnic: introduce service API for NTNIC PMD Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 2/7] net/ntnic: migrate flm update thread to service Serhii Iliushyk
@ 2025-09-08 14:17 ` Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 4/7] net/ntnic: migrate port event " Serhii Iliushyk
` (3 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 14:17 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
The statistic service is responsible for collecting statistics.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/include/ntdrv_4ga.h | 1 -
drivers/net/ntnic/ntnic_ethdev.c | 146 ++++++++++++++------------
drivers/net/ntnic/ntutil/nt_service.c | 6 ++
drivers/net/ntnic/rte_pmd_ntnic.h | 1 +
4 files changed, 84 insertions(+), 70 deletions(-)
diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h
index 35afcd546c..c143c0c2b6 100644
--- a/drivers/net/ntnic/include/ntdrv_4ga.h
+++ b/drivers/net/ntnic/include/ntdrv_4ga.h
@@ -16,7 +16,6 @@ typedef struct ntdrv_4ga_s {
volatile bool b_shutdown;
rte_spinlock_t stat_lck;
- rte_thread_t stat_thread;
rte_thread_t port_event_thread;
} ntdrv_4ga_t;
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index c114017db8..54c9e218bc 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -1542,9 +1542,9 @@ drv_deinit(struct drv_s *p_drv)
clear_pdrv(p_drv);
nt_os_wait_usec(1000000);
- /* stop statistics threads */
+ /* stop statistics service */
p_drv->ntdrv.b_shutdown = true;
- THREAD_JOIN(p_nt_drv->stat_thread);
+ nthw_service_del(RTE_NTNIC_SERVICE_STAT);
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
nthw_service_del(RTE_NTNIC_SERVICE_FLM_UPDATE);
@@ -2024,84 +2024,86 @@ static int adapter_flm_update_service(void *context)
}
/*
- * Adapter stat thread
+ * Adapter stat service
*/
-THREAD_FUNC adapter_stat_thread_fn(void *context)
+static int adapter_stat_service(void *context)
{
- const struct nt4ga_stat_ops *nt4ga_stat_ops = get_nt4ga_stat_ops();
+ static struct ntdrv_4ga_s *p_nt_drv;
+ static nt4ga_stat_t *p_nt4ga_stat;
+ static nthw_stat_t *p_nthw_stat;
+ static const struct nt4ga_stat_ops *nt4ga_stat_ops;
- if (nt4ga_stat_ops == NULL) {
- NT_LOG_DBGX(ERR, NTNIC, "Statistics module uninitialized");
- return THREAD_RETURN;
- }
+ struct nt_service *stat_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_STAT);
+ RTE_ASSERT(stat_srv != NULL);
- struct drv_s *p_drv = context;
+ if (!NT_SERVICE_GET_STATE(stat_srv)) {
+ struct drv_s *p_drv = context;
+ RTE_ASSERT(p_drv != NULL);
- ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
- nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
- nthw_stat_t *p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
- const char *const p_adapter_id_str = p_nt_drv->adapter_info.mp_adapter_id_str;
- (void)p_adapter_id_str;
+ nt4ga_stat_ops = get_nt4ga_stat_ops();
+ RTE_ASSERT(nt4ga_stat_ops != NULL);
- if (!p_nthw_stat)
- return THREAD_RETURN;
+ p_nt_drv = &p_drv->ntdrv;
+ p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
+ p_nthw_stat = p_nt4ga_stat->mp_nthw_stat;
- NT_LOG_DBGX(DBG, NTNIC, "%s: begin", p_adapter_id_str);
+ if (!p_nthw_stat)
+ return 0;
- RTE_ASSERT(p_nthw_stat);
+ NT_LOG(INF, NTNIC, "statistic service started on lcore %u", rte_lcore_id());
+ stat_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(stat_srv, true);
+ return 0;
+ }
- while (!p_drv->ntdrv.b_shutdown) {
- nt_os_wait_usec(10 * 1000);
-
- nthw_stat_trigger(p_nthw_stat);
-
- uint32_t loop = 0;
-
- while ((!p_drv->ntdrv.b_shutdown) &&
- (*p_nthw_stat->mp_timestamp == (uint64_t)-1)) {
- nt_os_wait_usec(1 * 100);
-
- if (rte_log_get_level(nt_log_ntnic) == RTE_LOG_DEBUG &&
- (++loop & 0x3fff) == 0) {
- if (p_nt4ga_stat->mp_nthw_rpf) {
- NT_LOG(ERR, NTNIC, "Statistics DMA frozen");
-
- } else if (p_nt4ga_stat->mp_nthw_rmc) {
- uint32_t sf_ram_of =
- nthw_rmc_get_status_sf_ram_of(p_nt4ga_stat
- ->mp_nthw_rmc);
- uint32_t descr_fifo_of =
- nthw_rmc_get_status_descr_fifo_of(p_nt4ga_stat
- ->mp_nthw_rmc);
-
- uint32_t dbg_merge =
- nthw_rmc_get_dbg_merge(p_nt4ga_stat->mp_nthw_rmc);
- uint32_t mac_if_err =
- nthw_rmc_get_mac_if_err(p_nt4ga_stat->mp_nthw_rmc);
-
- NT_LOG(ERR, NTNIC, "Statistics DMA frozen");
- NT_LOG(ERR, NTNIC, "SF RAM Overflow : %08x",
- sf_ram_of);
- NT_LOG(ERR, NTNIC, "Descr Fifo Overflow : %08x",
- descr_fifo_of);
- NT_LOG(ERR, NTNIC, "DBG Merge : %08x",
- dbg_merge);
- NT_LOG(ERR, NTNIC, "MAC If Errors : %08x",
- mac_if_err);
- }
+ nt_os_wait_usec(10 * 1000);
+
+ nthw_stat_trigger(p_nthw_stat);
+
+ uint32_t loop = 0;
+
+ while (rte_service_runstate_get(stat_srv->id) &&
+ (*p_nthw_stat->mp_timestamp == (uint64_t)-1)) {
+ nt_os_wait_usec(1 * 100);
+
+ if ((++loop & 0x3fff) == 0) {
+ if (p_nt4ga_stat->mp_nthw_rpf) {
+ NT_LOG(DBG, NTNIC, "Statistics DMA frozen");
+
+ } else if (p_nt4ga_stat->mp_nthw_rmc) {
+ uint32_t sf_ram_of =
+ nthw_rmc_get_status_sf_ram_of(p_nt4ga_stat
+ ->mp_nthw_rmc);
+ uint32_t descr_fifo_of =
+ nthw_rmc_get_status_descr_fifo_of(p_nt4ga_stat
+ ->mp_nthw_rmc);
+
+ uint32_t dbg_merge =
+ nthw_rmc_get_dbg_merge(p_nt4ga_stat->mp_nthw_rmc);
+ uint32_t mac_if_err =
+ nthw_rmc_get_mac_if_err(p_nt4ga_stat->mp_nthw_rmc);
+
+ NT_LOG(DBG, NTNIC, "Statistics DMA frozen");
+ NT_LOG(DBG, NTNIC, "SF RAM Overflow : %08x",
+ sf_ram_of);
+ NT_LOG(DBG, NTNIC, "Descr Fifo Overflow : %08x",
+ descr_fifo_of);
+ NT_LOG(DBG, NTNIC, "DBG Merge : %08x",
+ dbg_merge);
+ NT_LOG(DBG, NTNIC, "MAC If Errors : %08x",
+ mac_if_err);
}
}
+ }
- /* Check then collect */
- {
- rte_spinlock_lock(&p_nt_drv->stat_lck);
- nt4ga_stat_ops->nt4ga_stat_collect(&p_nt_drv->adapter_info, p_nt4ga_stat);
- rte_spinlock_unlock(&p_nt_drv->stat_lck);
- }
+ /* Check then collect */
+ {
+ rte_spinlock_lock(&p_nt_drv->stat_lck);
+ nt4ga_stat_ops->nt4ga_stat_collect(&p_nt_drv->adapter_info, p_nt4ga_stat);
+ rte_spinlock_unlock(&p_nt_drv->stat_lck);
}
- NT_LOG_DBGX(DBG, NTNIC, "%s: end", p_adapter_id_str);
- return THREAD_RETURN;
+ return 0;
}
static int
@@ -2371,9 +2373,15 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
}
}
- rte_spinlock_init(&p_nt_drv->stat_lck);
- res = THREAD_CTRL_CREATE(&p_nt_drv->stat_thread, "nt4ga_stat_thr", adapter_stat_thread_fn,
- (void *)p_drv);
+ struct rte_service_spec stat_spec = {
+ .name = "ntnic-stat_collect_service",
+ .callback = adapter_stat_service,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = p_drv
+ };
+
+ res = nthw_service_add(&stat_spec, RTE_NTNIC_SERVICE_STAT);
if (res) {
NT_LOG(ERR, NTNIC, "%s: error=%d",
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
index 86f709e401..c109b44483 100644
--- a/drivers/net/ntnic/ntutil/nt_service.c
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -18,6 +18,12 @@ static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
.lcore = RTE_MAX_LCORE,
.initialized = false,
},
+ [RTE_NTNIC_SERVICE_STAT] = {
+ .tag = RTE_NTNIC_SERVICE_STAT,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
};
inline struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index d6236dae32..6fe6541984 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -42,6 +42,7 @@ enum rte_ntnic_event_type {
enum rte_ntnic_service_tag {
RTE_NTNIC_SERVICE_FLM_UPDATE = 0,
+ RTE_NTNIC_SERVICE_STAT = 1,
RTE_NTNIC_SERVICE_MAX
};
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 4/7] net/ntnic: migrate port event thread to service
2025-09-08 14:17 ` [PATCH v2 0/7] migrate threads to DPDK service framework Serhii Iliushyk
` (2 preceding siblings ...)
2025-09-08 14:17 ` [PATCH v2 3/7] net/ntnic: migrate statistic " Serhii Iliushyk
@ 2025-09-08 14:17 ` Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 5/7] net/ntnic: migrate adapter mon " Serhii Iliushyk
` (2 subsequent siblings)
6 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 14:17 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
The port event service is responsible for handling port events.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/include/ntdrv_4ga.h | 1 -
drivers/net/ntnic/include/ntos_drv.h | 2 +-
drivers/net/ntnic/ntnic_ethdev.c | 271 +++++++++++++++-----------
drivers/net/ntnic/ntutil/nt_service.c | 12 ++
drivers/net/ntnic/rte_pmd_ntnic.h | 2 +
5 files changed, 174 insertions(+), 114 deletions(-)
diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h
index c143c0c2b6..ee0e66c4d4 100644
--- a/drivers/net/ntnic/include/ntdrv_4ga.h
+++ b/drivers/net/ntnic/include/ntdrv_4ga.h
@@ -16,7 +16,6 @@ typedef struct ntdrv_4ga_s {
volatile bool b_shutdown;
rte_spinlock_t stat_lck;
- rte_thread_t port_event_thread;
} ntdrv_4ga_t;
#endif /* __NTDRV_4GA_H__ */
diff --git a/drivers/net/ntnic/include/ntos_drv.h b/drivers/net/ntnic/include/ntos_drv.h
index 047c077057..e6e46f8cc1 100644
--- a/drivers/net/ntnic/include/ntos_drv.h
+++ b/drivers/net/ntnic/include/ntos_drv.h
@@ -21,7 +21,7 @@
#define NUM_MULTICAST_ADDRS_PER_PORT (16U)
#define NUM_ADAPTER_MAX (8)
-#define NUM_ADAPTER_PORTS_MAX (128)
+#define NUM_ADAPTER_PORTS_MAX (2)
/* Max RSS queues */
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index 54c9e218bc..7ec1c94a14 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -1549,7 +1549,8 @@ drv_deinit(struct drv_s *p_drv)
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
nthw_service_del(RTE_NTNIC_SERVICE_FLM_UPDATE);
profile_inline_ops->flm_free_queues();
- THREAD_JOIN(p_nt_drv->port_event_thread);
+ nthw_service_del(RTE_NTNIC_SERVICE_PORT_0_EVENT);
+ nthw_service_del(RTE_NTNIC_SERVICE_PORT_1_EVENT);
/* Free all local flm event queues */
nthw_flm_inf_sta_queue_free_all(FLM_INFO_LOCAL);
/* Free all remote flm event queues */
@@ -1849,135 +1850,168 @@ static struct eth_dev_ops nthw_eth_dev_ops = {
};
/*
- * Port event thread
+ * Port event service
*/
-THREAD_FUNC port_event_thread_fn(void *context)
+static int port_event_service(void *context)
{
struct pmd_internals *internals = context;
- struct drv_s *p_drv = internals->p_drv;
- ntdrv_4ga_t *p_nt_drv = &p_drv->ntdrv;
- struct adapter_info_s *p_adapter_info = &p_nt_drv->adapter_info;
- struct flow_nic_dev *ndev = p_adapter_info->nt4ga_filter.mp_flow_device;
+ RTE_ASSERT(internals != NULL);
- nt4ga_stat_t *p_nt4ga_stat = &p_nt_drv->adapter_info.nt4ga_stat;
- struct rte_eth_dev *eth_dev = &rte_eth_devices[internals->port_id];
- uint8_t port_no = internals->port;
+ const uint8_t port_no = internals->port;
+ if (port_no >= NUM_ADAPTER_PORTS_MAX) {
+ NT_LOG(ERR, NTNIC, "Invalid Port number");
+ return -1;
+ }
- ntnic_flm_load_t flmdata;
- ntnic_port_load_t portdata;
+ static ntdrv_4ga_t *p_nt_drv[NUM_ADAPTER_PORTS_MAX] = {NULL, NULL};
+ static struct rte_eth_dev *eth_dev[NUM_ADAPTER_PORTS_MAX] = {NULL, NULL};
+ static nt4ga_stat_t *p_nt4ga_stat[NUM_ADAPTER_PORTS_MAX] = {NULL, NULL};
+ static ntnic_flm_load_t flmdata[NUM_ADAPTER_PORTS_MAX];
+ static ntnic_port_load_t portdata[NUM_ADAPTER_PORTS_MAX];
- memset(&flmdata, 0, sizeof(flmdata));
- memset(&portdata, 0, sizeof(portdata));
+ const int port_srv_tag[2] = {
+ RTE_NTNIC_SERVICE_PORT_0_EVENT,
+ RTE_NTNIC_SERVICE_PORT_1_EVENT
+ };
- while (ndev != NULL && ndev->eth_base == NULL)
- nt_os_wait_usec(1 * 1000 * 1000);
+ struct nt_service *port_event_srv = nthw_service_get_info(port_srv_tag[port_no]);
+ RTE_ASSERT(port_event_srv != NULL);
+
+ if (!NT_SERVICE_GET_STATE(port_event_srv)) {
+ struct drv_s *p_drv = internals->p_drv;
+ p_nt_drv[port_no] = &p_drv->ntdrv;
+ struct adapter_info_s *p_adapter_info = &p_nt_drv[port_no]->adapter_info;
+ struct flow_nic_dev *ndev = p_adapter_info->nt4ga_filter.mp_flow_device;
+ p_nt4ga_stat[port_no] = &p_nt_drv[port_no]->adapter_info.nt4ga_stat;
+ eth_dev[port_no] = &rte_eth_devices[internals->port_id];
+ if (ndev != NULL && ndev->eth_base == NULL)
+ return -1;
- while (!p_drv->ntdrv.b_shutdown) {
- /*
- * FLM load measurement
- * Do only send event, if there has been a change
- */
- if (p_nt4ga_stat->flm_stat_ver > 22 && p_nt4ga_stat->mp_stat_structs_flm) {
- if (flmdata.lookup != p_nt4ga_stat->mp_stat_structs_flm->load_lps ||
- flmdata.access != p_nt4ga_stat->mp_stat_structs_flm->load_aps) {
- rte_spinlock_lock(&p_nt_drv->stat_lck);
- flmdata.lookup = p_nt4ga_stat->mp_stat_structs_flm->load_lps;
- flmdata.access = p_nt4ga_stat->mp_stat_structs_flm->load_aps;
- flmdata.lookup_maximum =
- p_nt4ga_stat->mp_stat_structs_flm->max_lps;
- flmdata.access_maximum =
- p_nt4ga_stat->mp_stat_structs_flm->max_aps;
- rte_spinlock_unlock(&p_nt_drv->stat_lck);
-
- if (eth_dev && eth_dev->data && eth_dev->data->dev_private) {
- rte_eth_dev_callback_process(eth_dev,
- (enum rte_eth_event_type)RTE_NTNIC_FLM_LOAD_EVENT,
- &flmdata);
- }
+ memset(&flmdata, 0, sizeof(flmdata));
+ memset(&portdata, 0, sizeof(portdata));
+
+
+ NT_LOG(INF, NTNIC, "port[%u] event service started on lcore %i",
+ port_no, rte_lcore_id());
+ port_event_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(port_event_srv, true);
+ return 0;
+ }
+
+ /*
+ * FLM load measurement
+ * Do only send event, if there has been a change
+ */
+
+ nt4ga_stat_t *port_stat = p_nt4ga_stat[port_no];
+ ntnic_flm_load_t *port_flm_load = &flmdata[port_no];
+ ntnic_port_load_t *port_load = &portdata[port_no];
+
+ if (port_stat->flm_stat_ver > 22 && port_stat->mp_stat_structs_flm) {
+ if (port_flm_load->lookup != port_stat->mp_stat_structs_flm->load_lps ||
+ port_flm_load->access != port_stat->mp_stat_structs_flm->load_aps) {
+ rte_spinlock_lock(&p_nt_drv[port_no]->stat_lck);
+ port_flm_load->lookup = port_stat->mp_stat_structs_flm->load_lps;
+ port_flm_load->access = port_stat->mp_stat_structs_flm->load_aps;
+ port_flm_load->lookup_maximum =
+ port_stat->mp_stat_structs_flm->max_lps;
+ port_flm_load->access_maximum =
+ port_stat->mp_stat_structs_flm->max_aps;
+ rte_spinlock_unlock(&p_nt_drv[port_no]->stat_lck);
+
+ if (eth_dev[port_no] &&
+ eth_dev[port_no]->data &&
+ eth_dev[port_no]->data->dev_private) {
+ rte_eth_dev_callback_process(eth_dev[port_no],
+ (enum rte_eth_event_type)RTE_NTNIC_FLM_LOAD_EVENT,
+ &flmdata);
}
}
+ }
- /*
- * Port load measurement
- * Do only send event, if there has been a change.
- */
- if (p_nt4ga_stat->mp_port_load) {
- if (portdata.rx_bps != p_nt4ga_stat->mp_port_load[port_no].rx_bps ||
- portdata.tx_bps != p_nt4ga_stat->mp_port_load[port_no].tx_bps) {
- rte_spinlock_lock(&p_nt_drv->stat_lck);
- portdata.rx_bps = p_nt4ga_stat->mp_port_load[port_no].rx_bps;
- portdata.tx_bps = p_nt4ga_stat->mp_port_load[port_no].tx_bps;
- portdata.rx_pps = p_nt4ga_stat->mp_port_load[port_no].rx_pps;
- portdata.tx_pps = p_nt4ga_stat->mp_port_load[port_no].tx_pps;
- portdata.rx_pps_maximum =
- p_nt4ga_stat->mp_port_load[port_no].rx_pps_max;
- portdata.tx_pps_maximum =
- p_nt4ga_stat->mp_port_load[port_no].tx_pps_max;
- portdata.rx_bps_maximum =
- p_nt4ga_stat->mp_port_load[port_no].rx_bps_max;
- portdata.tx_bps_maximum =
- p_nt4ga_stat->mp_port_load[port_no].tx_bps_max;
- rte_spinlock_unlock(&p_nt_drv->stat_lck);
-
- if (eth_dev && eth_dev->data && eth_dev->data->dev_private) {
- rte_eth_dev_callback_process(eth_dev,
- (enum rte_eth_event_type)RTE_NTNIC_PORT_LOAD_EVENT,
- &portdata);
- }
+ /*
+ * Port load measurement
+ * Do only send event, if there has been a change.
+ */
+ if (port_stat->mp_port_load) {
+ if (port_load->rx_bps != port_stat->mp_port_load[port_no].rx_bps ||
+ port_load->tx_bps != port_stat->mp_port_load[port_no].tx_bps) {
+ rte_spinlock_lock(&p_nt_drv[port_no]->stat_lck);
+ port_load->rx_bps = port_stat->mp_port_load[port_no].rx_bps;
+ port_load->tx_bps = port_stat->mp_port_load[port_no].tx_bps;
+ port_load->rx_pps = port_stat->mp_port_load[port_no].rx_pps;
+ port_load->tx_pps = port_stat->mp_port_load[port_no].tx_pps;
+ port_load->rx_pps_maximum =
+ port_stat->mp_port_load[port_no].rx_pps_max;
+ port_load->tx_pps_maximum =
+ port_stat->mp_port_load[port_no].tx_pps_max;
+ port_load->rx_bps_maximum =
+ port_stat->mp_port_load[port_no].rx_bps_max;
+ port_load->tx_bps_maximum =
+ port_stat->mp_port_load[port_no].tx_bps_max;
+ rte_spinlock_unlock(&p_nt_drv[port_no]->stat_lck);
+
+ if (eth_dev[port_no] && eth_dev[port_no]->data &&
+ eth_dev[port_no]->data->dev_private) {
+ rte_eth_dev_callback_process(eth_dev[port_no],
+ (enum rte_eth_event_type)RTE_NTNIC_PORT_LOAD_EVENT,
+ &portdata);
}
}
+ }
- /* Process events */
- {
- int count = 0;
- bool do_wait = true;
-
- while (count < 5000) {
- /* Local FLM statistic events */
- struct flm_info_event_s data;
-
- if (nthw_flm_inf_queue_get(port_no, FLM_INFO_LOCAL, &data) == 0) {
- if (eth_dev && eth_dev->data &&
- eth_dev->data->dev_private) {
- struct ntnic_flm_statistic_s event_data;
- event_data.bytes = data.bytes;
- event_data.packets = data.packets;
- event_data.cause = data.cause;
- event_data.id = data.id;
- event_data.timestamp = data.timestamp;
- rte_eth_dev_callback_process(eth_dev,
- (enum rte_eth_event_type)
- RTE_NTNIC_FLM_STATS_EVENT,
- &event_data);
- do_wait = false;
- }
- }
-
- /* AGED event */
- /* Note: RTE_FLOW_PORT_FLAG_STRICT_QUEUE flag is not supported so
- * event is always generated
- */
- int aged_event_count = flm_age_event_get(port_no);
-
- if (aged_event_count > 0 && eth_dev && eth_dev->data &&
- eth_dev->data->dev_private) {
- rte_eth_dev_callback_process(eth_dev,
- RTE_ETH_EVENT_FLOW_AGED,
- NULL);
- flm_age_event_clear(port_no);
+ /* Process events */
+ {
+ int count = 0;
+ bool do_wait = true;
+
+ while (count < 5000) {
+ /* Local FLM statistic events */
+ struct flm_info_event_s data;
+
+ if (nthw_flm_inf_queue_get(port_no, FLM_INFO_LOCAL, &data) == 0) {
+ if (eth_dev[port_no] && eth_dev[port_no]->data &&
+ eth_dev[port_no]->data->dev_private) {
+ struct ntnic_flm_statistic_s event_data;
+ event_data.bytes = data.bytes;
+ event_data.packets = data.packets;
+ event_data.cause = data.cause;
+ event_data.id = data.id;
+ event_data.timestamp = data.timestamp;
+ rte_eth_dev_callback_process(eth_dev[port_no],
+ (enum rte_eth_event_type)
+ RTE_NTNIC_FLM_STATS_EVENT,
+ &event_data);
do_wait = false;
}
+ }
- if (do_wait)
- nt_os_wait_usec(10);
-
- count++;
- do_wait = true;
+ /* AGED event */
+ /* Note: RTE_FLOW_PORT_FLAG_STRICT_QUEUE flag is not supported so
+ * event is always generated
+ */
+ int aged_event_count = flm_age_event_get(port_no);
+
+ if (aged_event_count > 0 &&
+ eth_dev[port_no] &&
+ eth_dev[port_no]->data &&
+ eth_dev[port_no]->data->dev_private) {
+ rte_eth_dev_callback_process(eth_dev[port_no],
+ RTE_ETH_EVENT_FLOW_AGED,
+ NULL);
+ flm_age_event_clear(port_no);
+ do_wait = false;
}
+
+ if (do_wait)
+ nt_os_wait_usec(10);
+
+ count++;
+ do_wait = true;
}
}
- return THREAD_RETURN;
+ return 0;
}
/*
@@ -2547,10 +2581,23 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
}
}
- /* Port event thread */
+ /* Port event service */
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
- res = THREAD_CTRL_CREATE(&p_nt_drv->port_event_thread, "nt_port_event_thr",
- port_event_thread_fn, (void *)internals);
+ struct rte_service_spec port_event_spec = {
+ .callback = port_event_service,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = internals
+ };
+
+ sprintf(port_event_spec.name, "ntnic-port_%d_event_service", n_intf_no);
+
+ const int port_srv_tag[2] = {
+ RTE_NTNIC_SERVICE_PORT_0_EVENT,
+ RTE_NTNIC_SERVICE_PORT_1_EVENT
+ };
+
+ res = nthw_service_add(&port_event_spec, port_srv_tag[n_intf_no]);
if (res) {
NT_LOG(ERR, NTNIC, "%s: error=%d",
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
index c109b44483..9f22ee2bba 100644
--- a/drivers/net/ntnic/ntutil/nt_service.c
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -24,6 +24,18 @@ static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
.lcore = RTE_MAX_LCORE,
.initialized = false,
},
+ [RTE_NTNIC_SERVICE_PORT_0_EVENT] = {
+ .tag = RTE_NTNIC_SERVICE_PORT_0_EVENT,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
+ [RTE_NTNIC_SERVICE_PORT_1_EVENT] = {
+ .tag = RTE_NTNIC_SERVICE_PORT_1_EVENT,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
};
inline struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index 6fe6541984..1a68cb8e37 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -43,6 +43,8 @@ enum rte_ntnic_event_type {
enum rte_ntnic_service_tag {
RTE_NTNIC_SERVICE_FLM_UPDATE = 0,
RTE_NTNIC_SERVICE_STAT = 1,
+ RTE_NTNIC_SERVICE_PORT_0_EVENT = 2,
+ RTE_NTNIC_SERVICE_PORT_1_EVENT = 3,
RTE_NTNIC_SERVICE_MAX
};
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 5/7] net/ntnic: migrate adapter mon thread to service
2025-09-08 14:17 ` [PATCH v2 0/7] migrate threads to DPDK service framework Serhii Iliushyk
` (3 preceding siblings ...)
2025-09-08 14:17 ` [PATCH v2 4/7] net/ntnic: migrate port event " Serhii Iliushyk
@ 2025-09-08 14:17 ` Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 6/7] net/ntnic: add warning about service cores Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 7/7] net/ntnic: cleanup using pthreads and rte_thread Serhii Iliushyk
6 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 14:17 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
The adapter monitor service is responsible for link state management.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/adapter/nt4ga_adapter.c | 25 +-
.../net/ntnic/include/common_adapter_defs.h | 15 -
drivers/net/ntnic/include/nt4ga_adapter.h | 3 -
drivers/net/ntnic/include/ntnic_stat.h | 2 +-
drivers/net/ntnic/include/ntos_drv.h | 2 +-
.../link_mgmt/link_100g/nt4ga_link_100g.c | 303 +++++++++--------
.../link_agx_100g/nt4ga_agx_link_100g.c | 306 ++++++++++--------
drivers/net/ntnic/ntutil/nt_service.c | 6 +
drivers/net/ntnic/rte_pmd_ntnic.h | 1 +
9 files changed, 334 insertions(+), 329 deletions(-)
delete mode 100644 drivers/net/ntnic/include/common_adapter_defs.h
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c
index 526ecc8089..363874c85f 100644
--- a/drivers/net/ntnic/adapter/nt4ga_adapter.c
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c
@@ -5,6 +5,7 @@
#include <rte_thread.h>
+#include "nt_service.h"
#include "ntlog.h"
#include "nthw_fpga.h"
#include "ntnic_mod_reg.h"
@@ -12,28 +13,6 @@
/*
* Global variables shared by NT adapter types
*/
-rte_thread_t monitor_tasks[NUM_ADAPTER_MAX];
-volatile int monitor_task_is_running[NUM_ADAPTER_MAX];
-
-/*
- * Signal-handler to stop all monitor threads
- */
-static void stop_monitor_tasks(int signum)
-{
- const size_t N = ARRAY_SIZE(monitor_task_is_running);
- size_t i;
-
- /* Stop all monitor tasks */
- for (i = 0; i < N; i++) {
- const int is_running = monitor_task_is_running[i];
- monitor_task_is_running[i] = 0;
-
- if (signum == -1 && is_running != 0) {
- rte_thread_join(monitor_tasks[i], NULL);
- memset(&monitor_tasks[i], 0, sizeof(monitor_tasks[0]));
- }
- }
-}
static int nt4ga_adapter_show_info(struct adapter_info_s *p_adapter_info, FILE *pfh)
{
@@ -255,7 +234,7 @@ static int nt4ga_adapter_deinit(struct adapter_info_s *p_adapter_info)
int i;
int res = -1;
- stop_monitor_tasks(-1);
+ nthw_service_del(RTE_NTNIC_SERVICE_ADAPTER_MON);
/* Nt4ga Deinit Filter */
nt4ga_filter_t *p_filter = &p_adapter_info->nt4ga_filter;
diff --git a/drivers/net/ntnic/include/common_adapter_defs.h b/drivers/net/ntnic/include/common_adapter_defs.h
deleted file mode 100644
index 6ed9121f0f..0000000000
--- a/drivers/net/ntnic/include/common_adapter_defs.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2023 Napatech A/S
- */
-
-#ifndef _COMMON_ADAPTER_DEFS_H_
-#define _COMMON_ADAPTER_DEFS_H_
-
-/*
- * Declarations shared by NT adapter types.
- */
-#define NUM_ADAPTER_MAX (8)
-#define NUM_ADAPTER_PORTS_MAX (128)
-
-#endif /* _COMMON_ADAPTER_DEFS_H_ */
diff --git a/drivers/net/ntnic/include/nt4ga_adapter.h b/drivers/net/ntnic/include/nt4ga_adapter.h
index 7396b8ab65..6c701b601f 100644
--- a/drivers/net/ntnic/include/nt4ga_adapter.h
+++ b/drivers/net/ntnic/include/nt4ga_adapter.h
@@ -47,8 +47,5 @@ typedef struct adapter_info_s {
int n_tx_host_buffers;
} adapter_info_t;
-extern rte_thread_t monitor_tasks[NUM_ADAPTER_MAX];
-extern volatile int monitor_task_is_running[NUM_ADAPTER_MAX];
-
#endif /* _NT4GA_ADAPTER_H_ */
diff --git a/drivers/net/ntnic/include/ntnic_stat.h b/drivers/net/ntnic/include/ntnic_stat.h
index 1b53f6c347..928c629fb2 100644
--- a/drivers/net/ntnic/include/ntnic_stat.h
+++ b/drivers/net/ntnic/include/ntnic_stat.h
@@ -6,7 +6,7 @@
#ifndef NTNIC_STAT_H_
#define NTNIC_STAT_H_
-#include "common_adapter_defs.h"
+#include "ntos_drv.h"
#include "nthw_rmc.h"
#include "nthw_rpf.h"
#include "nthw_fpga_model.h"
diff --git a/drivers/net/ntnic/include/ntos_drv.h b/drivers/net/ntnic/include/ntos_drv.h
index e6e46f8cc1..f353a5eca8 100644
--- a/drivers/net/ntnic/include/ntos_drv.h
+++ b/drivers/net/ntnic/include/ntos_drv.h
@@ -20,7 +20,7 @@
#define NUM_MAC_ADDRS_PER_PORT (16U)
#define NUM_MULTICAST_ADDRS_PER_PORT (16U)
-#define NUM_ADAPTER_MAX (8)
+#define NUM_ADAPTER_MAX (1)
#define NUM_ADAPTER_PORTS_MAX (2)
diff --git a/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c b/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c
index adb187d322..21e95d84bd 100644
--- a/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_100g/nt4ga_link_100g.c
@@ -9,6 +9,7 @@
#include "ntlog.h"
#include "i2c_nim.h"
#include "ntnic_mod_reg.h"
+#include "nt_service.h"
/*
* Swap tx/rx polarity
@@ -478,170 +479,178 @@ static int _port_init(adapter_info_t *drv, nthw_fpga_t *fpga, int port)
*/
static int _common_ptp_nim_state_machine(void *data)
{
- adapter_info_t *drv = (adapter_info_t *)data;
- fpga_info_t *fpga_info = &drv->fpga_info;
- nt4ga_link_t *link_info = &drv->nt4ga_link;
- nthw_fpga_t *fpga = fpga_info->mp_fpga;
- const int adapter_no = drv->adapter_no;
- const int nb_ports = fpga_info->n_phy_ports;
- uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
+ static adapter_info_t *drv;
+ static nt4ga_link_t *link_info;
+ static nthw_fpga_t *fpga;
+ static int nb_ports;
+ static nim_i2c_ctx_t *nim_ctx;
+ static link_state_t *link_state;
+ static nthw_mac_pcs_t *mac_pcs;
+ static nthw_gpio_phy_t *gpio_phy;
+ static uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
+
+ struct nt_service *adapter_mon_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_ADAPTER_MON);
+ RTE_ASSERT(adapter_mon_srv != NULL);
+
+ if (!NT_SERVICE_GET_STATE(adapter_mon_srv)) {
+ drv = (adapter_info_t *)data;
+ RTE_ASSERT(drv != NULL);
+
+ fpga_info_t *fpga_info = &drv->fpga_info;
+ int adapter_no = drv->adapter_no;
+
+ link_info = &drv->nt4ga_link;
+ fpga = fpga_info->mp_fpga;
+ nb_ports = fpga_info->n_phy_ports;
+
+ if (!fpga) {
+ NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
+ return -1;
+ }
- nim_i2c_ctx_t *nim_ctx;
- link_state_t *link_state;
- nthw_mac_pcs_t *mac_pcs;
- nthw_gpio_phy_t *gpio_phy;
+ RTE_ASSERT(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
+ nim_ctx = link_info->u.var100g.nim_ctx;
+ link_state = link_info->link_state;
+ mac_pcs = link_info->u.var100g.mac_pcs100g;
+ gpio_phy = link_info->u.var100g.gpio_phy;
- if (!fpga) {
- NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
- goto NT4GA_LINK_100G_MON_EXIT;
- }
+ memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
- RTE_ASSERT(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
- nim_ctx = link_info->u.var100g.nim_ctx;
- link_state = link_info->link_state;
- mac_pcs = link_info->u.var100g.mac_pcs100g;
- gpio_phy = link_info->u.var100g.gpio_phy;
+ NT_LOG(DBG, NTNIC, "%s: link state machine running...", drv->mp_adapter_id_str);
- monitor_task_is_running[adapter_no] = 1;
- memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
+ NT_LOG(INF, NTNIC, "Adapter monitor service started on lcore %i", rte_lcore_id());
+ adapter_mon_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(adapter_mon_srv, true);
+ return 0;
+ }
- if (monitor_task_is_running[adapter_no])
- NT_LOG(DBG, NTNIC, "%s: link state machine running...", drv->mp_adapter_id_str);
+ int i;
+ static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
- while (monitor_task_is_running[adapter_no]) {
- int i;
- static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
+ for (i = 0; i < nb_ports; i++) {
+ link_state_t new_link_state;
+ const bool is_port_disabled = link_info->port_action[i].port_disable;
+ const bool was_port_disabled = link_state[i].link_disabled;
+ const bool disable_port = is_port_disabled && !was_port_disabled;
+ const bool enable_port = !is_port_disabled && was_port_disabled;
- for (i = 0; i < nb_ports; i++) {
- link_state_t new_link_state;
- const bool is_port_disabled = link_info->port_action[i].port_disable;
- const bool was_port_disabled = link_state[i].link_disabled;
- const bool disable_port = is_port_disabled && !was_port_disabled;
- const bool enable_port = !is_port_disabled && was_port_disabled;
+ if (!rte_service_runstate_get(adapter_mon_srv->id)) /* stop quickly */
+ break;
- if (!monitor_task_is_running[adapter_no]) /* stop quickly */
- break;
+ /* Has the administrative port state changed? */
+ RTE_ASSERT(!(disable_port && enable_port));
+
+ if (disable_port) {
+ memset(&link_state[i], 0, sizeof(link_state[i]));
+ link_info->link_info[i].link_speed = NT_LINK_SPEED_UNKNOWN;
+ link_state[i].link_disabled = true;
+ reported_link[i] = false;
+ /* Turn off laser and LED, etc. */
+ (void)_create_nim(drv, i, false);
+ NT_LOG(DBG, NTNIC, "%s: Port %i is disabled",
+ drv->mp_port_id_str[i], i);
+ continue;
+ }
- /* Has the administrative port state changed? */
- RTE_ASSERT(!(disable_port && enable_port));
-
- if (disable_port) {
- memset(&link_state[i], 0, sizeof(link_state[i]));
- link_info->link_info[i].link_speed = NT_LINK_SPEED_UNKNOWN;
- link_state[i].link_disabled = true;
- reported_link[i] = false;
- /* Turn off laser and LED, etc. */
- (void)_create_nim(drv, i, false);
- NT_LOG(DBG, NTNIC, "%s: Port %i is disabled",
- drv->mp_port_id_str[i], i);
- continue;
- }
+ if (enable_port) {
+ link_state[i].link_disabled = false;
+ NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
+ drv->mp_port_id_str[i], i);
+ }
- if (enable_port) {
- link_state[i].link_disabled = false;
- NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
- drv->mp_port_id_str[i], i);
+ if (is_port_disabled)
+ continue;
+
+ if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
+ /* Loopback mode has changed. Do something */
+ if (!_nim_is_present(&gpio_phy[i], (uint8_t)i)) {
+ /*
+ * If there is no Nim present, we need to initialize the
+ * port anyway
+ */
+ _port_init(drv, fpga, i);
}
- if (is_port_disabled)
- continue;
+ NT_LOG(INF, NTNIC, "%s: Loopback mode changed=%u",
+ drv->mp_port_id_str[i],
+ link_info->port_action[i].port_lpbk_mode);
+ _set_loopback(drv,
+ &mac_pcs[i],
+ i,
+ link_info->port_action[i].port_lpbk_mode,
+ last_lpbk_mode[i]);
- if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
- /* Loopback mode has changed. Do something */
- if (!_nim_is_present(&gpio_phy[i], (uint8_t)i)) {
- /*
- * If there is no Nim present, we need to initialize the
- * port anyway
- */
- _port_init(drv, fpga, i);
- }
-
- NT_LOG(INF, NTNIC, "%s: Loopback mode changed=%u",
- drv->mp_port_id_str[i],
- link_info->port_action[i].port_lpbk_mode);
- _set_loopback(drv,
- &mac_pcs[i],
- i,
- link_info->port_action[i].port_lpbk_mode,
- last_lpbk_mode[i]);
-
- if (link_info->port_action[i].port_lpbk_mode == 1)
- link_state[i].link_up = true;
-
- last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode;
- continue;
- }
+ if (link_info->port_action[i].port_lpbk_mode == 1)
+ link_state[i].link_up = true;
- (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i, &new_link_state,
- is_port_disabled);
+ last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode;
+ continue;
+ }
- if (!new_link_state.nim_present) {
- if (link_state[i].nim_present) {
- NT_LOG(INF, NTNIC, "%s: NIM module removed",
- drv->mp_port_id_str[i]);
- }
+ (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i, &new_link_state,
+ is_port_disabled);
- link_state[i] = new_link_state;
- continue;
+ if (!new_link_state.nim_present) {
+ if (link_state[i].nim_present) {
+ NT_LOG(INF, NTNIC, "%s: NIM module removed",
+ drv->mp_port_id_str[i]);
}
- /* NIM module is present */
- if (new_link_state.lh_nim_absent || !link_state[i].nim_present) {
- sfp_nim_state_t new_state;
+ link_state[i] = new_link_state;
+ continue;
+ }
- NT_LOG(DBG, NTNIC, "%s: NIM module inserted",
- drv->mp_port_id_str[i]);
+ /* NIM module is present */
+ if (new_link_state.lh_nim_absent || !link_state[i].nim_present) {
+ sfp_nim_state_t new_state;
+
+ NT_LOG(DBG, NTNIC, "%s: NIM module inserted",
+ drv->mp_port_id_str[i]);
- if (_port_init(drv, fpga, i)) {
- NT_LOG(ERR, NTNIC,
- "%s: Failed to initialize NIM module",
- drv->mp_port_id_str[i]);
- continue;
- }
-
- if (nthw_nim_state_build(&nim_ctx[i], &new_state)) {
- NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data",
- drv->mp_port_id_str[i]);
- continue;
- }
-
- RTE_ASSERT(new_state.br); /* Cannot be zero if NIM is present */
- NT_LOG(DBG, NTNIC,
- "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
- drv->mp_port_id_str[i], nim_ctx->nim_id,
- nthw_nim_id_to_text(nim_ctx->nim_id),
- (unsigned int)new_state.br, nim_ctx->vendor_name,
- nim_ctx->prod_no, nim_ctx->serial_no);
-
- (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i,
- &link_state[i], is_port_disabled);
-
- NT_LOG(DBG, NTNIC, "%s: NIM module initialized",
+ if (_port_init(drv, fpga, i)) {
+ NT_LOG(ERR, NTNIC,
+ "%s: Failed to initialize NIM module",
drv->mp_port_id_str[i]);
continue;
}
- if (reported_link[i] != new_link_state.link_up) {
- NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
- (new_link_state.link_up ? "up" : "down"));
- link_info->link_info[i].link_speed =
- (new_link_state.link_up ? NT_LINK_SPEED_100G
- : NT_LINK_SPEED_UNKNOWN);
- link_state[i].link_up = new_link_state.link_up;
- reported_link[i] = new_link_state.link_up;
+ if (nthw_nim_state_build(&nim_ctx[i], &new_state)) {
+ NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data",
+ drv->mp_port_id_str[i]);
+ continue;
}
- check_link_state(drv, &mac_pcs[i]);
- } /* end-for */
+ RTE_ASSERT(new_state.br); /* Cannot be zero if NIM is present */
+ NT_LOG(DBG, NTNIC,
+ "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
+ drv->mp_port_id_str[i], nim_ctx->nim_id,
+ nthw_nim_id_to_text(nim_ctx->nim_id),
+ (unsigned int)new_state.br, nim_ctx->vendor_name,
+ nim_ctx->prod_no, nim_ctx->serial_no);
- if (monitor_task_is_running[adapter_no])
- nt_os_wait_usec(5 * 100000U); /* 5 x 0.1s = 0.5s */
- }
+ (void)_link_state_build(drv, &mac_pcs[i], &gpio_phy[i], i,
+ &link_state[i], is_port_disabled);
-NT4GA_LINK_100G_MON_EXIT:
+ NT_LOG(DBG, NTNIC, "%s: NIM module initialized",
+ drv->mp_port_id_str[i]);
+ continue;
+ }
- NT_LOG(DBG, NTNIC, "%s: Stopped NT4GA 100 Gbps link monitoring thread.",
- drv->mp_adapter_id_str);
+ if (reported_link[i] != new_link_state.link_up) {
+ NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
+ (new_link_state.link_up ? "up" : "down"));
+ link_info->link_info[i].link_speed =
+ (new_link_state.link_up ? NT_LINK_SPEED_100G
+ : NT_LINK_SPEED_UNKNOWN);
+ link_state[i].link_up = new_link_state.link_up;
+ reported_link[i] = new_link_state.link_up;
+ }
+
+ check_link_state(drv, &mac_pcs[i]);
+ } /* end-for */
+
+ if (rte_service_runstate_get(adapter_mon_srv->id))
+ nt_os_wait_usec(5 * 100000U); /* 5 x 0.1s = 0.5s */
return 0;
}
@@ -649,11 +658,9 @@ static int _common_ptp_nim_state_machine(void *data)
/*
* Userland NIM state machine
*/
-static uint32_t nt4ga_link_100g_mon(void *data)
+static int nt4ga_link_100g_mon(void *data)
{
- (void)_common_ptp_nim_state_machine(data);
-
- return 0;
+ return _common_ptp_nim_state_machine(data);
}
/*
@@ -710,11 +717,21 @@ static int nt4ga_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nth
}
}
- /* Create state-machine thread */
+ /* Create state-machine service */
if (res == 0) {
- if (!monitor_task_is_running[adapter_no]) {
- res = rte_thread_create(&monitor_tasks[adapter_no], NULL,
- nt4ga_link_100g_mon, p_adapter_info);
+ struct rte_service_spec adapter_monitor_service = {
+ .name = "ntnic-adapter-monitor",
+ .callback = nt4ga_link_100g_mon,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = p_adapter_info,
+ };
+
+ res = nthw_service_add(&adapter_monitor_service, RTE_NTNIC_SERVICE_ADAPTER_MON);
+ if (res) {
+ NT_LOG(ERR, NTNIC, "%s: Failed to create adapter monitor service",
+ p_adapter_info->mp_adapter_id_str);
+ return res;
}
}
diff --git a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
index 75a7504510..c8b7912e26 100644
--- a/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
+++ b/drivers/net/ntnic/link_mgmt/link_agx_100g/nt4ga_agx_link_100g.c
@@ -13,6 +13,7 @@
#include "nim_defines.h"
#include "nthw_gfg.h"
#include "nthw_phy_tile.h"
+#include "nt_service.h"
typedef enum {
LOOPBACK_HOST_NONE,
@@ -768,179 +769,186 @@ static int _port_init(adapter_info_t *p_info, nthw_fpga_t *fpga, int port)
/*
* Link state machine
*/
-static void *_common_ptp_nim_state_machine(void *data)
+static int _common_ptp_nim_state_machine(void *data)
{
- adapter_info_t *drv = (adapter_info_t *)data;
- fpga_info_t *fpga_info = &drv->fpga_info;
- nt4ga_link_t *link_info = &drv->nt4ga_link;
- nthw_fpga_t *fpga = fpga_info->mp_fpga;
- const int adapter_no = drv->adapter_no;
- const int nb_ports = fpga_info->n_phy_ports;
- uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
- /* link_state_t new_link_state; */
-
- link_state_t *link_state = link_info->link_state;
- nim_i2c_ctx_t *nim_ctx = link_info->u.var_a100g.nim_ctx;
+ static adapter_info_t *drv;
+ static nt4ga_link_t *link_info;
+ static nthw_fpga_t *fpga;
+ static int nb_ports;
+ static link_state_t *link_state;
+ static nim_i2c_ctx_t *nim_ctx;
+ static uint32_t last_lpbk_mode[NUM_ADAPTER_PORTS_MAX];
+
+ struct nt_service *adapter_mon_srv = nthw_service_get_info(RTE_NTNIC_SERVICE_ADAPTER_MON);
+ RTE_ASSERT(adapter_mon_srv != NULL);
+
+ if (!NT_SERVICE_GET_STATE(adapter_mon_srv)) {
+ drv = (adapter_info_t *)data;
+ RTE_ASSERT(drv != NULL);
+
+ fpga_info_t *fpga_info = &drv->fpga_info;
+ link_info = &drv->nt4ga_link;
+ fpga = fpga_info->mp_fpga;
+ int adapter_no = drv->adapter_no;
+
+ nb_ports = fpga_info->n_phy_ports;
+ link_state = link_info->link_state;
+ nim_ctx = link_info->u.var_a100g.nim_ctx;
+
+ if (!fpga) {
+ NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
+ return -1;
+ }
- if (!fpga) {
- NT_LOG(ERR, NTNIC, "%s: fpga is NULL", drv->mp_adapter_id_str);
- goto NT4GA_LINK_100G_MON_EXIT;
- }
+ RTE_ASSERT(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
- RTE_ASSERT(adapter_no >= 0 && adapter_no < NUM_ADAPTER_MAX);
+ memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
- monitor_task_is_running[adapter_no] = 1;
- memset(last_lpbk_mode, 0, sizeof(last_lpbk_mode));
+ /* Initialize link state */
+ for (int i = 0; i < nb_ports; i++) {
+ link_state[i].link_disabled = true;
+ link_state[i].nim_present = false;
+ link_state[i].lh_nim_absent = true;
+ link_state[i].link_up = false;
+ link_state[i].link_state = NT_LINK_STATE_UNKNOWN;
+ link_state[i].link_state_latched = NT_LINK_STATE_UNKNOWN;
+ }
- /* Initialize link state */
- for (int i = 0; i < nb_ports; i++) {
- link_state[i].link_disabled = true;
- link_state[i].nim_present = false;
- link_state[i].lh_nim_absent = true;
- link_state[i].link_up = false;
- link_state[i].link_state = NT_LINK_STATE_UNKNOWN;
- link_state[i].link_state_latched = NT_LINK_STATE_UNKNOWN;
+ NT_LOG(INF, NTNIC, "Adapter monitor service started on lcore %i", rte_lcore_id());
+ adapter_mon_srv->lcore = rte_lcore_id();
+ NT_SERVICE_SET_STATE(adapter_mon_srv, true);
+ return 0;
}
- if (monitor_task_is_running[adapter_no])
- NT_LOG(DBG, NTNIC, "%s: link state machine running...", drv->mp_adapter_id_str);
+ int i;
+ static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
- while (monitor_task_is_running[adapter_no]) {
- int i;
- static bool reported_link[NUM_ADAPTER_PORTS_MAX] = { false };
+ for (i = 0; i < nb_ports; i++) {
+ const bool is_port_disabled = link_info->port_action[i].port_disable;
+ const bool was_port_disabled = link_state[i].link_disabled;
+ const bool disable_port = is_port_disabled && !was_port_disabled;
+ const bool enable_port = !is_port_disabled && was_port_disabled;
- for (i = 0; i < nb_ports; i++) {
- const bool is_port_disabled = link_info->port_action[i].port_disable;
- const bool was_port_disabled = link_state[i].link_disabled;
- const bool disable_port = is_port_disabled && !was_port_disabled;
- const bool enable_port = !is_port_disabled && was_port_disabled;
-
- if (!monitor_task_is_running[adapter_no])
- break;
-
- /*
- * Has the administrative port state changed?
- */
- RTE_ASSERT(!(disable_port && enable_port));
-
- if (disable_port) {
- memset(&link_state[i], 0, sizeof(link_state[i]));
- link_state[i].link_disabled = true;
- link_state[i].lh_nim_absent = true;
- reported_link[i] = false;
- port_disable(drv, i);
- NT_LOG(INF, NTNIC, "%s: Port %i is disabled",
- drv->mp_port_id_str[i], i);
- continue;
- }
+ if (!rte_service_runstate_get(adapter_mon_srv->id))
+ break;
- if (enable_port) {
- link_state[i].link_disabled = false;
- NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
- drv->mp_port_id_str[i], i);
- }
+ /*
+ * Has the administrative port state changed?
+ */
+ RTE_ASSERT(!(disable_port && enable_port));
+
+ if (disable_port) {
+ memset(&link_state[i], 0, sizeof(link_state[i]));
+ link_state[i].link_disabled = true;
+ link_state[i].lh_nim_absent = true;
+ reported_link[i] = false;
+ port_disable(drv, i);
+ NT_LOG(INF, NTNIC, "%s: Port %i is disabled",
+ drv->mp_port_id_str[i], i);
+ continue;
+ }
- if (is_port_disabled)
- continue;
+ if (enable_port) {
+ link_state[i].link_disabled = false;
+ NT_LOG(DBG, NTNIC, "%s: Port %i is enabled",
+ drv->mp_port_id_str[i], i);
+ }
- if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
- /* Loopback mode has changed. Do something */
- if (!nim_is_present(&nim_ctx[i], i)) {
- /*
- * If there is no Nim present, we need to initialize the
- * port anyway
- */
- _port_init(drv, fpga, i);
- }
-
- set_loopback(drv,
- i,
- link_info->port_action[i].port_lpbk_mode,
- last_lpbk_mode[i]);
-
- if (link_info->port_action[i].port_lpbk_mode == 1)
- link_state[i].link_up = true;
-
- last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode;
- continue;
+ if (is_port_disabled)
+ continue;
+
+ if (link_info->port_action[i].port_lpbk_mode != last_lpbk_mode[i]) {
+ /* Loopback mode has changed. Do something */
+ if (!nim_is_present(&nim_ctx[i], i)) {
+ /*
+ * If there is no Nim present, we need to initialize the
+ * port anyway
+ */
+ _port_init(drv, fpga, i);
}
- get_link_state(drv, nim_ctx, &link_state[i], i);
- link_state[i].link_disabled = is_port_disabled;
+ set_loopback(drv,
+ i,
+ link_info->port_action[i].port_lpbk_mode,
+ last_lpbk_mode[i]);
- if (!link_state[i].nim_present) {
- if (!link_state[i].lh_nim_absent) {
- NT_LOG(INF, NTNIC, "%s: NIM module removed",
- drv->mp_port_id_str[i]);
- reported_link[i] = false;
- link_state[i].link_up = false;
- link_state[i].lh_nim_absent = true;
+ if (link_info->port_action[i].port_lpbk_mode == 1)
+ link_state[i].link_up = true;
- } else {
- NT_LOG(DBG, NTNIC, "%s: No NIM module, skip",
- drv->mp_port_id_str[i]);
- }
+ last_lpbk_mode[i] = link_info->port_action[i].port_lpbk_mode;
+ continue;
+ }
- continue;
- }
+ get_link_state(drv, nim_ctx, &link_state[i], i);
+ link_state[i].link_disabled = is_port_disabled;
- /*
- * NIM module is present
- */
- if (link_state[i].lh_nim_absent && link_state[i].nim_present) {
- sfp_nim_state_t new_state;
- NT_LOG(INF, NTNIC, "%s: NIM module inserted",
+ if (!link_state[i].nim_present) {
+ if (!link_state[i].lh_nim_absent) {
+ NT_LOG(INF, NTNIC, "%s: NIM module removed",
drv->mp_port_id_str[i]);
+ reported_link[i] = false;
+ link_state[i].link_up = false;
+ link_state[i].lh_nim_absent = true;
- if (_port_init(drv, fpga, i)) {
- NT_LOG(ERR, NTNIC,
- "%s: Failed to initialize NIM module",
- drv->mp_port_id_str[i]);
- continue;
- }
+ } else {
+ NT_LOG(DBG, NTNIC, "%s: No NIM module, skip",
+ drv->mp_port_id_str[i]);
+ }
- if (nthw_nim_state_build(&nim_ctx[i], &new_state)) {
- NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data",
- drv->mp_port_id_str[i]);
- continue;
- }
+ continue;
+ }
- RTE_ASSERT(new_state.br); /* Cannot be zero if NIM is present */
- NT_LOG(DBG, NTNIC,
- "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
- drv->mp_port_id_str[i], nim_ctx[i].nim_id,
- nthw_nim_id_to_text(nim_ctx[i].nim_id),
- (unsigned int)new_state.br, nim_ctx[i].vendor_name,
- nim_ctx[i].prod_no, nim_ctx[i].serial_no);
- link_state[i].lh_nim_absent = false;
- NT_LOG(DBG, NTNIC, "%s: NIM module initialized",
+ /*
+ * NIM module is present
+ */
+ if (link_state[i].lh_nim_absent && link_state[i].nim_present) {
+ sfp_nim_state_t new_state;
+ NT_LOG(INF, NTNIC, "%s: NIM module inserted",
+ drv->mp_port_id_str[i]);
+
+ if (_port_init(drv, fpga, i)) {
+ NT_LOG(ERR, NTNIC,
+ "%s: Failed to initialize NIM module",
drv->mp_port_id_str[i]);
continue;
}
- if (reported_link[i] != link_state[i].link_up) {
- NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
- (link_state[i].link_up ? "up" : "down"));
- reported_link[i] = link_state[i].link_up;
- set_link_state(drv, nim_ctx, &link_state[i], i);
+ if (nthw_nim_state_build(&nim_ctx[i], &new_state)) {
+ NT_LOG(ERR, NTNIC, "%s: Cannot read basic NIM data",
+ drv->mp_port_id_str[i]);
+ continue;
}
+
+ RTE_ASSERT(new_state.br); /* Cannot be zero if NIM is present */
+ NT_LOG(DBG, NTNIC,
+ "%s: NIM id = %u (%s), br = %u, vendor = '%s', pn = '%s', sn='%s'",
+ drv->mp_port_id_str[i], nim_ctx[i].nim_id,
+ nthw_nim_id_to_text(nim_ctx[i].nim_id),
+ (unsigned int)new_state.br, nim_ctx[i].vendor_name,
+ nim_ctx[i].prod_no, nim_ctx[i].serial_no);
+ link_state[i].lh_nim_absent = false;
+ NT_LOG(DBG, NTNIC, "%s: NIM module initialized",
+ drv->mp_port_id_str[i]);
+ continue;
}
- if (monitor_task_is_running[adapter_no])
- nt_os_wait_usec(5 * 100000U); /* 5 x 0.1s = 0.5s */
+ if (reported_link[i] != link_state[i].link_up) {
+ NT_LOG(INF, NTNIC, "%s: link is %s", drv->mp_port_id_str[i],
+ (link_state[i].link_up ? "up" : "down"));
+ reported_link[i] = link_state[i].link_up;
+ set_link_state(drv, nim_ctx, &link_state[i], i);
+ }
}
-NT4GA_LINK_100G_MON_EXIT:
- NT_LOG(DBG, NTNIC, "%s: Stopped NT4GA 100 Gbps link monitoring thread.",
- drv->mp_adapter_id_str);
- return NULL;
+ if (rte_service_runstate_get(adapter_mon_srv->id))
+ nt_os_wait_usec(5 * 100000U); /* 5 x 0.1s = 0.5s */
+
+ return 0;
}
-static uint32_t nt4ga_agx_link_100g_mon(void *data)
+static int nt4ga_agx_link_100g_mon(void *data)
{
- (void)_common_ptp_nim_state_machine(data);
-
- return 0;
+ return _common_ptp_nim_state_machine(data);
}
/*
@@ -1009,12 +1017,24 @@ int nt4ga_agx_link_100g_ports_init(struct adapter_info_s *p_adapter_info, nthw_f
}
/*
- * Create state-machine thread
+ * Create state-machine service
*/
- if (!monitor_task_is_running[adapter_no]) {
- res = rte_thread_create(&monitor_tasks[adapter_no], NULL,
- nt4ga_agx_link_100g_mon, p_adapter_info);
+ if (res == 0) {
+ struct rte_service_spec adapter_monitor_service = {
+ .name = "ntnic-adapter_agx-monitor",
+ .callback = nt4ga_agx_link_100g_mon,
+ .socket_id = SOCKET_ID_ANY,
+ .capabilities = RTE_SERVICE_CAP_MT_SAFE,
+ .callback_userdata = p_adapter_info,
+ };
+
+ res = nthw_service_add(&adapter_monitor_service, RTE_NTNIC_SERVICE_ADAPTER_MON);
+ if (res) {
+ NT_LOG(ERR, NTNIC, "%s: Failed to create adapter monitor service",
+ p_adapter_info->mp_adapter_id_str);
+ return res;
+ }
}
return res;
diff --git a/drivers/net/ntnic/ntutil/nt_service.c b/drivers/net/ntnic/ntutil/nt_service.c
index 9f22ee2bba..c39771acc2 100644
--- a/drivers/net/ntnic/ntutil/nt_service.c
+++ b/drivers/net/ntnic/ntutil/nt_service.c
@@ -36,6 +36,12 @@ static struct nt_service g_nt_services[RTE_NTNIC_SERVICE_MAX] = {
.lcore = RTE_MAX_LCORE,
.initialized = false,
},
+ [RTE_NTNIC_SERVICE_ADAPTER_MON] = {
+ .tag = RTE_NTNIC_SERVICE_ADAPTER_MON,
+ .id = NT_SERVICE_UNKNOWN_ID,
+ .lcore = RTE_MAX_LCORE,
+ .initialized = false,
+ },
};
inline struct nt_service *nthw_service_get_info(const enum rte_ntnic_service_tag tag)
diff --git a/drivers/net/ntnic/rte_pmd_ntnic.h b/drivers/net/ntnic/rte_pmd_ntnic.h
index 1a68cb8e37..08e7958acd 100644
--- a/drivers/net/ntnic/rte_pmd_ntnic.h
+++ b/drivers/net/ntnic/rte_pmd_ntnic.h
@@ -45,6 +45,7 @@ enum rte_ntnic_service_tag {
RTE_NTNIC_SERVICE_STAT = 1,
RTE_NTNIC_SERVICE_PORT_0_EVENT = 2,
RTE_NTNIC_SERVICE_PORT_1_EVENT = 3,
+ RTE_NTNIC_SERVICE_ADAPTER_MON = 4,
RTE_NTNIC_SERVICE_MAX
};
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 6/7] net/ntnic: add warning about service cores
2025-09-08 14:17 ` [PATCH v2 0/7] migrate threads to DPDK service framework Serhii Iliushyk
` (4 preceding siblings ...)
2025-09-08 14:17 ` [PATCH v2 5/7] net/ntnic: migrate adapter mon " Serhii Iliushyk
@ 2025-09-08 14:17 ` Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 7/7] net/ntnic: cleanup using pthreads and rte_thread Serhii Iliushyk
6 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 14:17 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This commit adds a warning message if the service cores are not available.
This warning notifies a user about potential issues with ntnic services.
There in no error because the service cores may be added
by application itself after the pcie_probe.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/ntnic_ethdev.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index 7ec1c94a14..664112f67e 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -2607,6 +2607,14 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
}
}
+ uint32_t cores[RTE_MAX_LCORE] = {0};
+ int32_t lcore_count = rte_service_lcore_list(cores, RTE_MAX_LCORE);
+
+ if (lcore_count <= 0) {
+ NT_LOG(WRN, NTNIC, "No service cores available. "
+ "Please check if all NTNIC services are started");
+ }
+
return 0;
}
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2 7/7] net/ntnic: cleanup using pthreads and rte_thread
2025-09-08 14:17 ` [PATCH v2 0/7] migrate threads to DPDK service framework Serhii Iliushyk
` (5 preceding siblings ...)
2025-09-08 14:17 ` [PATCH v2 6/7] net/ntnic: add warning about service cores Serhii Iliushyk
@ 2025-09-08 14:17 ` Serhii Iliushyk
6 siblings, 0 replies; 17+ messages in thread
From: Serhii Iliushyk @ 2025-09-08 14:17 UTC (permalink / raw)
To: dev; +Cc: mko-plv, sil-plv, ckm, stephen
This patch cleans up the code to use pthreads and rte_thread APIs.
Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
drivers/net/ntnic/adapter/nt4ga_adapter.c | 2 --
drivers/net/ntnic/include/nt4ga_adapter.h | 1 -
drivers/net/ntnic/include/ntdrv_4ga.h | 1 -
drivers/net/ntnic/nthw/core/nthw_pca9532.c | 2 --
drivers/net/ntnic/nthw/core/nthw_pcal6416a.c | 1 -
.../net/ntnic/nthw/core/nthw_si5332_si5156.c | 1 -
.../profile_inline/flow_api_profile_inline.c | 2 +-
drivers/net/ntnic/ntnic_ethdev.c | 22 +++++--------------
drivers/net/ntnic/ntutil/nt_util.c | 2 +-
9 files changed, 7 insertions(+), 27 deletions(-)
diff --git a/drivers/net/ntnic/adapter/nt4ga_adapter.c b/drivers/net/ntnic/adapter/nt4ga_adapter.c
index 363874c85f..de4e8707bf 100644
--- a/drivers/net/ntnic/adapter/nt4ga_adapter.c
+++ b/drivers/net/ntnic/adapter/nt4ga_adapter.c
@@ -3,8 +3,6 @@
* Copyright(c) 2023 Napatech A/S
*/
-#include <rte_thread.h>
-
#include "nt_service.h"
#include "ntlog.h"
#include "nthw_fpga.h"
diff --git a/drivers/net/ntnic/include/nt4ga_adapter.h b/drivers/net/ntnic/include/nt4ga_adapter.h
index 6c701b601f..0598e62b7b 100644
--- a/drivers/net/ntnic/include/nt4ga_adapter.h
+++ b/drivers/net/ntnic/include/nt4ga_adapter.h
@@ -40,7 +40,6 @@ typedef struct adapter_info_s {
char *mp_port_id_str[NUM_ADAPTER_PORTS_MAX];
char *mp_adapter_id_str;
char *p_dev_name;
- volatile bool *pb_shutdown;
int adapter_no;
int n_rx_host_buffers;
diff --git a/drivers/net/ntnic/include/ntdrv_4ga.h b/drivers/net/ntnic/include/ntdrv_4ga.h
index ee0e66c4d4..4ff1f115f4 100644
--- a/drivers/net/ntnic/include/ntdrv_4ga.h
+++ b/drivers/net/ntnic/include/ntdrv_4ga.h
@@ -14,7 +14,6 @@ typedef struct ntdrv_4ga_s {
struct adapter_info_s adapter_info;
char *p_drv_name;
- volatile bool b_shutdown;
rte_spinlock_t stat_lck;
} ntdrv_4ga_t;
diff --git a/drivers/net/ntnic/nthw/core/nthw_pca9532.c b/drivers/net/ntnic/nthw/core/nthw_pca9532.c
index af14cd6d06..805e0275e8 100644
--- a/drivers/net/ntnic/nthw/core/nthw_pca9532.c
+++ b/drivers/net/ntnic/nthw/core/nthw_pca9532.c
@@ -3,8 +3,6 @@
* Copyright(c) 2023 Napatech A/S
*/
-#include <pthread.h>
-
#include "nt_util.h"
#include "ntlog.h"
diff --git a/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
index 2fca469497..f7efc196f4 100644
--- a/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
+++ b/drivers/net/ntnic/nthw/core/nthw_pcal6416a.c
@@ -2,7 +2,6 @@
* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2023 Napatech A/S
*/
-#include <pthread.h>
#include "nt_util.h"
#include "ntlog.h"
diff --git a/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
index eb11ebc67a..537d58afb7 100644
--- a/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
+++ b/drivers/net/ntnic/nthw/core/nthw_si5332_si5156.c
@@ -3,7 +3,6 @@
* Copyright(c) 2023 Napatech A/S
*/
-#include <pthread.h>
#include "generic/rte_spinlock.h"
#include "nt_util.h"
#include "ntlog.h"
diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
index eaaf681ac6..2291642ca9 100644
--- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
+++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c
@@ -5276,7 +5276,7 @@ struct flow_handle *flow_async_create_profile_inline(struct flow_eth_dev *dev,
} while (status == CELL_STATUS_INITIALIZING);
/* error handling in case that create_flow_filter() will fail in the other
- * thread
+ * service
*/
if (status == CELL_STATUS_UNINITIALIZED)
goto err_exit;
diff --git a/drivers/net/ntnic/ntnic_ethdev.c b/drivers/net/ntnic/ntnic_ethdev.c
index 664112f67e..0f70462f3d 100644
--- a/drivers/net/ntnic/ntnic_ethdev.c
+++ b/drivers/net/ntnic/ntnic_ethdev.c
@@ -6,8 +6,6 @@
#include <stdint.h>
#include <stdarg.h>
-#include <signal.h>
-
#include <rte_eal.h>
#include <rte_dev.h>
#include <rte_vfio.h>
@@ -33,12 +31,6 @@
#include "rte_pmd_ntnic.h"
#include "nt_service.h"
-const rte_thread_attr_t thread_attr = { .priority = RTE_THREAD_PRIORITY_NORMAL };
-#define THREAD_CREATE(a, b, c) rte_thread_create(a, &thread_attr, b, c)
-#define THREAD_CTRL_CREATE(a, b, c, d) rte_thread_create_internal_control(a, b, c, d)
-#define THREAD_JOIN(a) rte_thread_join(a, NULL)
-#define THREAD_FUNC static uint32_t
-#define THREAD_RETURN (0)
#define HW_MAX_PKT_LEN (10000)
#define MAX_MTU (HW_MAX_PKT_LEN - RTE_ETHER_HDR_LEN - RTE_ETHER_CRC_LEN)
#define MIN_MTU_INLINE 512
@@ -1536,14 +1528,13 @@ drv_deinit(struct drv_s *p_drv)
fpga_info_t *fpga_info = &p_nt_drv->adapter_info.fpga_info;
/*
- * Mark the global pdrv for cleared. Used by some threads to terminate.
- * 1 second to give the threads a chance to see the termonation.
+ * Mark the global pdrv for cleared. Used by some services to terminate.
+ * 1 second to give the services a chance to see the termonation.
*/
clear_pdrv(p_drv);
nt_os_wait_usec(1000000);
/* stop statistics service */
- p_drv->ntdrv.b_shutdown = true;
nthw_service_del(RTE_NTNIC_SERVICE_STAT);
if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
@@ -2323,9 +2314,6 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
p_nt_drv->adapter_info.hw_info.pci_sub_vendor_id,
p_nt_drv->adapter_info.hw_info.pci_sub_device_id);
- p_nt_drv->b_shutdown = false;
- p_nt_drv->adapter_info.pb_shutdown = &p_nt_drv->b_shutdown;
-
/* store context */
store_pdrv(p_drv);
@@ -2366,7 +2354,7 @@ nthw_pci_dev_init(struct rte_pci_device *pci_dev)
NT_LOG_DBGX(DBG, NTNIC, "SG module is not initialized");
}
- /* Start ctrl, monitor, stat thread only for primary process. */
+ /* Start ctrl, monitor, stat service only for primary process. */
if (err == 0) {
/* mp_adapter_id_str is initialized after nt4ga_adapter_init(p_nt_drv) */
const char *const p_adapter_id_str = p_nt_drv->adapter_info.mp_adapter_id_str;
@@ -2631,7 +2619,7 @@ nthw_pci_dev_deinit(struct rte_eth_dev *eth_dev __rte_unused)
fpga_info_t *fpga_info = &p_ntdrv->adapter_info.fpga_info;
const int n_phy_ports = fpga_info->n_phy_ports;
- /* let running threads end Rx and Tx activity */
+ /* let running services end Rx and Tx activity */
if (sg_ops != NULL) {
nt_os_wait_usec(1 * 1000 * 1000);
@@ -2706,7 +2694,7 @@ nthw_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
/*
* 1 time calculation of 1 sec stat update rtc cycles to prevent stat poll
- * flooding by OVS from multiple virtual port threads - no need to be precise
+ * flooding by OVS from multiple virtual port services - no need to be precise
*/
uint64_t now_rtc = rte_get_tsc_cycles();
nt_os_wait_usec(10 * 1000);
diff --git a/drivers/net/ntnic/ntutil/nt_util.c b/drivers/net/ntnic/ntutil/nt_util.c
index df382e7a24..a4d30d8ca4 100644
--- a/drivers/net/ntnic/ntutil/nt_util.c
+++ b/drivers/net/ntnic/ntutil/nt_util.c
@@ -16,7 +16,7 @@
static struct nt_util_vfio_impl vfio_cb;
-/* uses usleep which schedules out the calling thread */
+/* uses usleep which schedules out the calling service */
void nt_os_wait_usec(int val)
{
rte_delay_us_sleep(val);
--
2.45.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v1 0/7] migrate threads to DPDK service framework
2025-09-08 11:04 [PATCH v1 0/7] migrate threads to DPDK service framework Serhii Iliushyk
` (6 preceding siblings ...)
2025-09-08 11:04 ` [PATCH v1 7/7] net/ntnic: cleanup using pthreads and rte_thread Serhii Iliushyk
@ 2025-09-08 20:08 ` Stephen Hemminger
7 siblings, 0 replies; 17+ messages in thread
From: Stephen Hemminger @ 2025-09-08 20:08 UTC (permalink / raw)
To: Serhii Iliushyk; +Cc: dev, mko-plv, ckm
On Mon, 8 Sep 2025 13:04:38 +0200
Serhii Iliushyk <sil-plv@napatech.com> wrote:
> This modification provides better resource (CPU) management for NTNIC PMD.
>
> The following threads are migrated:
> * FLM update thread
> * Statistic thread
> * Port event thread
> * Adapter monitoring thread
> Additionally, a warning is added to inform users about the importance of
> dedicating lcores to the DPDK service framework when using the NTNIC PMD.
> The code is also cleaned up to use pthreads and rte_thread APIs.
>
> After this patch series, an each application using NTNIC PMD should
> dedicate at least five(5) cores for DPDK service framework to ensure
> proper operation of the NTNIC PMD.
I was concerned with excessive control thread usage before, and this
seems to be worse not better.
There are conflicting use cases here:
1. The original DPDK goal was to make effective use of multiple cores
with no locking. Intel customers often had idle lcore's and some CPU's
had lots of inactive lcores that could be used to get more work done.
Dedicating some to service tasks etc was a natural outcome.
2. DPDK applications (OVS, Grout, VPP) usually want to know about lcores
at least in the documentation and examples. They don't cover the case
of service lcores.
3. Dedicated low core count smart NIC's using DPDK. In this case it
makes sense to be frugal with lcores since the point of the smart NIC
is to be able to run other control services. For example, the MS
NIC had hard limit on the DPDK part (via cgroups) of only 4 + main
lcores.
Granted NTNIC is likely only being used for a specific application on
a specific set of hardware.
The ideal would be to have better control event management in EAL.
Something like "libevent" style API. This would reduce control core
needs, and avoid any potential resource conflict overlap between control
threads.
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2025-09-08 20:08 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-08 11:04 [PATCH v1 0/7] migrate threads to DPDK service framework Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 1/7] net/ntnic: introduce service API for NTNIC PMD Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 2/7] net/ntnic: migrate flm update thread to service Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 3/7] net/ntnic: migrate statistic " Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 4/7] net/ntnic: migrate port event " Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 5/7] net/ntnic: migrate adapter mon " Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 6/7] net/ntnic: add warning about service cores Serhii Iliushyk
2025-09-08 11:04 ` [PATCH v1 7/7] net/ntnic: cleanup using pthreads and rte_thread Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 0/7] migrate threads to DPDK service framework Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 1/7] net/ntnic: introduce service API for NTNIC PMD Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 2/7] net/ntnic: migrate flm update thread to service Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 3/7] net/ntnic: migrate statistic " Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 4/7] net/ntnic: migrate port event " Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 5/7] net/ntnic: migrate adapter mon " Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 6/7] net/ntnic: add warning about service cores Serhii Iliushyk
2025-09-08 14:17 ` [PATCH v2 7/7] net/ntnic: cleanup using pthreads and rte_thread Serhii Iliushyk
2025-09-08 20:08 ` [PATCH v1 0/7] migrate threads to DPDK service framework Stephen Hemminger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).