Data Path Hash Calculation
Data Path Hash is used by the application to predict what hash will be calculated for a received packet that is detected as if the packet has passed the hardware. The application can decide how to handle the calculation process based on the hash value, (e.g., forwarding to a specific port). The received packet in the slow path, (e.g., the first or the fragmented packet without hitting any offloading rule), can have the same handling as the following packets offloaded. This behavior removes some inconsistent behavior issue between slow path and data path, like the packets reordering within the same traffic flow.
For further information, see also:
https://doc.dpdk.org/guides/testpmd_app_ug/testpmd_funcs.html#calculating-hash
https://doc.dpdk.org/guides/prog_guide/rte_flow.html#calculate-hash
The following is an example of a use case:
The application has two tables where each table in its own group. In the first table, the application matches 5 tuple count the packets and jumps to the second table. The second table is configured with a CRC 32 hash, is inserted by the index and used to load balance the packets between the different physical ports based on the UDP source port modulo 2 (there will be only two rules in the second table).
If a packet arrives to the 5 tuple table and does not match any of the rules, the packet is routed to the application so it can offload the corresponding rule to the 5 tuple table. When the application receives such a packet, it needs to know to which port to forward it.
The port must match the port that all the rest of the packets matching the UDP source port will go to in order for the application to know the hash result for the given packet in the second table.
Create the table on which you want to calculate the hash.
flow pattern_template
0create pattern_template_id8ingress template eth / ipv4 / udp src mask0xffff/ end flow actions_template0create actions_template_id8template queue index1/ end mask queue index0/ end flow template_table0create table_id8priority0ingress rules_number2hash_func crc32 insertion_type index group1pattern_template8actions_template8Calculate the hash for the given pattern.
flow hash
0template_table8pattern_template0pattern eth / ipv4 / udp src spec100/ end
Int rte_flow_calc_table_hash(uint16_t port_id, const struct rte_flow_template_table *table,
const struct rte_flow_item pattern[], uint8_t pattern_template_index,
uint32_t *hash, struct rte_flow_error *error);
static struct rte_flow_actions_template *
create_action_template(uint16_t port)
{
struct rte_flow_actions_template_attr at_attr = { .transfer = 1 };
struct rte_flow_error error;
struct rte_flow_action actions[] = {
{
.type = RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
},
{
.type = RTE_FLOW_ACTION_TYPE_END,
},
};
return rte_flow_actions_template_create(port, &at_attr, actions, actions, &error);
}
static struct rte_flow_pattern_template *
create_pattern_template(uint16_t port)
{
struct rte_flow_item_udp udp_mask = {.hdr.src_port = 0xffff};
struct rte_flow_pattern_template_attr pt_attr = { .transfer = 1 };
struct rte_flow_item pattern[] = {
{
.type = RTE_FLOW_ITEM_TYPE_ETH,
},
{
.type = RTE_FLOW_ITEM_TYPE_IPV4,
},
{
.type = RTE_FLOW_ITEM_TYPE_UDP,
.mask = &udp_mask,
},
{
.type = RTE_FLOW_ITEM_TYPE_END,
},
};
struct rte_flow_error error;
return rte_flow_pattern_template_create(port, &pt_attr, pattern, &error);
}
static struct rte_flow_template_table *
create_table(uint16_t port, struct rte_flow_pattern_template *pt, struct rte_flow_actions_template *at)
{
struct rte_flow_template_table_attr table_attr = {
.nb_flows = 2,
.flow_attr = { .transfer = 1, },
.hash_func = RTE_FLOW_TABLE_HASH_FUNC_DEFAULT,
.insertion_type = RTE_FLOW_TABLE_INSERTION_TYPE_INDEX,
};
struct rte_flow_template_table *table;
struct rte_flow_error error;
table = rte_flow_template_table_create(port, &table_attr, &pt, 1, &at, 1, &error);
return table;
}
static void
cleanup(uint16_t port,
struct rte_flow_actions_template *at,
struct rte_flow_pattern_template *pt,
struct rte_flow_template_table *table)
{
struct rte_flow_error error;
if (at)
rte_flow_actions_template_destroy(port, at, &error);
if (pt)
rte_flow_pattern_template_destroy(port, pt, &error);
if (table)
rte_flow_template_table_destroy(port, table, &error);
}
static int
calc_hash(uint16_t port, struct rte_flow_template_table *table, uint32_t src_port, uint32_t *hash)
{
struct rte_flow_item_udp udp = {.hdr.src_port = src_port};
struct rte_flow_item pattern[] = {
{
.type = RTE_FLOW_ITEM_TYPE_ETH,
},
{
.type = RTE_FLOW_ITEM_TYPE_IPV4,
},
{
.type = RTE_FLOW_ITEM_TYPE_UDP,
.spec = &udp,
},
{
.type = RTE_FLOW_ITEM_TYPE_END,
},
};
struct rte_flow_error error;
return rte_flow_calc_table_hash(port, table, pattern, 0, hash, &error);
}