diff options
author | Louis Peens <louis.peens@netronome.com> | 2020-08-20 16:39:38 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-08-20 16:04:42 -0700 |
commit | 0d630f58989a1ac741dc6cb0afd49daa95aac0fc (patch) | |
tree | bccc044017dc5f14cfdbaa260180b6767389f295 /drivers/net/ethernet/netronome/nfp/flower/match.c | |
parent | e4cab45a19cde8c03e9af3124ef1513ed58ca3a6 (diff) | |
download | lwn-0d630f58989a1ac741dc6cb0afd49daa95aac0fc.tar.gz lwn-0d630f58989a1ac741dc6cb0afd49daa95aac0fc.zip |
nfp: flower: add support to offload QinQ match
When both the driver and the firmware supports QinQ the flow key
structure that is send to the firmware is updated as the old
method of matching on VLAN did not allow for space to add another
VLAN tag. VLAN flows can now also match on the tpid field, not
constrained to just 0x8100 as before.
Signed-off-by: Louis Peens <louis.peens@netronome.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/netronome/nfp/flower/match.c')
-rw-r--r-- | drivers/net/ethernet/netronome/nfp/flower/match.c | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/flower/match.c b/drivers/net/ethernet/netronome/nfp/flower/match.c index 64690511e47b..255a4dff6288 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/match.c +++ b/drivers/net/ethernet/netronome/nfp/flower/match.c @@ -10,7 +10,7 @@ static void nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *ext, struct nfp_flower_meta_tci *msk, - struct flow_rule *rule, u8 key_type) + struct flow_rule *rule, u8 key_type, bool qinq_sup) { u16 tmp_tci; @@ -24,7 +24,7 @@ nfp_flower_compile_meta_tci(struct nfp_flower_meta_tci *ext, msk->nfp_flow_key_layer = key_type; msk->mask_id = ~0; - if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + if (!qinq_sup && flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { struct flow_match_vlan match; flow_rule_match_vlan(rule, &match); @@ -231,6 +231,50 @@ nfp_flower_compile_ip_ext(struct nfp_flower_ip_ext *ext, } static void +nfp_flower_fill_vlan(struct flow_dissector_key_vlan *key, + struct nfp_flower_vlan *frame, + bool outer_vlan) +{ + u16 tci; + + tci = NFP_FLOWER_MASK_VLAN_PRESENT; + tci |= FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO, + key->vlan_priority) | + FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID, + key->vlan_id); + + if (outer_vlan) { + frame->outer_tci = cpu_to_be16(tci); + frame->outer_tpid = key->vlan_tpid; + } else { + frame->inner_tci = cpu_to_be16(tci); + frame->inner_tpid = key->vlan_tpid; + } +} + +static void +nfp_flower_compile_vlan(struct nfp_flower_vlan *ext, + struct nfp_flower_vlan *msk, + struct flow_rule *rule) +{ + struct flow_match_vlan match; + + memset(ext, 0, sizeof(struct nfp_flower_vlan)); + memset(msk, 0, sizeof(struct nfp_flower_vlan)); + + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) { + flow_rule_match_vlan(rule, &match); + nfp_flower_fill_vlan(match.key, ext, true); + nfp_flower_fill_vlan(match.mask, msk, true); + } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) { + flow_rule_match_cvlan(rule, &match); + nfp_flower_fill_vlan(match.key, ext, false); + nfp_flower_fill_vlan(match.mask, msk, false); + } +} + +static void nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *ext, struct nfp_flower_ipv4 *msk, struct flow_rule *rule) { @@ -433,6 +477,8 @@ int nfp_flower_compile_flow_match(struct nfp_app *app, struct netlink_ext_ack *extack) { struct flow_rule *rule = flow_cls_offload_flow_rule(flow); + struct nfp_flower_priv *priv = app->priv; + bool qinq_sup; u32 port_id; int ext_len; int err; @@ -447,9 +493,11 @@ int nfp_flower_compile_flow_match(struct nfp_app *app, ext = nfp_flow->unmasked_data; msk = nfp_flow->mask_data; + qinq_sup = !!(priv->flower_ext_feats & NFP_FL_FEATS_VLAN_QINQ); + nfp_flower_compile_meta_tci((struct nfp_flower_meta_tci *)ext, (struct nfp_flower_meta_tci *)msk, - rule, key_ls->key_layer); + rule, key_ls->key_layer, qinq_sup); ext += sizeof(struct nfp_flower_meta_tci); msk += sizeof(struct nfp_flower_meta_tci); @@ -548,6 +596,14 @@ int nfp_flower_compile_flow_match(struct nfp_app *app, } } + if (NFP_FLOWER_LAYER2_QINQ & key_ls->key_layer_two) { + nfp_flower_compile_vlan((struct nfp_flower_vlan *)ext, + (struct nfp_flower_vlan *)msk, + rule); + ext += sizeof(struct nfp_flower_vlan); + msk += sizeof(struct nfp_flower_vlan); + } + if (key_ls->key_layer & NFP_FLOWER_LAYER_VXLAN || key_ls->key_layer_two & NFP_FLOWER_LAYER2_GENEVE) { if (key_ls->key_layer_two & NFP_FLOWER_LAYER2_TUN_IPV6) { |