Merge tag 'mm-hotfixes-stable-2025-07-11-16-16' of git://git.kernel.org/pub/scm/linux...
[linux-block.git] / net / switchdev / switchdev.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
007f790c
JP
2/*
3 * net/switchdev/switchdev.c - Switch device API
7ea6eb3f 4 * Copyright (c) 2014-2015 Jiri Pirko <jiri@resnulli.us>
f8f21471 5 * Copyright (c) 2014-2015 Scott Feldman <sfeldma@gmail.com>
007f790c
JP
6 */
7
8#include <linux/kernel.h>
9#include <linux/types.h>
10#include <linux/init.h>
03bf0c28
JP
11#include <linux/mutex.h>
12#include <linux/notifier.h>
007f790c 13#include <linux/netdevice.h>
850d0cbc 14#include <linux/etherdevice.h>
47f8328b 15#include <linux/if_bridge.h>
7ea6eb3f 16#include <linux/list.h>
793f4014 17#include <linux/workqueue.h>
87aaf2ca 18#include <linux/if_vlan.h>
4f2c6ae5 19#include <linux/rtnetlink.h>
007f790c
JP
20#include <net/switchdev.h>
21
dc489f86
TW
22static bool switchdev_obj_eq(const struct switchdev_obj *a,
23 const struct switchdev_obj *b)
24{
25 const struct switchdev_obj_port_vlan *va, *vb;
26 const struct switchdev_obj_port_mdb *ma, *mb;
27
28 if (a->id != b->id || a->orig_dev != b->orig_dev)
29 return false;
30
31 switch (a->id) {
32 case SWITCHDEV_OBJ_ID_PORT_VLAN:
33 va = SWITCHDEV_OBJ_PORT_VLAN(a);
34 vb = SWITCHDEV_OBJ_PORT_VLAN(b);
35 return va->flags == vb->flags &&
36 va->vid == vb->vid &&
37 va->changed == vb->changed;
38 case SWITCHDEV_OBJ_ID_PORT_MDB:
39 case SWITCHDEV_OBJ_ID_HOST_MDB:
40 ma = SWITCHDEV_OBJ_PORT_MDB(a);
41 mb = SWITCHDEV_OBJ_PORT_MDB(b);
42 return ma->vid == mb->vid &&
43 ether_addr_equal(ma->addr, mb->addr);
44 default:
45 break;
46 }
47
48 BUG();
49}
50
793f4014
JP
51static LIST_HEAD(deferred);
52static DEFINE_SPINLOCK(deferred_lock);
53
54typedef void switchdev_deferred_func_t(struct net_device *dev,
55 const void *data);
56
57struct switchdev_deferred_item {
58 struct list_head list;
59 struct net_device *dev;
4fc003fe 60 netdevice_tracker dev_tracker;
793f4014 61 switchdev_deferred_func_t *func;
fbfc8502 62 unsigned long data[];
793f4014
JP
63};
64
65static struct switchdev_deferred_item *switchdev_deferred_dequeue(void)
66{
67 struct switchdev_deferred_item *dfitem;
68
69 spin_lock_bh(&deferred_lock);
70 if (list_empty(&deferred)) {
71 dfitem = NULL;
72 goto unlock;
73 }
74 dfitem = list_first_entry(&deferred,
75 struct switchdev_deferred_item, list);
76 list_del(&dfitem->list);
77unlock:
78 spin_unlock_bh(&deferred_lock);
79 return dfitem;
80}
81
82/**
83 * switchdev_deferred_process - Process ops in deferred queue
84 *
85 * Called to flush the ops currently queued in deferred ops queue.
86 * rtnl_lock must be held.
87 */
88void switchdev_deferred_process(void)
89{
90 struct switchdev_deferred_item *dfitem;
91
92 ASSERT_RTNL();
93
94 while ((dfitem = switchdev_deferred_dequeue())) {
95 dfitem->func(dfitem->dev, dfitem->data);
d62607c3 96 netdev_put(dfitem->dev, &dfitem->dev_tracker);
793f4014
JP
97 kfree(dfitem);
98 }
99}
100EXPORT_SYMBOL_GPL(switchdev_deferred_process);
101
102static void switchdev_deferred_process_work(struct work_struct *work)
103{
104 rtnl_lock();
105 switchdev_deferred_process();
106 rtnl_unlock();
107}
108
109static DECLARE_WORK(deferred_process_work, switchdev_deferred_process_work);
110
111static int switchdev_deferred_enqueue(struct net_device *dev,
112 const void *data, size_t data_len,
113 switchdev_deferred_func_t *func)
114{
115 struct switchdev_deferred_item *dfitem;
116
d8c28581 117 dfitem = kmalloc(struct_size(dfitem, data, data_len), GFP_ATOMIC);
793f4014
JP
118 if (!dfitem)
119 return -ENOMEM;
120 dfitem->dev = dev;
121 dfitem->func = func;
122 memcpy(dfitem->data, data, data_len);
d62607c3 123 netdev_hold(dev, &dfitem->dev_tracker, GFP_ATOMIC);
793f4014
JP
124 spin_lock_bh(&deferred_lock);
125 list_add_tail(&dfitem->list, &deferred);
126 spin_unlock_bh(&deferred_lock);
127 schedule_work(&deferred_process_work);
128 return 0;
129}
130
d45224d6
FF
131static int switchdev_port_attr_notify(enum switchdev_notifier_type nt,
132 struct net_device *dev,
dcbdf135
VO
133 const struct switchdev_attr *attr,
134 struct netlink_ext_ack *extack)
3094333d 135{
d45224d6
FF
136 int err;
137 int rc;
3094333d 138
d45224d6
FF
139 struct switchdev_notifier_port_attr_info attr_info = {
140 .attr = attr,
d45224d6
FF
141 .handled = false,
142 };
3094333d 143
d45224d6 144 rc = call_switchdev_blocking_notifiers(nt, dev,
dcbdf135 145 &attr_info.info, extack);
d45224d6
FF
146 err = notifier_to_errno(rc);
147 if (err) {
148 WARN_ON(!attr_info.handled);
149 return err;
3094333d
SF
150 }
151
d45224d6
FF
152 if (!attr_info.handled)
153 return -EOPNOTSUPP;
464314ea 154
d45224d6 155 return 0;
3094333d
SF
156}
157
0bc05d58 158static int switchdev_port_attr_set_now(struct net_device *dev,
dcbdf135
VO
159 const struct switchdev_attr *attr,
160 struct netlink_ext_ack *extack)
3094333d 161{
dcbdf135
VO
162 return switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr,
163 extack);
3094333d 164}
0bc05d58
JP
165
166static void switchdev_port_attr_set_deferred(struct net_device *dev,
167 const void *data)
168{
169 const struct switchdev_attr *attr = data;
170 int err;
171
dcbdf135 172 err = switchdev_port_attr_set_now(dev, attr, NULL);
0bc05d58
JP
173 if (err && err != -EOPNOTSUPP)
174 netdev_err(dev, "failed (err=%d) to set attribute (id=%d)\n",
175 err, attr->id);
7ceb2afb
ER
176 if (attr->complete)
177 attr->complete(dev, err, attr->complete_priv);
0bc05d58
JP
178}
179
180static int switchdev_port_attr_set_defer(struct net_device *dev,
181 const struct switchdev_attr *attr)
182{
183 return switchdev_deferred_enqueue(dev, attr, sizeof(*attr),
184 switchdev_port_attr_set_deferred);
185}
186
187/**
188 * switchdev_port_attr_set - Set port attribute
189 *
190 * @dev: port device
191 * @attr: attribute to set
dcbdf135 192 * @extack: netlink extended ack, for error message propagation
0bc05d58 193 *
0bc05d58
JP
194 * rtnl_lock must be held and must not be in atomic section,
195 * in case SWITCHDEV_F_DEFER flag is not set.
196 */
197int switchdev_port_attr_set(struct net_device *dev,
dcbdf135
VO
198 const struct switchdev_attr *attr,
199 struct netlink_ext_ack *extack)
0bc05d58
JP
200{
201 if (attr->flags & SWITCHDEV_F_DEFER)
202 return switchdev_port_attr_set_defer(dev, attr);
203 ASSERT_RTNL();
dcbdf135 204 return switchdev_port_attr_set_now(dev, attr, extack);
0bc05d58 205}
3094333d
SF
206EXPORT_SYMBOL_GPL(switchdev_port_attr_set);
207
e258d919
SF
208static size_t switchdev_obj_size(const struct switchdev_obj *obj)
209{
210 switch (obj->id) {
211 case SWITCHDEV_OBJ_ID_PORT_VLAN:
212 return sizeof(struct switchdev_obj_port_vlan);
4d41e125
ER
213 case SWITCHDEV_OBJ_ID_PORT_MDB:
214 return sizeof(struct switchdev_obj_port_mdb);
47d5b6db
AL
215 case SWITCHDEV_OBJ_ID_HOST_MDB:
216 return sizeof(struct switchdev_obj_port_mdb);
e258d919
SF
217 default:
218 BUG();
219 }
220 return 0;
221}
222
d17d9f5e
PM
223static int switchdev_port_obj_notify(enum switchdev_notifier_type nt,
224 struct net_device *dev,
225 const struct switchdev_obj *obj,
69b7320e 226 struct netlink_ext_ack *extack)
491d0f15 227{
d17d9f5e
PM
228 int rc;
229 int err;
491d0f15 230
d17d9f5e
PM
231 struct switchdev_notifier_port_obj_info obj_info = {
232 .obj = obj,
d17d9f5e
PM
233 .handled = false,
234 };
491d0f15 235
479c86dc 236 rc = call_switchdev_blocking_notifiers(nt, dev, &obj_info.info, extack);
d17d9f5e
PM
237 err = notifier_to_errno(rc);
238 if (err) {
239 WARN_ON(!obj_info.handled);
240 return err;
491d0f15 241 }
d17d9f5e
PM
242 if (!obj_info.handled)
243 return -EOPNOTSUPP;
244 return 0;
491d0f15
SF
245}
246
b7ffab29
OR
247static void switchdev_obj_id_to_helpful_msg(struct net_device *dev,
248 enum switchdev_obj_id obj_id,
249 int err, bool add)
250{
251 const char *action = add ? "add" : "del";
252 const char *reason = "";
253 const char *problem;
254 const char *obj_str;
255
256 switch (obj_id) {
257 case SWITCHDEV_OBJ_ID_UNDEFINED:
258 obj_str = "Undefined object";
259 problem = "Attempted operation is undefined, indicating a possible programming\n"
260 "error.\n";
261 break;
262 case SWITCHDEV_OBJ_ID_PORT_VLAN:
263 obj_str = "VLAN entry";
264 problem = "Failure in VLAN settings on this port might disrupt network\n"
265 "segmentation or traffic isolation, affecting network partitioning.\n";
266 break;
267 case SWITCHDEV_OBJ_ID_PORT_MDB:
268 obj_str = "Port Multicast Database entry";
269 problem = "Failure in updating the port's Multicast Database could lead to\n"
270 "multicast forwarding issues.\n";
271 break;
272 case SWITCHDEV_OBJ_ID_HOST_MDB:
273 obj_str = "Host Multicast Database entry";
274 problem = "Failure in updating the host's Multicast Database may impact multicast\n"
275 "group memberships or traffic delivery, affecting multicast\n"
276 "communication.\n";
277 break;
278 case SWITCHDEV_OBJ_ID_MRP:
279 obj_str = "Media Redundancy Protocol configuration for port";
280 problem = "Failure to set MRP ring ID on this port prevents communication with\n"
281 "the specified redundancy ring, resulting in an inability to engage\n"
282 "in MRP-based network operations.\n";
283 break;
284 case SWITCHDEV_OBJ_ID_RING_TEST_MRP:
285 obj_str = "MRP Test Frame Operations for port";
286 problem = "Failure to generate/monitor MRP test frames may lead to inability to\n"
287 "assess the ring's operational integrity and fault response, hindering\n"
288 "proactive network management.\n";
289 break;
290 case SWITCHDEV_OBJ_ID_RING_ROLE_MRP:
291 obj_str = "MRP Ring Role Configuration";
292 problem = "Improper MRP ring role configuration may create conflicts in the ring,\n"
293 "disrupting communication for all participants, or isolate the local\n"
294 "system from the ring, hindering its ability to communicate with other\n"
295 "participants.\n";
296 break;
297 case SWITCHDEV_OBJ_ID_RING_STATE_MRP:
298 obj_str = "MRP Ring State Configuration";
299 problem = "Failure to correctly set the MRP ring state can result in network\n"
300 "loops or leave segments without communication. In a Closed state,\n"
301 "it maintains loop prevention by blocking one MRM port, while an Open\n"
302 "state activates in response to failures, changing port states to\n"
303 "preserve network connectivity.\n";
304 break;
305 case SWITCHDEV_OBJ_ID_IN_TEST_MRP:
306 obj_str = "MRP_InTest Frame Generation Configuration";
307 problem = "Failure in managing MRP_InTest frame generation can misjudge the\n"
308 "interconnection ring's state, leading to incorrect blocking or\n"
309 "unblocking of the I/C port. This misconfiguration might result\n"
310 "in unintended network loops or isolate critical network segments,\n"
311 "compromising network integrity and reliability.\n";
312 break;
313 case SWITCHDEV_OBJ_ID_IN_ROLE_MRP:
314 obj_str = "Interconnection Ring Role Configuration";
315 problem = "Failure in incorrect assignment of interconnection ring roles\n"
316 "(MIM/MIC) can impair the formation of the interconnection rings.\n";
317 break;
318 case SWITCHDEV_OBJ_ID_IN_STATE_MRP:
319 obj_str = "Interconnection Ring State Configuration";
320 problem = "Failure in updating the interconnection ring state can lead in\n"
321 "case of Open state to incorrect blocking or unblocking of the\n"
322 "I/C port, resulting in unintended network loops or isolation\n"
323 "of critical network\n";
324 break;
325 default:
326 obj_str = "Unknown object";
327 problem = "Indicating a possible programming error.\n";
328 }
329
330 switch (err) {
331 case -ENOSPC:
332 reason = "Current HW/SW setup lacks sufficient resources.\n";
333 break;
334 }
335
336 netdev_err(dev, "Failed to %s %s (object id=%d) with error: %pe (%d).\n%s%s\n",
337 action, obj_str, obj_id, ERR_PTR(err), err, problem, reason);
338}
339
4d429c5d
JP
340static void switchdev_port_obj_add_deferred(struct net_device *dev,
341 const void *data)
342{
343 const struct switchdev_obj *obj = data;
344 int err;
345
cf6def51
VO
346 ASSERT_RTNL();
347 err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD,
348 dev, obj, NULL);
4d429c5d 349 if (err && err != -EOPNOTSUPP)
b7ffab29 350 switchdev_obj_id_to_helpful_msg(dev, obj->id, err, true);
7ceb2afb
ER
351 if (obj->complete)
352 obj->complete(dev, err, obj->complete_priv);
4d429c5d
JP
353}
354
355static int switchdev_port_obj_add_defer(struct net_device *dev,
356 const struct switchdev_obj *obj)
357{
e258d919 358 return switchdev_deferred_enqueue(dev, obj, switchdev_obj_size(obj),
4d429c5d
JP
359 switchdev_port_obj_add_deferred);
360}
491d0f15
SF
361
362/**
4d429c5d 363 * switchdev_port_obj_add - Add port object
491d0f15
SF
364 *
365 * @dev: port device
4d429c5d 366 * @obj: object to add
c8af73f0 367 * @extack: netlink extended ack
4d429c5d 368 *
4d429c5d
JP
369 * rtnl_lock must be held and must not be in atomic section,
370 * in case SWITCHDEV_F_DEFER flag is not set.
491d0f15 371 */
4d429c5d 372int switchdev_port_obj_add(struct net_device *dev,
69b7320e
PM
373 const struct switchdev_obj *obj,
374 struct netlink_ext_ack *extack)
4d429c5d
JP
375{
376 if (obj->flags & SWITCHDEV_F_DEFER)
377 return switchdev_port_obj_add_defer(dev, obj);
378 ASSERT_RTNL();
cf6def51
VO
379 return switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD,
380 dev, obj, extack);
4d429c5d
JP
381}
382EXPORT_SYMBOL_GPL(switchdev_port_obj_add);
383
384static int switchdev_port_obj_del_now(struct net_device *dev,
385 const struct switchdev_obj *obj)
491d0f15 386{
d17d9f5e 387 return switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_DEL,
ffb68fc5 388 dev, obj, NULL);
491d0f15 389}
4d429c5d
JP
390
391static void switchdev_port_obj_del_deferred(struct net_device *dev,
392 const void *data)
393{
394 const struct switchdev_obj *obj = data;
395 int err;
396
397 err = switchdev_port_obj_del_now(dev, obj);
398 if (err && err != -EOPNOTSUPP)
b7ffab29 399 switchdev_obj_id_to_helpful_msg(dev, obj->id, err, false);
7ceb2afb
ER
400 if (obj->complete)
401 obj->complete(dev, err, obj->complete_priv);
4d429c5d
JP
402}
403
404static int switchdev_port_obj_del_defer(struct net_device *dev,
405 const struct switchdev_obj *obj)
406{
e258d919 407 return switchdev_deferred_enqueue(dev, obj, switchdev_obj_size(obj),
4d429c5d
JP
408 switchdev_port_obj_del_deferred);
409}
410
411/**
412 * switchdev_port_obj_del - Delete port object
413 *
414 * @dev: port device
4d429c5d
JP
415 * @obj: object to delete
416 *
417 * rtnl_lock must be held and must not be in atomic section,
418 * in case SWITCHDEV_F_DEFER flag is not set.
419 */
420int switchdev_port_obj_del(struct net_device *dev,
421 const struct switchdev_obj *obj)
422{
423 if (obj->flags & SWITCHDEV_F_DEFER)
424 return switchdev_port_obj_del_defer(dev, obj);
425 ASSERT_RTNL();
426 return switchdev_port_obj_del_now(dev, obj);
427}
491d0f15
SF
428EXPORT_SYMBOL_GPL(switchdev_port_obj_del);
429
dc489f86
TW
430/**
431 * switchdev_port_obj_act_is_deferred - Is object action pending?
432 *
433 * @dev: port device
434 * @nt: type of action; add or delete
435 * @obj: object to test
436 *
437 * Returns true if a deferred item is pending, which is
438 * equivalent to the action @nt on an object @obj.
439 *
440 * rtnl_lock must be held.
441 */
442bool switchdev_port_obj_act_is_deferred(struct net_device *dev,
443 enum switchdev_notifier_type nt,
444 const struct switchdev_obj *obj)
445{
446 struct switchdev_deferred_item *dfitem;
447 bool found = false;
448
449 ASSERT_RTNL();
450
451 spin_lock_bh(&deferred_lock);
452
453 list_for_each_entry(dfitem, &deferred, list) {
454 if (dfitem->dev != dev)
455 continue;
456
457 if ((dfitem->func == switchdev_port_obj_add_deferred &&
458 nt == SWITCHDEV_PORT_OBJ_ADD) ||
459 (dfitem->func == switchdev_port_obj_del_deferred &&
460 nt == SWITCHDEV_PORT_OBJ_DEL)) {
461 if (switchdev_obj_eq((const void *)dfitem->data, obj)) {
462 found = true;
463 break;
464 }
465 }
466 }
467
468 spin_unlock_bh(&deferred_lock);
469
470 return found;
471}
472EXPORT_SYMBOL_GPL(switchdev_port_obj_act_is_deferred);
473
ff5cf100 474static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain);
62531a1e 475static RAW_NOTIFIER_HEAD(switchdev_blocking_notif_chain);
03bf0c28
JP
476
477/**
ebb9a03a 478 * register_switchdev_notifier - Register notifier
03bf0c28
JP
479 * @nb: notifier_block
480 *
ff5cf100 481 * Register switch device notifier.
03bf0c28 482 */
ebb9a03a 483int register_switchdev_notifier(struct notifier_block *nb)
03bf0c28 484{
ff5cf100 485 return atomic_notifier_chain_register(&switchdev_notif_chain, nb);
03bf0c28 486}
ebb9a03a 487EXPORT_SYMBOL_GPL(register_switchdev_notifier);
03bf0c28
JP
488
489/**
ebb9a03a 490 * unregister_switchdev_notifier - Unregister notifier
03bf0c28
JP
491 * @nb: notifier_block
492 *
493 * Unregister switch device notifier.
03bf0c28 494 */
ebb9a03a 495int unregister_switchdev_notifier(struct notifier_block *nb)
03bf0c28 496{
ff5cf100 497 return atomic_notifier_chain_unregister(&switchdev_notif_chain, nb);
03bf0c28 498}
ebb9a03a 499EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
03bf0c28
JP
500
501/**
ebb9a03a 502 * call_switchdev_notifiers - Call notifiers
03bf0c28
JP
503 * @val: value passed unmodified to notifier function
504 * @dev: port device
505 * @info: notifier information data
ea6754ae 506 * @extack: netlink extended ack
ff5cf100 507 * Call all network notifier blocks.
03bf0c28 508 */
ebb9a03a 509int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
6685987c
PM
510 struct switchdev_notifier_info *info,
511 struct netlink_ext_ack *extack)
03bf0c28 512{
03bf0c28 513 info->dev = dev;
6685987c 514 info->extack = extack;
ff5cf100 515 return atomic_notifier_call_chain(&switchdev_notif_chain, val, info);
03bf0c28 516}
ebb9a03a 517EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
8a44dbb2 518
a93e3b17
PM
519int register_switchdev_blocking_notifier(struct notifier_block *nb)
520{
62531a1e
AC
521 struct raw_notifier_head *chain = &switchdev_blocking_notif_chain;
522 int err;
a93e3b17 523
62531a1e
AC
524 rtnl_lock();
525 err = raw_notifier_chain_register(chain, nb);
526 rtnl_unlock();
527
528 return err;
a93e3b17
PM
529}
530EXPORT_SYMBOL_GPL(register_switchdev_blocking_notifier);
531
532int unregister_switchdev_blocking_notifier(struct notifier_block *nb)
533{
62531a1e
AC
534 struct raw_notifier_head *chain = &switchdev_blocking_notif_chain;
535 int err;
a93e3b17 536
62531a1e
AC
537 rtnl_lock();
538 err = raw_notifier_chain_unregister(chain, nb);
539 rtnl_unlock();
540
541 return err;
a93e3b17
PM
542}
543EXPORT_SYMBOL_GPL(unregister_switchdev_blocking_notifier);
544
545int call_switchdev_blocking_notifiers(unsigned long val, struct net_device *dev,
479c86dc
PM
546 struct switchdev_notifier_info *info,
547 struct netlink_ext_ack *extack)
a93e3b17 548{
62531a1e 549 ASSERT_RTNL();
a93e3b17 550 info->dev = dev;
479c86dc 551 info->extack = extack;
62531a1e
AC
552 return raw_notifier_call_chain(&switchdev_blocking_notif_chain,
553 val, info);
a93e3b17
PM
554}
555EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers);
556
2b0a5688
VO
557struct switchdev_nested_priv {
558 bool (*check_cb)(const struct net_device *dev);
559 bool (*foreign_dev_check_cb)(const struct net_device *dev,
560 const struct net_device *foreign_dev);
561 const struct net_device *dev;
562 struct net_device *lower_dev;
563};
564
565static int switchdev_lower_dev_walk(struct net_device *lower_dev,
566 struct netdev_nested_priv *priv)
567{
568 struct switchdev_nested_priv *switchdev_priv = priv->data;
569 bool (*foreign_dev_check_cb)(const struct net_device *dev,
570 const struct net_device *foreign_dev);
571 bool (*check_cb)(const struct net_device *dev);
572 const struct net_device *dev;
573
574 check_cb = switchdev_priv->check_cb;
575 foreign_dev_check_cb = switchdev_priv->foreign_dev_check_cb;
576 dev = switchdev_priv->dev;
577
578 if (check_cb(lower_dev) && !foreign_dev_check_cb(lower_dev, dev)) {
579 switchdev_priv->lower_dev = lower_dev;
580 return 1;
581 }
582
583 return 0;
584}
585
586static struct net_device *
7b465f4c
VO
587switchdev_lower_dev_find_rcu(struct net_device *dev,
588 bool (*check_cb)(const struct net_device *dev),
589 bool (*foreign_dev_check_cb)(const struct net_device *dev,
590 const struct net_device *foreign_dev))
2b0a5688
VO
591{
592 struct switchdev_nested_priv switchdev_priv = {
593 .check_cb = check_cb,
594 .foreign_dev_check_cb = foreign_dev_check_cb,
595 .dev = dev,
596 .lower_dev = NULL,
597 };
598 struct netdev_nested_priv priv = {
599 .data = &switchdev_priv,
600 };
601
602 netdev_walk_all_lower_dev_rcu(dev, switchdev_lower_dev_walk, &priv);
603
604 return switchdev_priv.lower_dev;
605}
606
c4076cdd
VO
607static struct net_device *
608switchdev_lower_dev_find(struct net_device *dev,
609 bool (*check_cb)(const struct net_device *dev),
610 bool (*foreign_dev_check_cb)(const struct net_device *dev,
611 const struct net_device *foreign_dev))
612{
613 struct switchdev_nested_priv switchdev_priv = {
614 .check_cb = check_cb,
615 .foreign_dev_check_cb = foreign_dev_check_cb,
616 .dev = dev,
617 .lower_dev = NULL,
618 };
619 struct netdev_nested_priv priv = {
620 .data = &switchdev_priv,
621 };
622
623 netdev_walk_all_lower_dev(dev, switchdev_lower_dev_walk, &priv);
624
625 return switchdev_priv.lower_dev;
626}
627
716a30a9
VO
628static int __switchdev_handle_fdb_event_to_device(struct net_device *dev,
629 struct net_device *orig_dev, unsigned long event,
8ca07176
VO
630 const struct switchdev_notifier_fdb_info *fdb_info,
631 bool (*check_cb)(const struct net_device *dev),
632 bool (*foreign_dev_check_cb)(const struct net_device *dev,
633 const struct net_device *foreign_dev),
716a30a9
VO
634 int (*mod_cb)(struct net_device *dev, struct net_device *orig_dev,
635 unsigned long event, const void *ctx,
ec638740 636 const struct switchdev_notifier_fdb_info *fdb_info))
8ca07176
VO
637{
638 const struct switchdev_notifier_info *info = &fdb_info->info;
ec638740 639 struct net_device *br, *lower_dev, *switchdev;
8ca07176
VO
640 struct list_head *iter;
641 int err = -EOPNOTSUPP;
642
2b0a5688 643 if (check_cb(dev))
716a30a9 644 return mod_cb(dev, orig_dev, event, info->ctx, fdb_info);
8ca07176 645
8ca07176 646 /* Recurse through lower interfaces in case the FDB entry is pointing
ec638740 647 * towards a bridge or a LAG device.
8ca07176 648 */
ec638740
VO
649 netdev_for_each_lower_dev(dev, lower_dev, iter) {
650 /* Do not propagate FDB entries across bridges */
651 if (netif_is_bridge_master(lower_dev))
652 continue;
653
654 /* Bridge ports might be either us, or LAG interfaces
655 * that we offload.
656 */
657 if (!check_cb(lower_dev) &&
658 !switchdev_lower_dev_find_rcu(lower_dev, check_cb,
659 foreign_dev_check_cb))
660 continue;
661
662 err = __switchdev_handle_fdb_event_to_device(lower_dev, orig_dev,
663 event, fdb_info, check_cb,
664 foreign_dev_check_cb,
665 mod_cb);
666 if (err && err != -EOPNOTSUPP)
667 return err;
8ca07176
VO
668 }
669
2b0a5688
VO
670 /* Event is neither on a bridge nor a LAG. Check whether it is on an
671 * interface that is in a bridge with us.
672 */
673 br = netdev_master_upper_dev_get_rcu(dev);
674 if (!br || !netif_is_bridge_master(br))
675 return 0;
676
ec638740
VO
677 switchdev = switchdev_lower_dev_find_rcu(br, check_cb, foreign_dev_check_cb);
678 if (!switchdev)
2b0a5688
VO
679 return 0;
680
ec638740
VO
681 if (!foreign_dev_check_cb(switchdev, dev))
682 return err;
683
716a30a9
VO
684 return __switchdev_handle_fdb_event_to_device(br, orig_dev, event, fdb_info,
685 check_cb, foreign_dev_check_cb,
ec638740 686 mod_cb);
8ca07176
VO
687}
688
716a30a9 689int switchdev_handle_fdb_event_to_device(struct net_device *dev, unsigned long event,
8ca07176
VO
690 const struct switchdev_notifier_fdb_info *fdb_info,
691 bool (*check_cb)(const struct net_device *dev),
692 bool (*foreign_dev_check_cb)(const struct net_device *dev,
693 const struct net_device *foreign_dev),
716a30a9
VO
694 int (*mod_cb)(struct net_device *dev, struct net_device *orig_dev,
695 unsigned long event, const void *ctx,
ec638740 696 const struct switchdev_notifier_fdb_info *fdb_info))
8ca07176
VO
697{
698 int err;
699
716a30a9
VO
700 err = __switchdev_handle_fdb_event_to_device(dev, dev, event, fdb_info,
701 check_cb, foreign_dev_check_cb,
ec638740 702 mod_cb);
8ca07176
VO
703 if (err == -EOPNOTSUPP)
704 err = 0;
705
706 return err;
707}
716a30a9 708EXPORT_SYMBOL_GPL(switchdev_handle_fdb_event_to_device);
8ca07176 709
f30f0601
PM
710static int __switchdev_handle_port_obj_add(struct net_device *dev,
711 struct switchdev_notifier_port_obj_info *port_obj_info,
712 bool (*check_cb)(const struct net_device *dev),
c4076cdd
VO
713 bool (*foreign_dev_check_cb)(const struct net_device *dev,
714 const struct net_device *foreign_dev),
69bfac96 715 int (*add_cb)(struct net_device *dev, const void *ctx,
f30f0601 716 const struct switchdev_obj *obj,
69213513 717 struct netlink_ext_ack *extack))
f30f0601 718{
69bfac96 719 struct switchdev_notifier_info *info = &port_obj_info->info;
acd8df58 720 struct net_device *br, *lower_dev, *switchdev;
69213513 721 struct netlink_ext_ack *extack;
f30f0601
PM
722 struct list_head *iter;
723 int err = -EOPNOTSUPP;
724
69bfac96 725 extack = switchdev_notifier_info_to_extack(info);
69213513 726
f30f0601 727 if (check_cb(dev)) {
69bfac96 728 err = add_cb(dev, info->ctx, port_obj_info->obj, extack);
20776b46
RV
729 if (err != -EOPNOTSUPP)
730 port_obj_info->handled = true;
731 return err;
f30f0601
PM
732 }
733
734 /* Switch ports might be stacked under e.g. a LAG. Ignore the
735 * unsupported devices, another driver might be able to handle them. But
736 * propagate to the callers any hard errors.
737 *
738 * If the driver does its own bookkeeping of stacked ports, it's not
739 * necessary to go through this helper.
740 */
741 netdev_for_each_lower_dev(dev, lower_dev, iter) {
07c6f980
RK
742 if (netif_is_bridge_master(lower_dev))
743 continue;
744
c4076cdd
VO
745 /* When searching for switchdev interfaces that are neighbors
746 * of foreign ones, and @dev is a bridge, do not recurse on the
747 * foreign interface again, it was already visited.
748 */
749 if (foreign_dev_check_cb && !check_cb(lower_dev) &&
750 !switchdev_lower_dev_find(lower_dev, check_cb, foreign_dev_check_cb))
751 continue;
752
f30f0601 753 err = __switchdev_handle_port_obj_add(lower_dev, port_obj_info,
c4076cdd
VO
754 check_cb, foreign_dev_check_cb,
755 add_cb);
f30f0601
PM
756 if (err && err != -EOPNOTSUPP)
757 return err;
758 }
759
c4076cdd
VO
760 /* Event is neither on a bridge nor a LAG. Check whether it is on an
761 * interface that is in a bridge with us.
762 */
763 if (!foreign_dev_check_cb)
764 return err;
765
766 br = netdev_master_upper_dev_get(dev);
767 if (!br || !netif_is_bridge_master(br))
768 return err;
769
acd8df58
VO
770 switchdev = switchdev_lower_dev_find(br, check_cb, foreign_dev_check_cb);
771 if (!switchdev)
772 return err;
773
774 if (!foreign_dev_check_cb(switchdev, dev))
c4076cdd
VO
775 return err;
776
777 return __switchdev_handle_port_obj_add(br, port_obj_info, check_cb,
778 foreign_dev_check_cb, add_cb);
f30f0601
PM
779}
780
c4076cdd
VO
781/* Pass through a port object addition, if @dev passes @check_cb, or replicate
782 * it towards all lower interfaces of @dev that pass @check_cb, if @dev is a
783 * bridge or a LAG.
784 */
f30f0601
PM
785int switchdev_handle_port_obj_add(struct net_device *dev,
786 struct switchdev_notifier_port_obj_info *port_obj_info,
787 bool (*check_cb)(const struct net_device *dev),
69bfac96 788 int (*add_cb)(struct net_device *dev, const void *ctx,
f30f0601 789 const struct switchdev_obj *obj,
69213513 790 struct netlink_ext_ack *extack))
f30f0601
PM
791{
792 int err;
793
794 err = __switchdev_handle_port_obj_add(dev, port_obj_info, check_cb,
c4076cdd 795 NULL, add_cb);
f30f0601
PM
796 if (err == -EOPNOTSUPP)
797 err = 0;
798 return err;
799}
800EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_add);
801
c4076cdd
VO
802/* Same as switchdev_handle_port_obj_add(), except if object is notified on a
803 * @dev that passes @foreign_dev_check_cb, it is replicated towards all devices
804 * that pass @check_cb and are in the same bridge as @dev.
805 */
806int switchdev_handle_port_obj_add_foreign(struct net_device *dev,
807 struct switchdev_notifier_port_obj_info *port_obj_info,
808 bool (*check_cb)(const struct net_device *dev),
809 bool (*foreign_dev_check_cb)(const struct net_device *dev,
810 const struct net_device *foreign_dev),
811 int (*add_cb)(struct net_device *dev, const void *ctx,
812 const struct switchdev_obj *obj,
813 struct netlink_ext_ack *extack))
814{
815 int err;
816
817 err = __switchdev_handle_port_obj_add(dev, port_obj_info, check_cb,
818 foreign_dev_check_cb, add_cb);
819 if (err == -EOPNOTSUPP)
820 err = 0;
821 return err;
822}
823EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_add_foreign);
824
f30f0601
PM
825static int __switchdev_handle_port_obj_del(struct net_device *dev,
826 struct switchdev_notifier_port_obj_info *port_obj_info,
827 bool (*check_cb)(const struct net_device *dev),
c4076cdd
VO
828 bool (*foreign_dev_check_cb)(const struct net_device *dev,
829 const struct net_device *foreign_dev),
69bfac96 830 int (*del_cb)(struct net_device *dev, const void *ctx,
f30f0601
PM
831 const struct switchdev_obj *obj))
832{
69bfac96 833 struct switchdev_notifier_info *info = &port_obj_info->info;
acd8df58 834 struct net_device *br, *lower_dev, *switchdev;
f30f0601
PM
835 struct list_head *iter;
836 int err = -EOPNOTSUPP;
837
838 if (check_cb(dev)) {
69bfac96 839 err = del_cb(dev, info->ctx, port_obj_info->obj);
20776b46
RV
840 if (err != -EOPNOTSUPP)
841 port_obj_info->handled = true;
842 return err;
f30f0601
PM
843 }
844
845 /* Switch ports might be stacked under e.g. a LAG. Ignore the
846 * unsupported devices, another driver might be able to handle them. But
847 * propagate to the callers any hard errors.
848 *
849 * If the driver does its own bookkeeping of stacked ports, it's not
850 * necessary to go through this helper.
851 */
852 netdev_for_each_lower_dev(dev, lower_dev, iter) {
07c6f980
RK
853 if (netif_is_bridge_master(lower_dev))
854 continue;
855
c4076cdd
VO
856 /* When searching for switchdev interfaces that are neighbors
857 * of foreign ones, and @dev is a bridge, do not recurse on the
858 * foreign interface again, it was already visited.
859 */
860 if (foreign_dev_check_cb && !check_cb(lower_dev) &&
861 !switchdev_lower_dev_find(lower_dev, check_cb, foreign_dev_check_cb))
862 continue;
863
f30f0601 864 err = __switchdev_handle_port_obj_del(lower_dev, port_obj_info,
c4076cdd
VO
865 check_cb, foreign_dev_check_cb,
866 del_cb);
f30f0601
PM
867 if (err && err != -EOPNOTSUPP)
868 return err;
869 }
870
c4076cdd
VO
871 /* Event is neither on a bridge nor a LAG. Check whether it is on an
872 * interface that is in a bridge with us.
873 */
874 if (!foreign_dev_check_cb)
875 return err;
876
877 br = netdev_master_upper_dev_get(dev);
878 if (!br || !netif_is_bridge_master(br))
879 return err;
880
acd8df58
VO
881 switchdev = switchdev_lower_dev_find(br, check_cb, foreign_dev_check_cb);
882 if (!switchdev)
883 return err;
884
885 if (!foreign_dev_check_cb(switchdev, dev))
c4076cdd
VO
886 return err;
887
888 return __switchdev_handle_port_obj_del(br, port_obj_info, check_cb,
889 foreign_dev_check_cb, del_cb);
f30f0601
PM
890}
891
c4076cdd
VO
892/* Pass through a port object deletion, if @dev passes @check_cb, or replicate
893 * it towards all lower interfaces of @dev that pass @check_cb, if @dev is a
894 * bridge or a LAG.
895 */
f30f0601
PM
896int switchdev_handle_port_obj_del(struct net_device *dev,
897 struct switchdev_notifier_port_obj_info *port_obj_info,
898 bool (*check_cb)(const struct net_device *dev),
69bfac96 899 int (*del_cb)(struct net_device *dev, const void *ctx,
f30f0601
PM
900 const struct switchdev_obj *obj))
901{
902 int err;
903
904 err = __switchdev_handle_port_obj_del(dev, port_obj_info, check_cb,
c4076cdd 905 NULL, del_cb);
f30f0601
PM
906 if (err == -EOPNOTSUPP)
907 err = 0;
908 return err;
909}
910EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_del);
1cb33af1 911
c4076cdd
VO
912/* Same as switchdev_handle_port_obj_del(), except if object is notified on a
913 * @dev that passes @foreign_dev_check_cb, it is replicated towards all devices
914 * that pass @check_cb and are in the same bridge as @dev.
915 */
916int switchdev_handle_port_obj_del_foreign(struct net_device *dev,
917 struct switchdev_notifier_port_obj_info *port_obj_info,
918 bool (*check_cb)(const struct net_device *dev),
919 bool (*foreign_dev_check_cb)(const struct net_device *dev,
920 const struct net_device *foreign_dev),
921 int (*del_cb)(struct net_device *dev, const void *ctx,
922 const struct switchdev_obj *obj))
923{
924 int err;
925
926 err = __switchdev_handle_port_obj_del(dev, port_obj_info, check_cb,
927 foreign_dev_check_cb, del_cb);
928 if (err == -EOPNOTSUPP)
929 err = 0;
930 return err;
931}
932EXPORT_SYMBOL_GPL(switchdev_handle_port_obj_del_foreign);
933
1cb33af1
FF
934static int __switchdev_handle_port_attr_set(struct net_device *dev,
935 struct switchdev_notifier_port_attr_info *port_attr_info,
936 bool (*check_cb)(const struct net_device *dev),
69bfac96 937 int (*set_cb)(struct net_device *dev, const void *ctx,
4c08c586
VO
938 const struct switchdev_attr *attr,
939 struct netlink_ext_ack *extack))
1cb33af1 940{
69bfac96 941 struct switchdev_notifier_info *info = &port_attr_info->info;
4c08c586 942 struct netlink_ext_ack *extack;
1cb33af1
FF
943 struct net_device *lower_dev;
944 struct list_head *iter;
945 int err = -EOPNOTSUPP;
946
69bfac96 947 extack = switchdev_notifier_info_to_extack(info);
4c08c586 948
1cb33af1 949 if (check_cb(dev)) {
69bfac96 950 err = set_cb(dev, info->ctx, port_attr_info->attr, extack);
20776b46
RV
951 if (err != -EOPNOTSUPP)
952 port_attr_info->handled = true;
953 return err;
1cb33af1
FF
954 }
955
956 /* Switch ports might be stacked under e.g. a LAG. Ignore the
957 * unsupported devices, another driver might be able to handle them. But
958 * propagate to the callers any hard errors.
959 *
960 * If the driver does its own bookkeeping of stacked ports, it's not
961 * necessary to go through this helper.
962 */
963 netdev_for_each_lower_dev(dev, lower_dev, iter) {
07c6f980
RK
964 if (netif_is_bridge_master(lower_dev))
965 continue;
966
1cb33af1
FF
967 err = __switchdev_handle_port_attr_set(lower_dev, port_attr_info,
968 check_cb, set_cb);
969 if (err && err != -EOPNOTSUPP)
970 return err;
971 }
972
973 return err;
974}
975
976int switchdev_handle_port_attr_set(struct net_device *dev,
977 struct switchdev_notifier_port_attr_info *port_attr_info,
978 bool (*check_cb)(const struct net_device *dev),
69bfac96 979 int (*set_cb)(struct net_device *dev, const void *ctx,
4c08c586
VO
980 const struct switchdev_attr *attr,
981 struct netlink_ext_ack *extack))
1cb33af1
FF
982{
983 int err;
984
985 err = __switchdev_handle_port_attr_set(dev, port_attr_info, check_cb,
986 set_cb);
987 if (err == -EOPNOTSUPP)
988 err = 0;
989 return err;
990}
991EXPORT_SYMBOL_GPL(switchdev_handle_port_attr_set);
957e2235
VO
992
993int switchdev_bridge_port_offload(struct net_device *brport_dev,
994 struct net_device *dev, const void *ctx,
995 struct notifier_block *atomic_nb,
996 struct notifier_block *blocking_nb,
997 bool tx_fwd_offload,
998 struct netlink_ext_ack *extack)
999{
1000 struct switchdev_notifier_brport_info brport_info = {
1001 .brport = {
1002 .dev = dev,
1003 .ctx = ctx,
1004 .atomic_nb = atomic_nb,
1005 .blocking_nb = blocking_nb,
1006 .tx_fwd_offload = tx_fwd_offload,
1007 },
1008 };
1009 int err;
1010
1011 ASSERT_RTNL();
1012
1013 err = call_switchdev_blocking_notifiers(SWITCHDEV_BRPORT_OFFLOADED,
1014 brport_dev, &brport_info.info,
1015 extack);
1016 return notifier_to_errno(err);
1017}
1018EXPORT_SYMBOL_GPL(switchdev_bridge_port_offload);
1019
1020void switchdev_bridge_port_unoffload(struct net_device *brport_dev,
1021 const void *ctx,
1022 struct notifier_block *atomic_nb,
1023 struct notifier_block *blocking_nb)
1024{
1025 struct switchdev_notifier_brport_info brport_info = {
1026 .brport = {
1027 .ctx = ctx,
1028 .atomic_nb = atomic_nb,
1029 .blocking_nb = blocking_nb,
1030 },
1031 };
1032
1033 ASSERT_RTNL();
1034
1035 call_switchdev_blocking_notifiers(SWITCHDEV_BRPORT_UNOFFLOADED,
1036 brport_dev, &brport_info.info,
1037 NULL);
1038}
1039EXPORT_SYMBOL_GPL(switchdev_bridge_port_unoffload);
f2e2857b
PM
1040
1041int switchdev_bridge_port_replay(struct net_device *brport_dev,
1042 struct net_device *dev, const void *ctx,
1043 struct notifier_block *atomic_nb,
1044 struct notifier_block *blocking_nb,
1045 struct netlink_ext_ack *extack)
1046{
1047 struct switchdev_notifier_brport_info brport_info = {
1048 .brport = {
1049 .dev = dev,
1050 .ctx = ctx,
1051 .atomic_nb = atomic_nb,
1052 .blocking_nb = blocking_nb,
1053 },
1054 };
1055 int err;
1056
1057 ASSERT_RTNL();
1058
1059 err = call_switchdev_blocking_notifiers(SWITCHDEV_BRPORT_REPLAY,
1060 brport_dev, &brport_info.info,
1061 extack);
1062 return notifier_to_errno(err);
1063}
1064EXPORT_SYMBOL_GPL(switchdev_bridge_port_replay);