net: ethernet: mtk_ppe_offload: Allow QinQ, double ETH_P_8021Q only
authorEric Woudstra <ericwouds@gmail.com>
Tue, 25 Feb 2025 20:15:09 +0000 (21:15 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 27 Feb 2025 13:31:37 +0000 (14:31 +0100)
mtk_foe_entry_set_vlan() in mtk_ppe.c already supports double vlan
tagging, but mtk_flow_offload_replace() in mtk_ppe_offload.c only allows
for 1 vlan tag, optionally in combination with pppoe and dsa tags.

However, mtk_foe_entry_set_vlan() only allows for setting the vlan id.
The protocol cannot be set, it is always ETH_P_8021Q, for inner and outer
tag. This patch adds QinQ support to mtk_flow_offload_replace(), only in
the case that both inner and outer tags are ETH_P_8021Q.

Only PPPoE-in-Q (as before) and Q-in-Q are allowed. A combination
of PPPoE and Q-in-Q is not allowed.

Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
Link: https://patch.msgid.link/20250225201509.20843-1-ericwouds@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/mediatek/mtk_ppe_offload.c

index f20bb390df3add25873130ade2ad93ab5b01fe43..c855fb799ce1456fda12b43011e48ea0647c0804 100644 (file)
@@ -34,8 +34,10 @@ struct mtk_flow_data {
        u16 vlan_in;
 
        struct {
-               u16 id;
-               __be16 proto;
+               struct {
+                       u16 id;
+                       __be16 proto;
+               } vlans[2];
                u8 num;
        } vlan;
        struct {
@@ -349,18 +351,19 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
                case FLOW_ACTION_CSUM:
                        break;
                case FLOW_ACTION_VLAN_PUSH:
-                       if (data.vlan.num == 1 ||
+                       if (data.vlan.num + data.pppoe.num == 2 ||
                            act->vlan.proto != htons(ETH_P_8021Q))
                                return -EOPNOTSUPP;
 
-                       data.vlan.id = act->vlan.vid;
-                       data.vlan.proto = act->vlan.proto;
+                       data.vlan.vlans[data.vlan.num].id = act->vlan.vid;
+                       data.vlan.vlans[data.vlan.num].proto = act->vlan.proto;
                        data.vlan.num++;
                        break;
                case FLOW_ACTION_VLAN_POP:
                        break;
                case FLOW_ACTION_PPPOE_PUSH:
-                       if (data.pppoe.num == 1)
+                       if (data.pppoe.num == 1 ||
+                           data.vlan.num == 2)
                                return -EOPNOTSUPP;
 
                        data.pppoe.sid = act->pppoe.sid;
@@ -450,12 +453,9 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f,
        if (offload_type == MTK_PPE_PKT_TYPE_BRIDGE)
                foe.bridge.vlan = data.vlan_in;
 
-       if (data.vlan.num == 1) {
-               if (data.vlan.proto != htons(ETH_P_8021Q))
-                       return -EOPNOTSUPP;
+       for (i = 0; i < data.vlan.num; i++)
+               mtk_foe_entry_set_vlan(eth, &foe, data.vlan.vlans[i].id);
 
-               mtk_foe_entry_set_vlan(eth, &foe, data.vlan.id);
-       }
        if (data.pppoe.num == 1)
                mtk_foe_entry_set_pppoe(eth, &foe, data.pppoe.sid);