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.

     

    References

     

    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.

     

    Configuration

    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");

            exit(1);

        }