Which FW and OFED version are you using? BTW, have you tried on 6-Dx and can you try on the non-root (>0) group? I remember of the send_to_kernel is only supported on non-root tables. From: Gopinath K Sent: Tuesday, November 5, 2024 4:23 PM To: users Subject: Error with SEND_TO_KERNEL Action during Flow creation on Mellanox CX-5 External email: Use caution opening links or attachments Hi, I'm new to DPDK, and have been working on creating flow rules by using DPDK, to steer traffic to the kernel. To understand the functionality of the Mellanox Bifuracted drive, i attempted to steer ICMP packets to Linux Kernel and other traffics to DPDK application. first i tried to create simple flow rule which drops the packet whose destination equals 192.168.3.2 (refrenced from from API examples) the flow created successfully without an error. However the issue arises when I attempt to use the RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL, which results in an error. Below the sample code. 1. functions to validate and create flow rule. static ::rte_flow* create_flow(uint16_t port_id, rte_flow_attr& attr, rte_flow_item& pattern, rte_flow_action& actions) { rte_flow_error error; auto flow = rte_flow_create(port_id, &attr, &pattern, &actions, &error); if (!flow) { printf("[create flow rule] failed to create flow rule, error: %s.\n", error.message); } return flow; } bool validate_flow(uint16_t port_id, rte_flow_attr& attr, rte_flow_item& pattern, rte_flow_action& action) { rte_flow_error error; auto res = rte_flow_validate(port_id, &attr, &pattern, &action, &error); if (res < 0) { printf("[validate flow rule] validate flow failed, error: %s\n", error.message); return false; } return true; } 2. function to enable isolated mode on network port. bool enable_isolated_mode(uint16_t port_id) { rte_flow_error error; // enable isolated mode. if (rte_flow_isolate(port_id, 1, &error) < 0) { printf("[isolated mode] failed to enable isolated mode on port %u, error: %s\n", port_id, error.message); return false; } printf("[isolated mode] isolated mode enabled on port %u\n", port_id); return true; } 3. port initialization function. static inline int port_initilization(uint16_t port, rte_mempool *mbuf_pool) { rte_eth_conf port_conf; if (!rte_eth_dev_is_valid_port(port)) { printf("[port init] port %u is not a valid port\n", port); return -1; } if (!enable_isolated_mode(port)) { return -1; } memset(&port_conf, 0, sizeof(rte_eth_conf)); rte_eth_dev_info device_info; auto retval = rte_eth_dev_info_get(port, &device_info); if (retval != 0) { printf("[pirt init] getting device(port %u) info, error: %d [%s]\n", port, rte_errno, ::rte_strerror(rte_errno)); return retval; } if (device_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) port_conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE; uint16_t rx_rings = 1; uint16_t tx_rings = 1; retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) { printf("[port init] failed to configure port(%u), error: %d [%s]\n", port, rte_errno, ::rte_strerror(rte_errno)); return retval; } uint16_t nb_rxd = RX_RING_SIZE; uint16_t nb_txd = TX_RING_SIZE; retval = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd); if (retval != 0) { printf("[port init] rte_eth_dev_adjust failed, error: %d [%s]\n", rte_errno, ::rte_strerror(rte_errno)); return retval; } for (auto q = 0; q < rx_rings; q++) { retval = rte_eth_rx_queue_setup(port, q, nb_rxd, rte_eth_dev_socket_id(port), NULL, mbuf_pool); if (retval < 0) return retval; } auto tx_conf = device_info.default_txconf; tx_conf.offloads = port_conf.txmode.offloads; for (auto q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port, q, nb_txd, rte_eth_dev_socket_id(port), &tx_conf); if (retval < 0) return retval; } ::rte_ether_addr addr; retval = rte_eth_macaddr_get(port, &addr); if (retval != 0) return retval; retval = rte_eth_dev_start(port); if (retval != 0) { printf("[port init] starting port %u failed, error: %d [%s]\n", port, rte_errno, rte_strerror(rte_errno)); return retval; } printf("[port init] successfully started port: %u\n", port); printf("port %u MAC: %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 " %02" PRIx8 "\n", port, RTE_ETHER_ADDR_BYTES(&addr)); init_ingress_flow_rules(port); init_egress_flow_rule(port); return 0; } 4. Flow rule static void init_ingress_flow_rule(uint32_t port_id) { rte_flow_attr attr = {0}; rte_flow_item pattern[4]; rte_flow_action action[2]; attr.ingress = 1; memset(pattern, 0, sizeof pattern); rte_flow_item_eth eth_spec; rte_flow_item_eth eth_mask; memset(ð_spec, 0, sizeof eth_spec); memset(ð_mask, 0, sizeof eth_mask); pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; pattern[0].spec = ð_spec; rte_flow_item_ipv4 ipv4_spec; rte_flow_item_ipv4 ipv4_mask; memset(&ipv4_spec, 0, sizeof ipv4_spec); memset(&ipv4_mask, 0, sizeof ipv4_mask); pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; pattern[1].spec = &ipv4_spec; pattern[1].mask = &ipv4_mask; rte_flow_item_icmp icmp_spec; rte_flow_item_icmp icmp_mask; memset(&icmp_spec, 0, sizeof icmp_spec); memset(&icmp_mask, 0, sizeof icmp_mask); icmp_spec.hdr.icmp_type = 0; pattern[2].type = RTE_FLOW_ITEM_TYPE_ICMP; pattern[2].spec = &icmp_spec; pattern[2].mask = &icmp_mask; pattern[3].type = RTE_FLOW_ITEM_TYPE_END; action[0].type = RTE_FLOW_ACTION_TYPE_SEND_TO_KERNEL; action[1].type = RTE_FLOW_ACTION_TYPE_END; if (validate_flow(port_id, attr, pattern[0], action[0])) { printf("[init flow rule] validated successfully.\n"); auto flow = create_flow(port_id, attr, pattern[0], action[0]); if (flow != NULL) { printf("[rte flow rule] successfully created a egress flow rule in port %u\n", port_id); } } } When I try to run the above program, the flow rule validated successfully with `rte_flow_validate()`, but failed on creating the flow with an error of `hardware refuses to create flow`. [init flow rule] validated successfully. [create flow rule] failed to create flow rule, error: hardware refuses to create flow. The same error arise when try to create the flow in `dpdk-testpmd` program. testpmd> flow isolate 0 true testpmd> port start 0 testpmd> flow create 0 ingress pattern eth / ipv4 / icmp / end actions send_to_kernel / end port_flow_complain(): Caught PMD error type 1 (cause unspecified): hardware refuses to create flow: Operation not supported Can anyone tell me whether my code is correct or not? Can anyone tell me whether my code is correct or not? and any idea how to use SEND_TO_KERNEL Action on Mellanox CX-5 NIC's. System specification. Operating System: Debian OS Version: 12.7 DPDK version: 24.07 Thanks and Regards, Gopinath. Sent using Zoho Mail