Matching Random Value
Add support for matching 16 bits random in HW steering mode.
This value is not based on the packet data/headers.
Application shouldn't assume that this value is kept during the lifetime of the packet.
When the purpose of matching on random value is for getting certain percentage, the table should contain only one single flow rule.
Create a template table with 2 bits random values.
flow pattern_template 0
create pattern_template_id 1
ingress template random value mask 0x3
/ eth / end
flow actions_template 0
create actions_template_id 1
template queue / end mask queue / end
flow template_table 0
create table_id 1
group 1
priority 0
ingress rules_number 1
pattern_template 1
actions_template 1
Create a flow matches 25% of the traffic.
flow queue 0
create 0
template_table 1
pattern_template 0
actions_template 0
postpone no pattern random value spec 0x0
/ eth / end actions queue index 1
/ end
struct rte_flow_pattern_template *
create_pattern_template(uint16_t port_id, struct rte_flow_error *error)
{
struct rte_flow_item_random random_item = {
.value = 0x3
,
};
struct rte_flow_item pattern[] = {
{
.type = RTE_FLOW_ITEM_TYPE_RANDOM,
.mask = &random_item,
},
{
.type = RTE_FLOW_ITEM_TYPE_ETH,
},
{
.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[] = {
{
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue_v,
},
{
.type = RTE_FLOW_ACTION_TYPE_END,
},
};
struct rte_flow_action masks[] = {
{
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue_m,
},
{
.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 = 1
,
};
pt = create_pattern_template(port_id, error);
if
(pt == NULL) {
printf("Failed to create pattern template: %s (%s) \n"
,
error.message, rte_strerror(rte_errno));
return
NULL;
}
at = create_actions_template(port_id, error);
if
(at[0
] == NULL) {
printf("Failed to create actions template: %s (%s)\n"
,
error.message, rte_strerror(rte_errno));
return
NULL;
}
return
rte_flow_template_table_create(port_id, &tbl_attr, &pt, 1
, &at, 1
, error);
}
void
create_random_rule(void
)
{
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_item_random random_item = {
.value = 0
,
};
struct rte_flow_item pattern[] = {
{
.type = RTE_FLOW_ITEM_TYPE_RANDOM,
.spec = &random_item,
},
{
.type = RTE_FLOW_ITEM_TYPE_ETH,
},
{
.type = RTE_FLOW_ITEM_TYPE_END,
},
};
struct rte_flow_action_queue queue = {
.index = UINT16_MAX
};
struct rte_flow_action actions[] = {
{
.type = RTE_FLOW_ACTION_TYPE_QUEUE,
.conf = &queue
},
{
.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 (%s)\n"
,
error.message, rte_strerror(rte_errno));
rte_exit(EXIT_FAILURE, "Exiting"
);
}
flow = rte_flow_async_create(port_id, queue_id, &attr, table, pattern, 0
, actions, 1
, NULL, &error);
if
(flow == NULL) {
printf("Failed to enqueue flow create operation: %s (%s) \n"
,
error.message, rte_strerror(rte_errno));
rte_exit(EXIT_FAILURE, "Exiting"
);
};
}