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