When a VLAN pattern is present, the flow handler always copies its inner_type to the match buffer regardless of its value (i.e. HW matches inner_type against packet's inner ethertype). When inner_type spec and mask are both 0, adding it to the match buffer is usually harmless but breaks the following pattern used in some applications like OVS-DPDK.
flow create 0 ingress ... pattern eth ... type is 0x0800 / vlan tci spec 0x2 \ tci mask 0xefff / ipv4 / end actions count / of_pop_vlan / ... The VLAN pattern's inner_type is 0. And the outer eth pattern's type actually specifies the inner ethertype. The outer ethertype (0x0800) is first copied to the match buffer. Then, the driver copies inner_type (0) to the match buffer, which overwrites the existing 0x0800 with 0 and breaks the app usage above. Simply ignore inner_type when it is 0, which is the correct behavior. As a byproduct, the driver can support the usage like the above. Fixes: ea7768b5bba8 ("net/enic: add flow implementation based on Flow Manager API") Cc: sta...@dpdk.org Signed-off-by: Hyong Youb Kim <hyon...@cisco.com> Reviewed-by: John Daley <johnd...@cisco.com> --- drivers/net/enic/enic_fm_flow.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/enic/enic_fm_flow.c b/drivers/net/enic/enic_fm_flow.c index 5f22f2a32..a350b29a3 100644 --- a/drivers/net/enic/enic_fm_flow.c +++ b/drivers/net/enic/enic_fm_flow.c @@ -392,8 +392,11 @@ enic_fm_copy_item_vlan(struct copy_item_args *arg) eth_mask = (void *)&fm_mask->l2.eth; eth_val = (void *)&fm_data->l2.eth; - /* Outer TPID cannot be matched */ - if (eth_mask->ether_type) + /* + * Outer TPID cannot be matched. If inner_type is 0, use what is + * in the eth header. + */ + if (eth_mask->ether_type && mask->inner_type) return -ENOTSUP; /* @@ -401,8 +404,10 @@ enic_fm_copy_item_vlan(struct copy_item_args *arg) * L2, regardless of vlan stripping settings. So, the inner type * from vlan becomes the ether type of the eth header. */ - eth_mask->ether_type = mask->inner_type; - eth_val->ether_type = spec->inner_type; + if (mask->inner_type) { + eth_mask->ether_type = mask->inner_type; + eth_val->ether_type = spec->inner_type; + } fm_data->fk_header_select |= FKH_ETHER | FKH_QTAG; fm_mask->fk_header_select |= FKH_ETHER | FKH_QTAG; fm_data->fk_vlan = rte_be_to_cpu_16(spec->tci); -- 2.26.2