1// SPDX-License-Identifier: GPL-2.0 OR MIT
2/* Copyright (C) 2024 Pawel Dembicki <paweldembicki@gmail.com>
3 */
4#include <linux/dsa/8021q.h>
5
6#include "tag.h"
7#include "tag_8021q.h"
8
9#define VSC73XX_8021Q_NAME "vsc73xx-8021q"
10
11static struct sk_buff *
12vsc73xx_xmit(struct sk_buff *skb, struct net_device *netdev)
13{
14 struct dsa_port *dp = dsa_user_to_port(dev: netdev);
15 u16 queue_mapping = skb_get_queue_mapping(skb);
16 u16 tx_vid = dsa_tag_8021q_standalone_vid(dp);
17 u8 pcp;
18
19 if (skb->offload_fwd_mark) {
20 unsigned int bridge_num = dsa_port_bridge_num_get(dp);
21 struct net_device *br = dsa_port_bridge_dev_get(dp);
22
23 if (br_vlan_enabled(dev: br))
24 return skb;
25
26 tx_vid = dsa_tag_8021q_bridge_vid(bridge_num);
27 }
28
29 pcp = netdev_txq_to_tc(dev: netdev, txq: queue_mapping);
30
31 return dsa_8021q_xmit(skb, netdev, ETH_P_8021Q,
32 tci: ((pcp << VLAN_PRIO_SHIFT) | tx_vid));
33}
34
35static struct sk_buff *
36vsc73xx_rcv(struct sk_buff *skb, struct net_device *netdev)
37{
38 int src_port = -1, switch_id = -1, vbid = -1, vid = -1;
39
40 dsa_8021q_rcv(skb, source_port: &src_port, switch_id: &switch_id, vbid: &vbid, vid: &vid);
41
42 skb->dev = dsa_tag_8021q_find_user(conduit: netdev, source_port: src_port, switch_id,
43 vid, vbid);
44 if (!skb->dev) {
45 dev_warn_ratelimited(&netdev->dev,
46 "Couldn't decode source port\n");
47 return NULL;
48 }
49
50 dsa_default_offload_fwd_mark(skb);
51
52 return skb;
53}
54
55static const struct dsa_device_ops vsc73xx_8021q_netdev_ops = {
56 .name = VSC73XX_8021Q_NAME,
57 .proto = DSA_TAG_PROTO_VSC73XX_8021Q,
58 .xmit = vsc73xx_xmit,
59 .rcv = vsc73xx_rcv,
60 .needed_headroom = VLAN_HLEN,
61 .promisc_on_conduit = true,
62};
63
64MODULE_LICENSE("GPL");
65MODULE_DESCRIPTION("DSA tag driver for VSC73XX family of switches, using VLAN");
66MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_VSC73XX_8021Q, VSC73XX_8021Q_NAME);
67
68module_dsa_tag_driver(vsc73xx_8021q_netdev_ops);
69

source code of linux/net/dsa/tag_vsc73xx_8021q.c