Steering by Integrity Check Flags
Now steering can be performed by a new RTE flow item RTE_FLOW_ITEM_TYPE_INTEGRITY
to enable matching on l3_ok, ipv4_csum_ok, l4_ok
and l4_csum_ok
.
l3_ok (bit 2): If set, packet is matched to IPv4/IPv6, and the length of the data is not larger than the packet's length. For IPv4, protocol version is also verified.
l4_ok (bit 3):
In case of UDP - the packet has a valid length. For bad UDP, the length field is greater than the packet.
In case of TCP - a valid data offset value. For TCP the data offset value is greater than the packet size.
ipv4_csum_ok (bit 5): The IPv4 checksum is correct.
l4_csum_ok (bit 6): The UDP/TCP checksum is correct.
The item parameter `level’ select between inner and outer parts:
0,1 – outer
Level > 2 - inner
Match on a valid L3 packet (IPv4/IPv6):
testpmd> flow create 0 ingress pattern eth / {ipv4|ipv6} / tcp / integrity level is 0 value spec 4 value mask 4 / end actions queue index 1
Match on a valid L4 packet including checksum:
testpmd> flow create 0 ingress pattern eth / {ipv4|ipv6} / tcp / integrity level is 0 value mask 0x48 value spec 0x48 / end actions queue index 1
Match on a bad IPv4 checksum:
testpmd> flow create 0 ingress pattern eth / ipv4 / tcp / integrity level 0 value spec 0 value mask 32 / end actions queue index 1
static int add_integrity_checks_items(void) {
struct rte_flow_action_queue queue = { .index = rx_q };
struct rte_flow_item_ipv4 ip_spec;
struct rte_flow_item_ipv4 ip_mask;
struct rte_flow_item_integrity integrity_spec =
{.level = 0, .l3_ok = 1, . ipv4_csum_ok = 1};
struct rte_flow_item_integrity integrity_mask =
{.level = 0, .l3_ok = 1, .l4_ok = 0, .ipv4_csum_ok = 1};
int res;
memset(pattern, 0, sizeof(pattern));
memset(action, 0, sizeof(action));
/*
* set the rule attribute.
* in this case only ingress packets will be checked.
*/
memset(&attr, 0, sizeof(struct rte_flow_attr));
attr.ingress = 1;
/*
* create the action sequence.
* one action only, move packet to queue
*/
action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
action[0].conf = &queue;
action[1].type = RTE_FLOW_ACTION_TYPE_END;
/*
* set the first level of the pattern (ETH).
* since in this example we just want to get the
* ipv4 we set this level to allow all.
*/
pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
/*
* setting the second level of the pattern (IP).
* in this example this is the level we care about
* so we set it according to the parameters.
*/
memset(&ip_spec, 0, sizeof(struct rte_flow_item_ipv4));
memset(&ip_mask, 0, sizeof(struct rte_flow_item_ipv4));
ip_spec.hdr.dst_addr = htonl(dest_ip);
ip_mask.hdr.dst_addr = dest_mask;
ip_spec.hdr.src_addr = htonl(src_ip);
ip_mask.hdr.src_addr = src_mask;
pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
pattern[1].spec = &ip_spec;
pattern[1].mask = &ip_mask;
/*
* check for a valid ipv4 packet.
*/
pattern[2].type = RTE_FLOW_ITEM_TYPE_INTEGRITY;
pattern[2].spec = &integrity_spec;
pattern[2].mask = &integrity_mask;
/* the final level must be always type end */
pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
}