Raw Ethernet Programming: Flow ID Steering - Code Example

Version 6

    This post shows how to steer packets using flow ID, when developing Raw Ethernet over verbs.

    This feature is available starting with MLNX_OFED 3.4.




    In order to steer traffic according to flow id (tag_id), you need to use the ibv_exp_flow_attr struct and call ibv_exp_cmd_create_flow.

    The application appends several specs for each feature at the end of the struct, as described here:


    struct ibv_exp_flow_attr {

            enum ibv_exp_flow_attr_type type;

            uint16_t size;

            uint16_t priority;

            uint8_t num_of_specs;

            uint8_t port;

            uint32_t flags;

            /* Following are the optional layers according to the user request

             * struct ibv_exp_flow_spec_xxx [L2]

             * struct ibv_exp_flow_spec_yyy [L3/L4]


            uint64_t reserved; /* reserved for future growth (must be 0) */



    The flow steering creation is made through a container struct ibv_exp_flow_attr, which includes specification control header followed by the flow specification itself.



    1. Set the number of specs to add 1. For example, if no specs were specified before, change num_of_specs from 0 to 1.

    2. Configure the ibv_exp_flow_spec_action_tag struct as follows:

    struct ibv_exp_flow_spec_action_tag {

            enum ibv_exp_flow_spec_type  type;

            uint16_t size;

            uint32_t tag_id;


    • type: Need to use IBV_EXP_FLOW_SPEC_ACTION_TAG to define spec as an action spec.
    • size: The size of ibv_exp_kern_spec_action_tag.
    • tag_id: The flow ID, as defined by the application.


    For example, use as a reference Raw Ethernet Programming: Basic Introduction - Code Example , and make the following changes in the receiver side.

    /* 12. Register steering rule to intercept packet to DEST_MAC and place packet in ring pointed by ->qp */

        struct raw_eth_flow_attr {

            struct ibv_exp_flow_attr        attr;

            struct ibv_flow_spec_action_tag  action_tag;

        } __attribute__((packed)) flow_attr = {

            .attr = {

                .comp_mask  = 0,

                .type       = IBV_FLOW_ATTR_NORMAL,

                .size       = sizeof(flow_attr),

                .priority   = 0,

                .num_of_specs   = 1,

                .port       = PORT_NUM,

                .flags      = 0,


            .action_tag = {

                .type   = IBV_EXP_FLOW_SPEC_ACTION_TAG,

                .size   = sizeof(struct ibv_exp_kern_spec_action_tag),

                .tag_id = 100,




        /* 13. Create steering rule */

        struct ibv_flow *eth_flow;

        eth_flow = ibv_exp_cmd_create_flow(qp, &flow_attr.attr);

        if (!eth_flow) {

            fprintf(stderr, "Couldn't attach steering flow\n");