diff --git a/include/net/dsa.h b/include/net/dsa.h index a4f66dbb4b7c06f3bae090802ca408ac197be479..7f46b521313e51fdd032bd957f386d704c30e2c8 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -101,6 +101,15 @@ struct dsa_platform_data { struct packet_type; +struct dsa_device_ops { + struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); + struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pt, + struct net_device *orig_dev); + int (*flow_dissect)(const struct sk_buff *skb, __be16 *proto, + int *offset); +}; + struct dsa_switch_tree { struct list_head list; diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 0cc672aba1f00e58ecdaa83d6fdc1d53ef9eec19..5b5be9577257308cb143b2c98eaf3d47881bbf3f 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -440,6 +441,17 @@ bool __skb_flow_dissect(const struct sk_buff *skb, skb->vlan_proto : skb->protocol; nhoff = skb_network_offset(skb); hlen = skb_headlen(skb); + if (unlikely(netdev_uses_dsa(skb->dev))) { + const struct dsa_device_ops *ops; + int offset; + + ops = skb->dev->dsa_ptr->tag_ops; + if (ops->flow_dissect && + !ops->flow_dissect(skb, &proto, &offset)) { + hlen -= offset; + nhoff += offset; + } + } } /* It is ensured by skb_flow_dissector_init() that control key will diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 1debf9c42fc4219c29bd8738b797d2168276a3c8..9c3eeb72462d88cfa77704884ad083c8e462bf5b 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -65,13 +65,6 @@ struct dsa_notifier_vlan_info { int port; }; -struct dsa_device_ops { - struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); - struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt, - struct net_device *orig_dev); -}; - struct dsa_slave_priv { /* Copy of dp->ds->dst->tag_ops->xmit for faster access in hot path */ struct sk_buff * (*xmit)(struct sk_buff *skb, diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c index 2f32b7ea3365ce87f61e6a5002fbe45a4228e85f..02163c045a96ac639891931583585881eac08b2e 100644 --- a/net/dsa/tag_mtk.c +++ b/net/dsa/tag_mtk.c @@ -87,7 +87,17 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev, return skb; } +static int mtk_tag_flow_dissect(const struct sk_buff *skb, __be16 *proto, + int *offset) +{ + *offset = 4; + *proto = ((__be16 *)skb->data)[1]; + + return 0; +} + const struct dsa_device_ops mtk_netdev_ops = { - .xmit = mtk_tag_xmit, - .rcv = mtk_tag_rcv, + .xmit = mtk_tag_xmit, + .rcv = mtk_tag_rcv, + .flow_dissect = mtk_tag_flow_dissect, };