DPDK usage discussions
 help / color / mirror / Atom feed
From: Gopinath K <gopinath.gk@zohomail.com>
To: "users" <users@dpdk.org>
Subject: Error with SEND_TO_KERNEL Action during Flow creation on Mellanox CX-5
Date: Tue, 05 Nov 2024 13:53:24 +0530	[thread overview]
Message-ID: <192fb6be188.1149bb382642049.7819154315379406165@zohomail.com> (raw)
In-Reply-To: 

[-- Attachment #1: Type: text/plain, Size: 7960 bytes --]

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 https://doc.dpdk.org/guides/howto/rte_flow.html 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(&eth_spec, 0, sizeof eth_spec);

    memset(&eth_mask, 0, sizeof eth_mask);

    pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;

    pattern[0].spec = &eth_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

[-- Attachment #2: Type: text/html, Size: 15731 bytes --]

             reply	other threads:[~2024-11-05  8:23 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-05  8:23 Gopinath K [this message]
2024-11-06  9:16 ` Bing Zhao
2024-11-06  9:22   ` Gopinath K

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=192fb6be188.1149bb382642049.7819154315379406165@zohomail.com \
    --to=gopinath.gk@zohomail.com \
    --cc=users@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).