Index-based Insertion Flow Rule
Flow rules can be inserted by calculating the hash value for the pattern or inserted by index via new a rte_flow_async_create_by_index() API. The index-based insertion enable the user to avoid additional match and simply execute predefined actions after jumping to the index in the table.
Specify special tag[255] as a pattern to jump to a particular index
flow pattern_template
0create pattern_template_id1ingress template tag index is255/ endSelect queue based on the index
flow actions_template
0create actions_template_id1template queue / end queue / endCreate a table with linear hash distribution and insertion by index type
flow template_table
0create table_id1group10priority0ingress rules_number65000insertion_type index hash_func linear pattern_template1actions_template1Distribute packets according to the index in tag[255]
flow queue
0create0template_table1rule_index0actions_template0postpone no pattern end actions queue index0/ end flow queue0create0template_table1rule_index1actions_template0postpone no pattern end actions queue index1/ end flow queue0create0template_table1rule_index2actions_template0postpone no pattern end actions queue index2/ end flow queue0create0template_table1rule_index3actions_template0postpone no pattern end actions queue index3/ end
struct rte_flow_pattern_template *
create_pattern_template(uint16_t port_id, struct rte_flow_error *error)
{
const struct rte_flow_item_tag tag_mask = {
.data = 0,
.index = MLX5_LINEAR_HASH_TAG_INDEX,
};
struct rte_flow_item pattern[] = {
{
.type = RTE_FLOW_ITEM_TYPE_TAG,
.mask = &tag_mask,
},
{
.type = RTE_FLOW_ITEM_TYPE_END,
},
};
const struct rte_flow_pattern_template_attr pt_attr = {
.relaxed_matching = 0,
.ingress = 1,
};
return rte_flow_pattern_template_create(port_id,
&pt_attr, pattern, &error);
}
struct rte_flow_actions_template *
create_actions_template(uint16_t port_id, struct rte_flow_error *error)
{
struct rte_flow_action_queue queue_v = {
.index = 0
};
struct rte_flow_action_queue queue_m = {
.index = UINT16_MAX
};
struct rte_flow_action actions[] = {
[0] = { /* queue action. */
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue_v },
[1] = { /* end action mast be the last action. */
.type = RTE_FLOW_ACTION_TYPE_END,},
};
struct rte_flow_action masks[] = {
[0] = { /* queue action. */
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue_m },
[1] = { /* end action mast be the last action. */
.type = RTE_FLOW_ACTION_TYPE_END,},
};
const struct rte_flow_actions_template_attr at_attr = {
.ingress = 1,
};
return rte_flow_actions_template_create(port_id, &at_attr,
actions, masks, error);
}
struct rte_flow_template_table *
create_table(uint16_t port_id, struct rte_flow_error *error)
{
struct rte_flow_pattern_template *pt;
struct rte_flow_actions_template *at;
const struct rte_flow_template_table_attr tbl_attr = {
.flow_attr = {
.group = 1,
.priority = 0,
.ingress = 1,
},
.nb_flows = 4,
.insertion_type = RTE_FLOW_TABLE_INSERTION_TYPE_INDEX,
.hash_func = RTE_FLOW_TABLE_HASH_FUNC_LINEAR,
};
struc
pt = create_pattern_template(port_id, error);
if (pt == NULL) {
printf("Failed to create pattern template: %s (%d) \n",
error.message, rte_errno);
return NULL;
}
at = create_actions_template(port_id, error);
if (at == NULL) {
printf("Failed to create actions template: %s (%d)\n",
error.message, rte_errno);
return NULL;
}
return rte_flow_template_table_create(port_id, &tbl_attr,
&pt, 1, &at, 1, error);
}
void
custom_hash_example(void)
{
uint32_t idx;
uint16_t port_id = PORT_ID;
uint32_t queue_id = QUEUE_ID;
struct rte_flow_error error = { 0 };
struct rte_flow_op_attr attr = {
.postpone = 0,
};
struct rte_flow_action_queue queue = {
.index = 0
};
struct rte_flow_action actions[] = {
[0] = { /* queue action. */
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue },
[1] = { /* end action mast be the last action. */
.type = RTE_FLOW_ACTION_TYPE_END,},
};
struct rte_flow_template_table * table;
struct rte_flow *flow;
table = create_table(port_id, &error);
if (table == NULL) {
printf("Failed to create template table: %s (%d)\n",
error.message, rte_errno);
rte_exit(EXIT_FAILURE, "Exiting");
}
for (idx = 0, idx < 4, idx++) {
queue.index = idx;
flow = rte_flow_async_create_by_index(port_id, queue_id,
&attr, table, idx, actions, 0, NULL, &error);
if (flow == NULL) {
printf("Failed to enqueue flow create operation: %s (%d) \n",
error.message, rte_errno);
rte_exit(EXIT_FAILURE, "Exiting");
};
}
}