|
| 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 | + |
| 11 | +static struct sk_buff * |
| 12 | +vsc73xx_xmit(struct sk_buff *skb, struct net_device *netdev) |
| 13 | +{ |
| 14 | + struct dsa_port *dp = dsa_user_to_port(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(br)) |
| 24 | + return skb; |
| 25 | + |
| 26 | + tx_vid = dsa_tag_8021q_bridge_vid(bridge_num); |
| 27 | + } |
| 28 | + |
| 29 | + pcp = netdev_txq_to_tc(netdev, queue_mapping); |
| 30 | + |
| 31 | + return dsa_8021q_xmit(skb, netdev, ETH_P_8021Q, |
| 32 | + ((pcp << VLAN_PRIO_SHIFT) | tx_vid)); |
| 33 | +} |
| 34 | + |
| 35 | +static struct sk_buff * |
| 36 | +vsc73xx_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, &src_port, &switch_id, &vbid, &vid); |
| 41 | + |
| 42 | + skb->dev = dsa_tag_8021q_find_user(netdev, 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 | + |
| 55 | +static 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 | + |
| 64 | +MODULE_LICENSE("GPL"); |
| 65 | +MODULE_DESCRIPTION("DSA tag driver for VSC73XX family of switches, using VLAN"); |
| 66 | +MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_VSC73XX_8021Q, VSC73XX_8021Q_NAME); |
| 67 | + |
| 68 | +module_dsa_tag_driver(vsc73xx_8021q_netdev_ops); |
0 commit comments