xref: /linux/net/dsa/tag.c (revision aa0743a229366e8c1963f1b72a1c974a9d15f08f)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * DSA tagging protocol handling
4  *
5  * Copyright (c) 2008-2009 Marvell Semiconductor
6  * Copyright (c) 2013 Florian Fainelli <florian@openwrt.org>
7  * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
8  */
9 
10 #include <linux/netdevice.h>
11 #include <linux/ptp_classify.h>
12 #include <linux/skbuff.h>
13 #include <net/dsa.h>
14 #include <net/dst_metadata.h>
15 
16 #include "tag.h"
17 #include "user.h"
18 
19 static LIST_HEAD(dsa_tag_drivers_list);
20 static DEFINE_MUTEX(dsa_tag_drivers_lock);
21 
22 /* Determine if we should defer delivery of skb until we have a rx timestamp.
23  *
24  * Called from dsa_switch_rcv. For now, this will only work if tagging is
25  * enabled on the switch. Normally the MAC driver would retrieve the hardware
26  * timestamp when it reads the packet out of the hardware. However in a DSA
27  * switch, the DSA driver owning the interface to which the packet is
28  * delivered is never notified unless we do so here.
29  */
dsa_skb_defer_rx_timestamp(struct dsa_user_priv * p,struct sk_buff * skb)30 static bool dsa_skb_defer_rx_timestamp(struct dsa_user_priv *p,
31 				       struct sk_buff *skb)
32 {
33 	struct dsa_switch *ds = p->dp->ds;
34 	unsigned int type;
35 
36 	if (!ds->ops->port_rxtstamp)
37 		return false;
38 
39 	if (skb_headroom(skb) < ETH_HLEN)
40 		return false;
41 
42 	__skb_push(skb, ETH_HLEN);
43 
44 	type = ptp_classify_raw(skb);
45 
46 	__skb_pull(skb, ETH_HLEN);
47 
48 	if (type == PTP_CLASS_NONE)
49 		return false;
50 
51 	return ds->ops->port_rxtstamp(ds, p->dp->index, skb, type);
52 }
53 
dsa_switch_rcv(struct sk_buff * skb,struct net_device * dev,struct packet_type * pt,struct net_device * unused)54 static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev,
55 			  struct packet_type *pt, struct net_device *unused)
56 {
57 	struct metadata_dst *md_dst = skb_metadata_dst(skb);
58 	struct dsa_port *cpu_dp = dev->dsa_ptr;
59 	struct sk_buff *nskb = NULL;
60 	struct dsa_user_priv *p;
61 
62 	if (unlikely(!cpu_dp)) {
63 		kfree_skb(skb);
64 		return 0;
65 	}
66 
67 	skb = skb_unshare(skb, GFP_ATOMIC);
68 	if (!skb)
69 		return 0;
70 
71 	if (md_dst && md_dst->type == METADATA_HW_PORT_MUX) {
72 		unsigned int port = md_dst->u.port_info.port_id;
73 
74 		skb_dst_drop(skb);
75 		if (!skb_has_extensions(skb))
76 			skb->slow_gro = 0;
77 
78 		skb->dev = dsa_conduit_find_user(dev, 0, port);
79 		if (likely(skb->dev)) {
80 			dsa_default_offload_fwd_mark(skb);
81 			nskb = skb;
82 		}
83 	} else {
84 		nskb = cpu_dp->rcv(skb, dev);
85 	}
86 
87 	if (!nskb) {
88 		kfree_skb(skb);
89 		return 0;
90 	}
91 
92 	skb = nskb;
93 	skb_push(skb, ETH_HLEN);
94 	skb->pkt_type = PACKET_HOST;
95 	skb->protocol = eth_type_trans(skb, skb->dev);
96 
97 	if (unlikely(!dsa_user_dev_check(skb->dev))) {
98 		/* Packet is to be injected directly on an upper
99 		 * device, e.g. a team/bond, so skip all DSA-port
100 		 * specific actions.
101 		 */
102 		netif_rx(skb);
103 		return 0;
104 	}
105 
106 	p = netdev_priv(skb->dev);
107 
108 	if (unlikely(cpu_dp->ds->untag_bridge_pvid ||
109 		     cpu_dp->ds->untag_vlan_aware_bridge_pvid)) {
110 		nskb = dsa_software_vlan_untag(skb);
111 		if (!nskb) {
112 			kfree_skb(skb);
113 			return 0;
114 		}
115 		skb = nskb;
116 	}
117 
118 	dev_sw_netstats_rx_add(skb->dev, skb->len + ETH_HLEN);
119 
120 	if (dsa_skb_defer_rx_timestamp(p, skb))
121 		return 0;
122 
123 	gro_cells_receive(&p->gcells, skb);
124 
125 	return 0;
126 }
127 
128 struct packet_type dsa_pack_type __read_mostly = {
129 	.type	= cpu_to_be16(ETH_P_XDSA),
130 	.func	= dsa_switch_rcv,
131 };
132 
dsa_tag_driver_register(struct dsa_tag_driver * dsa_tag_driver,struct module * owner)133 static void dsa_tag_driver_register(struct dsa_tag_driver *dsa_tag_driver,
134 				    struct module *owner)
135 {
136 	dsa_tag_driver->owner = owner;
137 
138 	mutex_lock(&dsa_tag_drivers_lock);
139 	list_add_tail(&dsa_tag_driver->list, &dsa_tag_drivers_list);
140 	mutex_unlock(&dsa_tag_drivers_lock);
141 }
142 
dsa_tag_drivers_register(struct dsa_tag_driver * dsa_tag_driver_array[],unsigned int count,struct module * owner)143 void dsa_tag_drivers_register(struct dsa_tag_driver *dsa_tag_driver_array[],
144 			      unsigned int count, struct module *owner)
145 {
146 	unsigned int i;
147 
148 	for (i = 0; i < count; i++)
149 		dsa_tag_driver_register(dsa_tag_driver_array[i], owner);
150 }
151 
dsa_tag_driver_unregister(struct dsa_tag_driver * dsa_tag_driver)152 static void dsa_tag_driver_unregister(struct dsa_tag_driver *dsa_tag_driver)
153 {
154 	mutex_lock(&dsa_tag_drivers_lock);
155 	list_del(&dsa_tag_driver->list);
156 	mutex_unlock(&dsa_tag_drivers_lock);
157 }
158 EXPORT_SYMBOL_GPL(dsa_tag_drivers_register);
159 
dsa_tag_drivers_unregister(struct dsa_tag_driver * dsa_tag_driver_array[],unsigned int count)160 void dsa_tag_drivers_unregister(struct dsa_tag_driver *dsa_tag_driver_array[],
161 				unsigned int count)
162 {
163 	unsigned int i;
164 
165 	for (i = 0; i < count; i++)
166 		dsa_tag_driver_unregister(dsa_tag_driver_array[i]);
167 }
168 EXPORT_SYMBOL_GPL(dsa_tag_drivers_unregister);
169 
dsa_tag_protocol_to_str(const struct dsa_device_ops * ops)170 const char *dsa_tag_protocol_to_str(const struct dsa_device_ops *ops)
171 {
172 	return ops->name;
173 };
174 
175 /* Function takes a reference on the module owning the tagger,
176  * so dsa_tag_driver_put must be called afterwards.
177  */
dsa_tag_driver_get_by_name(const char * name)178 const struct dsa_device_ops *dsa_tag_driver_get_by_name(const char *name)
179 {
180 	const struct dsa_device_ops *ops = ERR_PTR(-ENOPROTOOPT);
181 	struct dsa_tag_driver *dsa_tag_driver;
182 
183 	request_module("%s%s", DSA_TAG_DRIVER_ALIAS, name);
184 
185 	mutex_lock(&dsa_tag_drivers_lock);
186 	list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) {
187 		const struct dsa_device_ops *tmp = dsa_tag_driver->ops;
188 
189 		if (strcmp(name, tmp->name))
190 			continue;
191 
192 		if (!try_module_get(dsa_tag_driver->owner))
193 			break;
194 
195 		ops = tmp;
196 		break;
197 	}
198 	mutex_unlock(&dsa_tag_drivers_lock);
199 
200 	return ops;
201 }
202 
dsa_tag_driver_get_by_id(int tag_protocol)203 const struct dsa_device_ops *dsa_tag_driver_get_by_id(int tag_protocol)
204 {
205 	struct dsa_tag_driver *dsa_tag_driver;
206 	const struct dsa_device_ops *ops;
207 	bool found = false;
208 
209 	request_module("%sid-%d", DSA_TAG_DRIVER_ALIAS, tag_protocol);
210 
211 	mutex_lock(&dsa_tag_drivers_lock);
212 	list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) {
213 		ops = dsa_tag_driver->ops;
214 		if (ops->proto == tag_protocol) {
215 			found = true;
216 			break;
217 		}
218 	}
219 
220 	if (found) {
221 		if (!try_module_get(dsa_tag_driver->owner))
222 			ops = ERR_PTR(-ENOPROTOOPT);
223 	} else {
224 		ops = ERR_PTR(-ENOPROTOOPT);
225 	}
226 
227 	mutex_unlock(&dsa_tag_drivers_lock);
228 
229 	return ops;
230 }
231 
dsa_tag_driver_put(const struct dsa_device_ops * ops)232 void dsa_tag_driver_put(const struct dsa_device_ops *ops)
233 {
234 	struct dsa_tag_driver *dsa_tag_driver;
235 
236 	mutex_lock(&dsa_tag_drivers_lock);
237 	list_for_each_entry(dsa_tag_driver, &dsa_tag_drivers_list, list) {
238 		if (dsa_tag_driver->ops == ops) {
239 			module_put(dsa_tag_driver->owner);
240 			break;
241 		}
242 	}
243 	mutex_unlock(&dsa_tag_drivers_lock);
244 }
245