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
0
create pattern_template_id1
ingress template tag index is255
/ endSelect queue based on the index
flow actions_template
0
create actions_template_id1
template queue / end queue / endCreate a table with linear hash distribution and insertion by index type
flow template_table
0
create table_id1
group10
priority0
ingress rules_number65000
insertion_type index hash_func linear pattern_template1
actions_template1
Distribute packets according to the index in tag[255]
flow queue
0
create0
template_table1
rule_index0
actions_template0
postpone no pattern end actions queue index0
/ end flow queue0
create0
template_table1
rule_index1
actions_template0
postpone no pattern end actions queue index1
/ end flow queue0
create0
template_table1
rule_index2
actions_template0
postpone no pattern end actions queue index2
/ end flow queue0
create0
template_table1
rule_index3
actions_template0
postpone 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"
);
};
}
}