]>
Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4 LT |
2 | /* |
3 | * Generic parts | |
4 | * Linux ethernet bridge | |
5 | * | |
6 | * Authors: | |
7 | * Lennert Buytenhek <[email protected]> | |
1da177e4 LT |
8 | */ |
9 | ||
1da177e4 LT |
10 | #include <linux/module.h> |
11 | #include <linux/kernel.h> | |
12 | #include <linux/netdevice.h> | |
13 | #include <linux/etherdevice.h> | |
14 | #include <linux/init.h> | |
cf0f02d0 SH |
15 | #include <linux/llc.h> |
16 | #include <net/llc.h> | |
7c85fbf0 | 17 | #include <net/stp.h> |
3aeb6617 | 18 | #include <net/switchdev.h> |
1da177e4 LT |
19 | |
20 | #include "br_private.h" | |
21 | ||
b1282726 CW |
22 | /* |
23 | * Handle changes in state of network devices enslaved to a bridge. | |
24 | * | |
25 | * Note: don't care about up/down if bridge itself is down, because | |
26 | * port state is checked when bridge is brought up. | |
27 | */ | |
28 | static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr) | |
29 | { | |
b89df65c PM |
30 | struct netlink_ext_ack *extack = netdev_notifier_info_to_extack(ptr); |
31 | struct netdev_notifier_pre_changeaddr_info *prechaddr_info; | |
b1282726 CW |
32 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
33 | struct net_bridge_port *p; | |
34 | struct net_bridge *br; | |
faa1cd82 | 35 | bool notified = false; |
b1282726 CW |
36 | bool changed_addr; |
37 | int err; | |
38 | ||
254ec036 | 39 | if (netif_is_bridge_master(dev)) { |
091adf9b NA |
40 | err = br_vlan_bridge_event(dev, event, ptr); |
41 | if (err) | |
42 | return notifier_from_errno(err); | |
43 | ||
9c0ec2e7 MM |
44 | if (event == NETDEV_REGISTER) { |
45 | /* register of bridge completed, add sysfs entries */ | |
989a1db0 WH |
46 | err = br_sysfs_addbr(dev); |
47 | if (err) | |
48 | return notifier_from_errno(err); | |
49 | ||
9c0ec2e7 MM |
50 | return NOTIFY_DONE; |
51 | } | |
b1282726 CW |
52 | } |
53 | ||
3abd4512 PM |
54 | if (is_vlan_dev(dev)) { |
55 | struct net_device *real_dev = vlan_dev_real_dev(dev); | |
56 | ||
57 | if (netif_is_bridge_master(real_dev)) | |
58 | br_vlan_vlan_upper_event(real_dev, dev, event); | |
59 | } | |
60 | ||
b1282726 CW |
61 | /* not a port of a bridge */ |
62 | p = br_port_get_rtnl(dev); | |
63 | if (!p) | |
64 | return NOTIFY_DONE; | |
65 | ||
66 | br = p->br; | |
67 | ||
68 | switch (event) { | |
69 | case NETDEV_CHANGEMTU: | |
804b854d | 70 | br_mtu_auto_adjust(br); |
b1282726 CW |
71 | break; |
72 | ||
b89df65c PM |
73 | case NETDEV_PRE_CHANGEADDR: |
74 | if (br->dev->addr_assign_type == NET_ADDR_SET) | |
75 | break; | |
76 | prechaddr_info = ptr; | |
77 | err = dev_pre_changeaddr_notify(br->dev, | |
78 | prechaddr_info->dev_addr, | |
79 | extack); | |
80 | if (err) | |
81 | return notifier_from_errno(err); | |
82 | break; | |
83 | ||
b1282726 CW |
84 | case NETDEV_CHANGEADDR: |
85 | spin_lock_bh(&br->lock); | |
86 | br_fdb_changeaddr(p, dev->dev_addr); | |
87 | changed_addr = br_stp_recalculate_bridge_id(br); | |
88 | spin_unlock_bh(&br->lock); | |
89 | ||
90 | if (changed_addr) | |
91 | call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); | |
92 | ||
93 | break; | |
94 | ||
95 | case NETDEV_CHANGE: | |
faa1cd82 | 96 | br_port_carrier_check(p, ¬ified); |
b1282726 CW |
97 | break; |
98 | ||
99 | case NETDEV_FEAT_CHANGE: | |
100 | netdev_update_features(br->dev); | |
101 | break; | |
102 | ||
103 | case NETDEV_DOWN: | |
104 | spin_lock_bh(&br->lock); | |
faa1cd82 | 105 | if (br->dev->flags & IFF_UP) { |
b1282726 | 106 | br_stp_disable_port(p); |
faa1cd82 NA |
107 | notified = true; |
108 | } | |
b1282726 CW |
109 | spin_unlock_bh(&br->lock); |
110 | break; | |
111 | ||
112 | case NETDEV_UP: | |
113 | if (netif_running(br->dev) && netif_oper_up(dev)) { | |
114 | spin_lock_bh(&br->lock); | |
115 | br_stp_enable_port(p); | |
faa1cd82 | 116 | notified = true; |
b1282726 CW |
117 | spin_unlock_bh(&br->lock); |
118 | } | |
119 | break; | |
120 | ||
121 | case NETDEV_UNREGISTER: | |
122 | br_del_if(br, dev); | |
123 | break; | |
124 | ||
125 | case NETDEV_CHANGENAME: | |
126 | err = br_sysfs_renameif(p); | |
127 | if (err) | |
128 | return notifier_from_errno(err); | |
129 | break; | |
130 | ||
131 | case NETDEV_PRE_TYPE_CHANGE: | |
efb5b338 | 132 | /* Forbid underlying device to change its type. */ |
b1282726 CW |
133 | return NOTIFY_BAD; |
134 | ||
135 | case NETDEV_RESEND_IGMP: | |
136 | /* Propagate to master device */ | |
137 | call_netdevice_notifiers(event, br->dev); | |
138 | break; | |
139 | } | |
140 | ||
697cd36c IS |
141 | if (event != NETDEV_UNREGISTER) |
142 | br_vlan_port_event(p, event); | |
9c0ec2e7 | 143 | |
b1282726 | 144 | /* Events that may cause spanning tree to refresh */ |
faa1cd82 NA |
145 | if (!notified && (event == NETDEV_CHANGEADDR || event == NETDEV_UP || |
146 | event == NETDEV_CHANGE || event == NETDEV_DOWN)) | |
92899063 | 147 | br_ifinfo_notify(RTM_NEWLINK, NULL, p); |
b1282726 CW |
148 | |
149 | return NOTIFY_DONE; | |
150 | } | |
151 | ||
152 | static struct notifier_block br_device_notifier = { | |
153 | .notifier_call = br_device_event | |
154 | }; | |
155 | ||
0baa10ff | 156 | /* called with RTNL or RCU */ |
ebb9a03a JP |
157 | static int br_switchdev_event(struct notifier_block *unused, |
158 | unsigned long event, void *ptr) | |
3aeb6617 | 159 | { |
ebb9a03a | 160 | struct net_device *dev = switchdev_notifier_info_to_dev(ptr); |
3aeb6617 JP |
161 | struct net_bridge_port *p; |
162 | struct net_bridge *br; | |
ebb9a03a | 163 | struct switchdev_notifier_fdb_info *fdb_info; |
3aeb6617 JP |
164 | int err = NOTIFY_DONE; |
165 | ||
0baa10ff | 166 | p = br_port_get_rtnl_rcu(dev); |
3aeb6617 JP |
167 | if (!p) |
168 | goto out; | |
169 | ||
170 | br = p->br; | |
171 | ||
172 | switch (event) { | |
6b26b51b | 173 | case SWITCHDEV_FDB_ADD_TO_BRIDGE: |
3aeb6617 JP |
174 | fdb_info = ptr; |
175 | err = br_fdb_external_learn_add(br, p, fdb_info->addr, | |
27fabd02 HS |
176 | fdb_info->vid, |
177 | fdb_info->locked, false); | |
9fe8bcec | 178 | if (err) { |
3aeb6617 | 179 | err = notifier_from_errno(err); |
9fe8bcec AS |
180 | break; |
181 | } | |
182 | br_fdb_offloaded_set(br, p, fdb_info->addr, | |
9baedc3c | 183 | fdb_info->vid, fdb_info->offloaded); |
3aeb6617 | 184 | break; |
6b26b51b | 185 | case SWITCHDEV_FDB_DEL_TO_BRIDGE: |
3aeb6617 JP |
186 | fdb_info = ptr; |
187 | err = br_fdb_external_learn_del(br, p, fdb_info->addr, | |
161d82de | 188 | fdb_info->vid, false); |
3aeb6617 JP |
189 | if (err) |
190 | err = notifier_from_errno(err); | |
191 | break; | |
9fe8bcec AS |
192 | case SWITCHDEV_FDB_OFFLOADED: |
193 | fdb_info = ptr; | |
194 | br_fdb_offloaded_set(br, p, fdb_info->addr, | |
e9ba0fbc | 195 | fdb_info->vid, fdb_info->offloaded); |
9fe8bcec | 196 | break; |
d05e8e68 AW |
197 | case SWITCHDEV_FDB_FLUSH_TO_BRIDGE: |
198 | fdb_info = ptr; | |
199 | /* Don't delete static entries */ | |
200 | br_fdb_delete_by_port(br, p, fdb_info->vid, 0); | |
201 | break; | |
3aeb6617 JP |
202 | } |
203 | ||
204 | out: | |
3aeb6617 JP |
205 | return err; |
206 | } | |
207 | ||
ebb9a03a JP |
208 | static struct notifier_block br_switchdev_notifier = { |
209 | .notifier_call = br_switchdev_event, | |
3aeb6617 JP |
210 | }; |
211 | ||
957e2235 VO |
212 | /* called under rtnl_mutex */ |
213 | static int br_switchdev_blocking_event(struct notifier_block *nb, | |
214 | unsigned long event, void *ptr) | |
215 | { | |
216 | struct netlink_ext_ack *extack = netdev_notifier_info_to_extack(ptr); | |
217 | struct net_device *dev = switchdev_notifier_info_to_dev(ptr); | |
218 | struct switchdev_notifier_brport_info *brport_info; | |
219 | const struct switchdev_brport *b; | |
220 | struct net_bridge_port *p; | |
221 | int err = NOTIFY_DONE; | |
222 | ||
223 | p = br_port_get_rtnl(dev); | |
224 | if (!p) | |
225 | goto out; | |
226 | ||
227 | switch (event) { | |
228 | case SWITCHDEV_BRPORT_OFFLOADED: | |
229 | brport_info = ptr; | |
230 | b = &brport_info->brport; | |
231 | ||
232 | err = br_switchdev_port_offload(p, b->dev, b->ctx, | |
233 | b->atomic_nb, b->blocking_nb, | |
234 | b->tx_fwd_offload, extack); | |
235 | err = notifier_from_errno(err); | |
236 | break; | |
237 | case SWITCHDEV_BRPORT_UNOFFLOADED: | |
238 | brport_info = ptr; | |
239 | b = &brport_info->brport; | |
240 | ||
241 | br_switchdev_port_unoffload(p, b->ctx, b->atomic_nb, | |
242 | b->blocking_nb); | |
243 | break; | |
f2e2857b PM |
244 | case SWITCHDEV_BRPORT_REPLAY: |
245 | brport_info = ptr; | |
246 | b = &brport_info->brport; | |
247 | ||
248 | err = br_switchdev_port_replay(p, b->dev, b->ctx, b->atomic_nb, | |
249 | b->blocking_nb, extack); | |
250 | err = notifier_from_errno(err); | |
251 | break; | |
957e2235 VO |
252 | } |
253 | ||
254 | out: | |
255 | return err; | |
256 | } | |
257 | ||
258 | static struct notifier_block br_switchdev_blocking_notifier = { | |
259 | .notifier_call = br_switchdev_blocking_event, | |
260 | }; | |
261 | ||
a428afe8 NA |
262 | /* br_boolopt_toggle - change user-controlled boolean option |
263 | * | |
264 | * @br: bridge device | |
265 | * @opt: id of the option to change | |
266 | * @on: new option value | |
267 | * @extack: extack for error messages | |
268 | * | |
269 | * Changes the value of the respective boolean option to @on taking care of | |
270 | * any internal option value mapping and configuration. | |
271 | */ | |
272 | int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on, | |
273 | struct netlink_ext_ack *extack) | |
274 | { | |
f4b7002a NA |
275 | int err = 0; |
276 | ||
a428afe8 | 277 | switch (opt) { |
70e4272b NA |
278 | case BR_BOOLOPT_NO_LL_LEARN: |
279 | br_opt_toggle(br, BROPT_NO_LL_LEARN, on); | |
280 | break; | |
f4b7002a NA |
281 | case BR_BOOLOPT_MCAST_VLAN_SNOOPING: |
282 | err = br_multicast_toggle_vlan_snooping(br, on, extack); | |
283 | break; | |
ec7328b5 TW |
284 | case BR_BOOLOPT_MST_ENABLE: |
285 | err = br_mst_set_enabled(br, on, extack); | |
286 | break; | |
a428afe8 NA |
287 | default: |
288 | /* shouldn't be called with unsupported options */ | |
289 | WARN_ON(1); | |
290 | break; | |
291 | } | |
292 | ||
f4b7002a | 293 | return err; |
a428afe8 NA |
294 | } |
295 | ||
296 | int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt) | |
297 | { | |
298 | switch (opt) { | |
70e4272b NA |
299 | case BR_BOOLOPT_NO_LL_LEARN: |
300 | return br_opt_get(br, BROPT_NO_LL_LEARN); | |
f4b7002a NA |
301 | case BR_BOOLOPT_MCAST_VLAN_SNOOPING: |
302 | return br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED); | |
ec7328b5 TW |
303 | case BR_BOOLOPT_MST_ENABLE: |
304 | return br_opt_get(br, BROPT_MST_ENABLED); | |
a428afe8 NA |
305 | default: |
306 | /* shouldn't be called with unsupported options */ | |
307 | WARN_ON(1); | |
308 | break; | |
309 | } | |
310 | ||
311 | return 0; | |
312 | } | |
313 | ||
314 | int br_boolopt_multi_toggle(struct net_bridge *br, | |
315 | struct br_boolopt_multi *bm, | |
316 | struct netlink_ext_ack *extack) | |
317 | { | |
318 | unsigned long bitmap = bm->optmask; | |
319 | int err = 0; | |
320 | int opt_id; | |
321 | ||
322 | for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) { | |
323 | bool on = !!(bm->optval & BIT(opt_id)); | |
324 | ||
325 | err = br_boolopt_toggle(br, opt_id, on, extack); | |
326 | if (err) { | |
327 | br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n", | |
328 | opt_id, br_boolopt_get(br, opt_id), on, err); | |
329 | break; | |
330 | } | |
331 | } | |
332 | ||
333 | return err; | |
334 | } | |
335 | ||
336 | void br_boolopt_multi_get(const struct net_bridge *br, | |
337 | struct br_boolopt_multi *bm) | |
338 | { | |
339 | u32 optval = 0; | |
340 | int opt_id; | |
341 | ||
342 | for (opt_id = 0; opt_id < BR_BOOLOPT_MAX; opt_id++) | |
343 | optval |= (br_boolopt_get(br, opt_id) << opt_id); | |
344 | ||
345 | bm->optval = optval; | |
1ed1ccb9 | 346 | bm->optmask = GENMASK((BR_BOOLOPT_MAX - 1), 0); |
a428afe8 NA |
347 | } |
348 | ||
349 | /* private bridge options, controlled by the kernel */ | |
ae75767e NA |
350 | void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on) |
351 | { | |
352 | bool cur = !!br_opt_get(br, opt); | |
353 | ||
354 | br_debug(br, "toggle option: %d state: %d -> %d\n", | |
355 | opt, cur, on); | |
356 | ||
357 | if (cur == on) | |
358 | return; | |
359 | ||
360 | if (on) | |
361 | set_bit(opt, &br->options); | |
362 | else | |
363 | clear_bit(opt, &br->options); | |
364 | } | |
365 | ||
806b6785 ED |
366 | static void __net_exit br_net_exit_batch_rtnl(struct list_head *net_list, |
367 | struct list_head *dev_to_kill) | |
b86f81cc WC |
368 | { |
369 | struct net_device *dev; | |
36a29fb6 | 370 | struct net *net; |
36a29fb6 | 371 | |
806b6785 | 372 | ASSERT_RTNL(); |
36a29fb6 ED |
373 | list_for_each_entry(net, net_list, exit_list) |
374 | for_each_netdev(net, dev) | |
375 | if (netif_is_bridge_master(dev)) | |
806b6785 | 376 | br_dev_delete(dev, dev_to_kill); |
b86f81cc | 377 | } |
cf0f02d0 | 378 | |
712d6954 | 379 | static struct pernet_operations br_net_ops = { |
806b6785 | 380 | .exit_batch_rtnl = br_net_exit_batch_rtnl, |
712d6954 AD |
381 | }; |
382 | ||
b86f81cc WC |
383 | static const struct stp_proto br_stp_proto = { |
384 | .rcv = br_stp_rcv, | |
385 | }; | |
386 | ||
1da177e4 LT |
387 | static int __init br_init(void) |
388 | { | |
c0909713 SH |
389 | int err; |
390 | ||
c593642c | 391 | BUILD_BUG_ON(sizeof(struct br_input_skb_cb) > sizeof_field(struct sk_buff, cb)); |
71e168b1 | 392 | |
7c85fbf0 PM |
393 | err = stp_proto_register(&br_stp_proto); |
394 | if (err < 0) { | |
28a16c97 | 395 | pr_err("bridge: can't register sap for STP\n"); |
7c85fbf0 | 396 | return err; |
cf0f02d0 SH |
397 | } |
398 | ||
87a596e0 AM |
399 | err = br_fdb_init(); |
400 | if (err) | |
17efdd45 | 401 | goto err_out; |
1da177e4 | 402 | |
712d6954 | 403 | err = register_pernet_subsys(&br_net_ops); |
c0909713 SH |
404 | if (err) |
405 | goto err_out1; | |
406 | ||
34666d46 | 407 | err = br_nf_core_init(); |
c0909713 SH |
408 | if (err) |
409 | goto err_out2; | |
410 | ||
712d6954 | 411 | err = register_netdevice_notifier(&br_device_notifier); |
32fe21c0 TG |
412 | if (err) |
413 | goto err_out3; | |
414 | ||
ebb9a03a | 415 | err = register_switchdev_notifier(&br_switchdev_notifier); |
712d6954 AD |
416 | if (err) |
417 | goto err_out4; | |
418 | ||
957e2235 | 419 | err = register_switchdev_blocking_notifier(&br_switchdev_blocking_notifier); |
3aeb6617 JP |
420 | if (err) |
421 | goto err_out5; | |
422 | ||
957e2235 VO |
423 | err = br_netlink_init(); |
424 | if (err) | |
425 | goto err_out6; | |
426 | ||
ad2f99ae | 427 | brioctl_set(br_ioctl_stub); |
1da177e4 | 428 | |
e6373c4c | 429 | #if IS_ENABLED(CONFIG_ATM_LANE) |
da678292 MM |
430 | br_fdb_test_addr_hook = br_fdb_test_addr; |
431 | #endif | |
1da177e4 | 432 | |
d4ef9f72 SA |
433 | #if IS_MODULE(CONFIG_BRIDGE_NETFILTER) |
434 | pr_info("bridge: filtering via arp/ip/ip6tables is no longer available " | |
435 | "by default. Update your scripts to load br_netfilter if you " | |
34666d46 | 436 | "need this.\n"); |
d4ef9f72 | 437 | #endif |
34666d46 | 438 | |
1da177e4 | 439 | return 0; |
34666d46 | 440 | |
957e2235 VO |
441 | err_out6: |
442 | unregister_switchdev_blocking_notifier(&br_switchdev_blocking_notifier); | |
3aeb6617 | 443 | err_out5: |
ebb9a03a | 444 | unregister_switchdev_notifier(&br_switchdev_notifier); |
712d6954 | 445 | err_out4: |
32fe21c0 | 446 | unregister_netdevice_notifier(&br_device_notifier); |
712d6954 | 447 | err_out3: |
34666d46 | 448 | br_nf_core_fini(); |
712d6954 AD |
449 | err_out2: |
450 | unregister_pernet_subsys(&br_net_ops); | |
c0909713 | 451 | err_out1: |
17efdd45 PE |
452 | br_fdb_fini(); |
453 | err_out: | |
7c85fbf0 | 454 | stp_proto_unregister(&br_stp_proto); |
c0909713 | 455 | return err; |
1da177e4 LT |
456 | } |
457 | ||
458 | static void __exit br_deinit(void) | |
459 | { | |
7c85fbf0 | 460 | stp_proto_unregister(&br_stp_proto); |
11dc1f36 | 461 | br_netlink_fini(); |
957e2235 | 462 | unregister_switchdev_blocking_notifier(&br_switchdev_blocking_notifier); |
ebb9a03a | 463 | unregister_switchdev_notifier(&br_switchdev_notifier); |
1da177e4 LT |
464 | unregister_netdevice_notifier(&br_device_notifier); |
465 | brioctl_set(NULL); | |
712d6954 | 466 | unregister_pernet_subsys(&br_net_ops); |
1da177e4 | 467 | |
473c22d7 | 468 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
1da177e4 | 469 | |
34666d46 | 470 | br_nf_core_fini(); |
e6373c4c | 471 | #if IS_ENABLED(CONFIG_ATM_LANE) |
da678292 MM |
472 | br_fdb_test_addr_hook = NULL; |
473 | #endif | |
1da177e4 LT |
474 | br_fdb_fini(); |
475 | } | |
476 | ||
1da177e4 LT |
477 | module_init(br_init) |
478 | module_exit(br_deinit) | |
479 | MODULE_LICENSE("GPL"); | |
8cbb512e | 480 | MODULE_VERSION(BR_VERSION); |
bb900b27 | 481 | MODULE_ALIAS_RTNL_LINK("bridge"); |
68089183 | 482 | MODULE_DESCRIPTION("Ethernet bridge driver"); |