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
0
create pattern_template_id8
ingress template eth / ipv4 / udp src mask0xffff
/ end flow actions_template0
create actions_template_id8
template queue index1
/ end mask queue index0
/ end flow template_table0
create table_id8
priority0
ingress rules_number2
hash_func crc32 insertion_type index group1
pattern_template8
actions_template8
Calculate the hash for the given pattern.
flow hash
0
template_table8
pattern_template0
pattern 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);
}