@@ -181,3 +181,16 @@ System configuration
-k option shows the device driver, if any, that devices are bound to.
Depending on the modules loaded at this point the new PCI devices may be
bound to nfp_netvf driver.
+
+
+Flow offload
+------------
+
+Use the flower firmware application, some type of Netronome's SmartNICs can
+offload the flow into cards.
+
+The flower firmware application requires the PMD running two services:
+
+ * PF vNIC service: handling the feedback traffic.
+ * ctrl vNIC service: communicate between PMD and firmware through
+ control message.
@@ -55,6 +55,13 @@ New Features
Also, make sure to start the actual text at the margin.
=======================================================
+* **Updated Netronome nfp driver.**
+
+ Add the needed data structures and logics to support the offload of rte_flow:
+
+ * Added the support of flower firmware.
+ * Added the flower service infrastructure.
+
* **Updated Wangxun ngbe driver.**
* Added support to set device link down/up.
new file mode 100644
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Corigine, Inc.
+ * All rights reserved.
+ */
+
+#include <rte_common.h>
+#include <ethdev_driver.h>
+#include <rte_service_component.h>
+#include <rte_malloc.h>
+#include <ethdev_pci.h>
+#include <ethdev_driver.h>
+
+#include "../nfp_common.h"
+#include "../nfp_logs.h"
+#include "../nfp_ctrl.h"
+#include "../nfp_cpp_bridge.h"
+#include "nfp_flower.h"
+
+int
+nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
+{
+ unsigned int numa_node;
+ struct nfp_app_fw_flower *app_fw_flower;
+
+ numa_node = rte_socket_id();
+
+ /* Allocate memory for the Flower app */
+ app_fw_flower = rte_zmalloc_socket("nfp_app_fw_flower", sizeof(*app_fw_flower),
+ RTE_CACHE_LINE_SIZE, numa_node);
+ if (app_fw_flower == NULL) {
+ PMD_INIT_LOG(ERR, "Could not malloc app fw flower");
+ return -ENOMEM;
+ }
+
+ pf_dev->app_fw_priv = app_fw_flower;
+
+ return 0;
+}
+
+int
+nfp_secondary_init_app_fw_flower(__rte_unused struct nfp_cpp *cpp)
+{
+ PMD_INIT_LOG(ERR, "Flower firmware not supported");
+ return -ENOTSUP;
+}
new file mode 100644
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Corigine, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _NFP_FLOWER_H_
+#define _NFP_FLOWER_H_
+
+/* The flower application's private structure */
+struct nfp_app_fw_flower {
+};
+
+int nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev);
+int nfp_secondary_init_app_fw_flower(struct nfp_cpp *cpp);
+
+#endif /* _NFP_FLOWER_H_ */
@@ -6,6 +6,7 @@ if not is_linux or not dpdk_conf.get('RTE_ARCH_64')
reason = 'only supported on 64-bit Linux'
endif
sources = files(
+ 'flower/nfp_flower.c',
'nfpcore/nfp_cpp_pcie_ops.c',
'nfpcore/nfp_nsp.c',
'nfpcore/nfp_cppcore.c',
@@ -116,6 +116,7 @@
/* Firmware application ID's */
enum nfp_app_fw_id {
NFP_APP_FW_CORE_NIC = 0x1,
+ NFP_APP_FW_FLOWER_NIC = 0x3,
};
/* nfp_qcp_ptr - Read or Write Pointer of a queue */
@@ -28,22 +28,86 @@
static int nfp_cpp_bridge_serve_write(int sockfd, struct nfp_cpp *cpp);
static int nfp_cpp_bridge_serve_read(int sockfd, struct nfp_cpp *cpp);
static int nfp_cpp_bridge_serve_ioctl(int sockfd, struct nfp_cpp *cpp);
+static int nfp_cpp_bridge_service_func(void *args);
-void nfp_register_cpp_service(struct nfp_cpp *cpp)
+int
+nfp_map_service(uint32_t service_id)
{
- uint32_t *cpp_service_id = NULL;
- struct rte_service_spec service;
+ int32_t ret;
+ uint32_t slcore = 0;
+ int32_t slcore_count;
+ uint8_t service_count;
+ const char *service_name;
+ uint32_t slcore_array[RTE_MAX_LCORE];
+ uint8_t min_service_count = UINT8_MAX;
+
+ slcore_count = rte_service_lcore_list(slcore_array, RTE_MAX_LCORE);
+ if (slcore_count <= 0) {
+ PMD_INIT_LOG(DEBUG, "No service cores found");
+ return -ENOENT;
+ }
+
+ /*
+ * Find a service core with the least number of services already
+ * registered to it
+ */
+ while (slcore_count--) {
+ service_count = rte_service_lcore_count_services(slcore_array[slcore_count]);
+ if (service_count < min_service_count) {
+ slcore = slcore_array[slcore_count];
+ min_service_count = service_count;
+ }
+ }
+
+ service_name = rte_service_get_name(service_id);
+ PMD_INIT_LOG(INFO, "Mapping service %s to core %u", service_name, slcore);
- memset(&service, 0, sizeof(struct rte_service_spec));
- snprintf(service.name, sizeof(service.name), "nfp_cpp_service");
- service.callback = nfp_cpp_bridge_service_func;
- service.callback_userdata = (void *)cpp;
+ ret = rte_service_map_lcore_set(service_id, slcore, 1);
+ if (ret != 0) {
+ PMD_INIT_LOG(DEBUG, "Could not map flower service");
+ return -ENOENT;
+ }
- if (rte_service_component_register(&service,
- cpp_service_id))
- RTE_LOG(WARNING, PMD, "NFP CPP bridge service register() failed");
+ rte_service_runstate_set(service_id, 1);
+ rte_service_component_runstate_set(service_id, 1);
+ rte_service_lcore_start(slcore);
+ if (rte_service_may_be_active(slcore))
+ PMD_INIT_LOG(INFO, "The service %s is running", service_name);
else
- RTE_LOG(DEBUG, PMD, "NFP CPP bridge service registered");
+ PMD_INIT_LOG(ERR, "The service %s is not running", service_name);
+
+ return 0;
+}
+
+int
+nfp_enable_cpp_service(struct nfp_cpp *cpp)
+{
+ int ret;
+ uint32_t service_id = 0;
+ struct rte_service_spec cpp_service = {
+ .name = "nfp_cpp_service",
+ .callback = nfp_cpp_bridge_service_func,
+ };
+
+ cpp_service.callback_userdata = (void *)cpp;
+
+ /* Register the cpp service */
+ ret = rte_service_component_register(&cpp_service, &service_id);
+ if (ret != 0) {
+ PMD_INIT_LOG(WARNING, "Could not register nfp cpp service");
+ return -EINVAL;
+ }
+
+ PMD_INIT_LOG(INFO, "NFP cpp service registered");
+
+ /* Map it to available service core*/
+ ret = nfp_map_service(service_id);
+ if (ret != 0) {
+ PMD_INIT_LOG(DEBUG, "Could not map nfp cpp service");
+ return -EINVAL;
+ }
+
+ return 0;
}
/*
@@ -307,7 +371,7 @@ void nfp_register_cpp_service(struct nfp_cpp *cpp)
* unaware of the CPP bridge performing the NFP kernel char driver for CPP
* accesses.
*/
-int32_t
+static int
nfp_cpp_bridge_service_func(void *args)
{
struct sockaddr address;
@@ -16,6 +16,8 @@
#ifndef _NFP_CPP_BRIDGE_H_
#define _NFP_CPP_BRIDGE_H_
+#include "nfp_common.h"
+
#define NFP_CPP_MEMIO_BOUNDARY (1 << 20)
#define NFP_BRIDGE_OP_READ 20
#define NFP_BRIDGE_OP_WRITE 30
@@ -24,8 +26,8 @@
#define NFP_IOCTL 'n'
#define NFP_IOCTL_CPP_IDENTIFICATION _IOW(NFP_IOCTL, 0x8f, uint32_t)
-void nfp_register_cpp_service(struct nfp_cpp *cpp);
-int32_t nfp_cpp_bridge_service_func(void *args);
+int nfp_enable_cpp_service(struct nfp_cpp *cpp);
+int nfp_map_service(uint32_t service_id);
#endif /* _NFP_CPP_BRIDGE_H_ */
/*
@@ -38,6 +38,8 @@
#include "nfp_ctrl.h"
#include "nfp_cpp_bridge.h"
+#include "flower/nfp_flower.h"
+
static int
nfp_net_pf_read_mac(struct nfp_app_fw_nic *app_fw_nic, int port)
{
@@ -969,6 +971,14 @@
goto hwqueues_cleanup;
}
break;
+ case NFP_APP_FW_FLOWER_NIC:
+ PMD_INIT_LOG(INFO, "Initializing Flower");
+ ret = nfp_init_app_fw_flower(pf_dev);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Could not initialize Flower!");
+ goto hwqueues_cleanup;
+ }
+ break;
default:
PMD_INIT_LOG(ERR, "Unsupported Firmware loaded");
ret = -EINVAL;
@@ -976,7 +986,12 @@
}
/* register the CPP bridge service here for primary use */
- nfp_register_cpp_service(pf_dev->cpp);
+ ret = nfp_enable_cpp_service(pf_dev->cpp);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Enable cpp service failed.");
+ ret = -EINVAL;
+ goto hwqueues_cleanup;
+ }
return 0;
@@ -1100,6 +1115,14 @@
goto sym_tbl_cleanup;
}
break;
+ case NFP_APP_FW_FLOWER_NIC:
+ PMD_INIT_LOG(INFO, "Initializing Flower");
+ ret = nfp_secondary_init_app_fw_flower(cpp);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Could not initialize Flower!");
+ goto sym_tbl_cleanup;
+ }
+ break;
default:
PMD_INIT_LOG(ERR, "Unsupported Firmware loaded");
ret = -EINVAL;
@@ -1107,7 +1130,11 @@
}
/* Register the CPP bridge service for the secondary too */
- nfp_register_cpp_service(cpp);
+ ret = nfp_enable_cpp_service(cpp);
+ if (ret != 0) {
+ PMD_INIT_LOG(ERR, "Enable cpp service failed.");
+ ret = -EINVAL;
+ }
sym_tbl_cleanup:
free(sym_tbl);