1 /*
2  * net/switchdev/switchdev.c - Switch device API
3  * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
4  * Copyright (c) 2014-2015 Scott Feldman <sfeldma@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/types.h>
14 #include <linux/init.h>
15 #include <linux/mutex.h>
16 #include <linux/notifier.h>
17 #include <linux/netdevice.h>
18 #include <linux/rtnetlink.h>
19 #include <net/ip_fib.h>
20 #include <net/switchdev.h>
21 
22 /**
23  *	netdev_switch_parent_id_get - Get ID of a switch
24  *	@dev: port device
25  *	@psid: switch ID
26  *
27  *	Get ID of a switch this port is part of.
28  */
netdev_switch_parent_id_get(struct net_device * dev,struct netdev_phys_item_id * psid)29 int netdev_switch_parent_id_get(struct net_device *dev,
30 				struct netdev_phys_item_id *psid)
31 {
32 	const struct swdev_ops *ops = dev->swdev_ops;
33 
34 	if (!ops || !ops->swdev_parent_id_get)
35 		return -EOPNOTSUPP;
36 	return ops->swdev_parent_id_get(dev, psid);
37 }
38 EXPORT_SYMBOL_GPL(netdev_switch_parent_id_get);
39 
40 /**
41  *	netdev_switch_port_stp_update - Notify switch device port of STP
42  *					state change
43  *	@dev: port device
44  *	@state: port STP state
45  *
46  *	Notify switch device port of bridge port STP state change.
47  */
netdev_switch_port_stp_update(struct net_device * dev,u8 state)48 int netdev_switch_port_stp_update(struct net_device *dev, u8 state)
49 {
50 	const struct swdev_ops *ops = dev->swdev_ops;
51 	struct net_device *lower_dev;
52 	struct list_head *iter;
53 	int err = -EOPNOTSUPP;
54 
55 	if (ops && ops->swdev_port_stp_update)
56 		return ops->swdev_port_stp_update(dev, state);
57 
58 	netdev_for_each_lower_dev(dev, lower_dev, iter) {
59 		err = netdev_switch_port_stp_update(lower_dev, state);
60 		if (err && err != -EOPNOTSUPP)
61 			return err;
62 	}
63 
64 	return err;
65 }
66 EXPORT_SYMBOL_GPL(netdev_switch_port_stp_update);
67 
68 static RAW_NOTIFIER_HEAD(netdev_switch_notif_chain);
69 
70 /**
71  *	register_netdev_switch_notifier - Register notifier
72  *	@nb: notifier_block
73  *
74  *	Register switch device notifier. This should be used by code
75  *	which needs to monitor events happening in particular device.
76  *	Return values are same as for atomic_notifier_chain_register().
77  */
register_netdev_switch_notifier(struct notifier_block * nb)78 int register_netdev_switch_notifier(struct notifier_block *nb)
79 {
80 	int err;
81 
82 	rtnl_lock();
83 	err = raw_notifier_chain_register(&netdev_switch_notif_chain, nb);
84 	rtnl_unlock();
85 	return err;
86 }
87 EXPORT_SYMBOL_GPL(register_netdev_switch_notifier);
88 
89 /**
90  *	unregister_netdev_switch_notifier - Unregister notifier
91  *	@nb: notifier_block
92  *
93  *	Unregister switch device notifier.
94  *	Return values are same as for atomic_notifier_chain_unregister().
95  */
unregister_netdev_switch_notifier(struct notifier_block * nb)96 int unregister_netdev_switch_notifier(struct notifier_block *nb)
97 {
98 	int err;
99 
100 	rtnl_lock();
101 	err = raw_notifier_chain_unregister(&netdev_switch_notif_chain, nb);
102 	rtnl_unlock();
103 	return err;
104 }
105 EXPORT_SYMBOL_GPL(unregister_netdev_switch_notifier);
106 
107 /**
108  *	call_netdev_switch_notifiers - Call notifiers
109  *	@val: value passed unmodified to notifier function
110  *	@dev: port device
111  *	@info: notifier information data
112  *
113  *	Call all network notifier blocks. This should be called by driver
114  *	when it needs to propagate hardware event.
115  *	Return values are same as for atomic_notifier_call_chain().
116  *	rtnl_lock must be held.
117  */
call_netdev_switch_notifiers(unsigned long val,struct net_device * dev,struct netdev_switch_notifier_info * info)118 int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev,
119 				 struct netdev_switch_notifier_info *info)
120 {
121 	int err;
122 
123 	ASSERT_RTNL();
124 
125 	info->dev = dev;
126 	err = raw_notifier_call_chain(&netdev_switch_notif_chain, val, info);
127 	return err;
128 }
129 EXPORT_SYMBOL_GPL(call_netdev_switch_notifiers);
130 
131 /**
132  *	netdev_switch_port_bridge_setlink - Notify switch device port of bridge
133  *	port attributes
134  *
135  *	@dev: port device
136  *	@nlh: netlink msg with bridge port attributes
137  *	@flags: bridge setlink flags
138  *
139  *	Notify switch device port of bridge port attributes
140  */
netdev_switch_port_bridge_setlink(struct net_device * dev,struct nlmsghdr * nlh,u16 flags)141 int netdev_switch_port_bridge_setlink(struct net_device *dev,
142 				      struct nlmsghdr *nlh, u16 flags)
143 {
144 	const struct net_device_ops *ops = dev->netdev_ops;
145 
146 	if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
147 		return 0;
148 
149 	if (!ops->ndo_bridge_setlink)
150 		return -EOPNOTSUPP;
151 
152 	return ops->ndo_bridge_setlink(dev, nlh, flags);
153 }
154 EXPORT_SYMBOL_GPL(netdev_switch_port_bridge_setlink);
155 
156 /**
157  *	netdev_switch_port_bridge_dellink - Notify switch device port of bridge
158  *	port attribute delete
159  *
160  *	@dev: port device
161  *	@nlh: netlink msg with bridge port attributes
162  *	@flags: bridge setlink flags
163  *
164  *	Notify switch device port of bridge port attribute delete
165  */
netdev_switch_port_bridge_dellink(struct net_device * dev,struct nlmsghdr * nlh,u16 flags)166 int netdev_switch_port_bridge_dellink(struct net_device *dev,
167 				      struct nlmsghdr *nlh, u16 flags)
168 {
169 	const struct net_device_ops *ops = dev->netdev_ops;
170 
171 	if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
172 		return 0;
173 
174 	if (!ops->ndo_bridge_dellink)
175 		return -EOPNOTSUPP;
176 
177 	return ops->ndo_bridge_dellink(dev, nlh, flags);
178 }
179 EXPORT_SYMBOL_GPL(netdev_switch_port_bridge_dellink);
180 
181 /**
182  *	ndo_dflt_netdev_switch_port_bridge_setlink - default ndo bridge setlink
183  *						     op for master devices
184  *
185  *	@dev: port device
186  *	@nlh: netlink msg with bridge port attributes
187  *	@flags: bridge setlink flags
188  *
189  *	Notify master device slaves of bridge port attributes
190  */
ndo_dflt_netdev_switch_port_bridge_setlink(struct net_device * dev,struct nlmsghdr * nlh,u16 flags)191 int ndo_dflt_netdev_switch_port_bridge_setlink(struct net_device *dev,
192 					       struct nlmsghdr *nlh, u16 flags)
193 {
194 	struct net_device *lower_dev;
195 	struct list_head *iter;
196 	int ret = 0, err = 0;
197 
198 	if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
199 		return ret;
200 
201 	netdev_for_each_lower_dev(dev, lower_dev, iter) {
202 		err = netdev_switch_port_bridge_setlink(lower_dev, nlh, flags);
203 		if (err && err != -EOPNOTSUPP)
204 			ret = err;
205 	}
206 
207 	return ret;
208 }
209 EXPORT_SYMBOL_GPL(ndo_dflt_netdev_switch_port_bridge_setlink);
210 
211 /**
212  *	ndo_dflt_netdev_switch_port_bridge_dellink - default ndo bridge dellink
213  *						     op for master devices
214  *
215  *	@dev: port device
216  *	@nlh: netlink msg with bridge port attributes
217  *	@flags: bridge dellink flags
218  *
219  *	Notify master device slaves of bridge port attribute deletes
220  */
ndo_dflt_netdev_switch_port_bridge_dellink(struct net_device * dev,struct nlmsghdr * nlh,u16 flags)221 int ndo_dflt_netdev_switch_port_bridge_dellink(struct net_device *dev,
222 					       struct nlmsghdr *nlh, u16 flags)
223 {
224 	struct net_device *lower_dev;
225 	struct list_head *iter;
226 	int ret = 0, err = 0;
227 
228 	if (!(dev->features & NETIF_F_HW_SWITCH_OFFLOAD))
229 		return ret;
230 
231 	netdev_for_each_lower_dev(dev, lower_dev, iter) {
232 		err = netdev_switch_port_bridge_dellink(lower_dev, nlh, flags);
233 		if (err && err != -EOPNOTSUPP)
234 			ret = err;
235 	}
236 
237 	return ret;
238 }
239 EXPORT_SYMBOL_GPL(ndo_dflt_netdev_switch_port_bridge_dellink);
240 
netdev_switch_get_lowest_dev(struct net_device * dev)241 static struct net_device *netdev_switch_get_lowest_dev(struct net_device *dev)
242 {
243 	const struct swdev_ops *ops = dev->swdev_ops;
244 	struct net_device *lower_dev;
245 	struct net_device *port_dev;
246 	struct list_head *iter;
247 
248 	/* Recusively search down until we find a sw port dev.
249 	 * (A sw port dev supports swdev_parent_id_get).
250 	 */
251 
252 	if (dev->features & NETIF_F_HW_SWITCH_OFFLOAD &&
253 	    ops && ops->swdev_parent_id_get)
254 		return dev;
255 
256 	netdev_for_each_lower_dev(dev, lower_dev, iter) {
257 		port_dev = netdev_switch_get_lowest_dev(lower_dev);
258 		if (port_dev)
259 			return port_dev;
260 	}
261 
262 	return NULL;
263 }
264 
netdev_switch_get_dev_by_nhs(struct fib_info * fi)265 static struct net_device *netdev_switch_get_dev_by_nhs(struct fib_info *fi)
266 {
267 	struct netdev_phys_item_id psid;
268 	struct netdev_phys_item_id prev_psid;
269 	struct net_device *dev = NULL;
270 	int nhsel;
271 
272 	/* For this route, all nexthop devs must be on the same switch. */
273 
274 	for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
275 		const struct fib_nh *nh = &fi->fib_nh[nhsel];
276 
277 		if (!nh->nh_dev)
278 			return NULL;
279 
280 		dev = netdev_switch_get_lowest_dev(nh->nh_dev);
281 		if (!dev)
282 			return NULL;
283 
284 		if (netdev_switch_parent_id_get(dev, &psid))
285 			return NULL;
286 
287 		if (nhsel > 0) {
288 			if (prev_psid.id_len != psid.id_len)
289 				return NULL;
290 			if (memcmp(prev_psid.id, psid.id, psid.id_len))
291 				return NULL;
292 		}
293 
294 		prev_psid = psid;
295 	}
296 
297 	return dev;
298 }
299 
300 /**
301  *	netdev_switch_fib_ipv4_add - Add IPv4 route entry to switch
302  *
303  *	@dst: route's IPv4 destination address
304  *	@dst_len: destination address length (prefix length)
305  *	@fi: route FIB info structure
306  *	@tos: route TOS
307  *	@type: route type
308  *	@nlflags: netlink flags passed in (NLM_F_*)
309  *	@tb_id: route table ID
310  *
311  *	Add IPv4 route entry to switch device.
312  */
netdev_switch_fib_ipv4_add(u32 dst,int dst_len,struct fib_info * fi,u8 tos,u8 type,u32 nlflags,u32 tb_id)313 int netdev_switch_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
314 			       u8 tos, u8 type, u32 nlflags, u32 tb_id)
315 {
316 	struct net_device *dev;
317 	const struct swdev_ops *ops;
318 	int err = 0;
319 
320 	/* Don't offload route if using custom ip rules or if
321 	 * IPv4 FIB offloading has been disabled completely.
322 	 */
323 
324 #ifdef CONFIG_IP_MULTIPLE_TABLES
325 	if (fi->fib_net->ipv4.fib_has_custom_rules)
326 		return 0;
327 #endif
328 
329 	if (fi->fib_net->ipv4.fib_offload_disabled)
330 		return 0;
331 
332 	dev = netdev_switch_get_dev_by_nhs(fi);
333 	if (!dev)
334 		return 0;
335 	ops = dev->swdev_ops;
336 
337 	if (ops->swdev_fib_ipv4_add) {
338 		err = ops->swdev_fib_ipv4_add(dev, htonl(dst), dst_len,
339 					      fi, tos, type, nlflags,
340 					      tb_id);
341 		if (!err)
342 			fi->fib_flags |= RTNH_F_OFFLOAD;
343 	}
344 
345 	return err;
346 }
347 EXPORT_SYMBOL_GPL(netdev_switch_fib_ipv4_add);
348 
349 /**
350  *	netdev_switch_fib_ipv4_del - Delete IPv4 route entry from switch
351  *
352  *	@dst: route's IPv4 destination address
353  *	@dst_len: destination address length (prefix length)
354  *	@fi: route FIB info structure
355  *	@tos: route TOS
356  *	@type: route type
357  *	@tb_id: route table ID
358  *
359  *	Delete IPv4 route entry from switch device.
360  */
netdev_switch_fib_ipv4_del(u32 dst,int dst_len,struct fib_info * fi,u8 tos,u8 type,u32 tb_id)361 int netdev_switch_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
362 			       u8 tos, u8 type, u32 tb_id)
363 {
364 	struct net_device *dev;
365 	const struct swdev_ops *ops;
366 	int err = 0;
367 
368 	if (!(fi->fib_flags & RTNH_F_OFFLOAD))
369 		return 0;
370 
371 	dev = netdev_switch_get_dev_by_nhs(fi);
372 	if (!dev)
373 		return 0;
374 	ops = dev->swdev_ops;
375 
376 	if (ops->swdev_fib_ipv4_del) {
377 		err = ops->swdev_fib_ipv4_del(dev, htonl(dst), dst_len,
378 					      fi, tos, type, tb_id);
379 		if (!err)
380 			fi->fib_flags &= ~RTNH_F_OFFLOAD;
381 	}
382 
383 	return err;
384 }
385 EXPORT_SYMBOL_GPL(netdev_switch_fib_ipv4_del);
386 
387 /**
388  *	netdev_switch_fib_ipv4_abort - Abort an IPv4 FIB operation
389  *
390  *	@fi: route FIB info structure
391  */
netdev_switch_fib_ipv4_abort(struct fib_info * fi)392 void netdev_switch_fib_ipv4_abort(struct fib_info *fi)
393 {
394 	/* There was a problem installing this route to the offload
395 	 * device.  For now, until we come up with more refined
396 	 * policy handling, abruptly end IPv4 fib offloading for
397 	 * for entire net by flushing offload device(s) of all
398 	 * IPv4 routes, and mark IPv4 fib offloading broken from
399 	 * this point forward.
400 	 */
401 
402 	fib_flush_external(fi->fib_net);
403 	fi->fib_net->ipv4.fib_offload_disabled = true;
404 }
405 EXPORT_SYMBOL_GPL(netdev_switch_fib_ipv4_abort);
406