br_mdb.c (320424c7d44f54c18df9812fd7c45f6963524002) br_mdb.c (9632233e7de8da43711bb7cd3e054af32fedcc38)
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/err.h>
3#include <linux/igmp.h>
4#include <linux/kernel.h>
5#include <linux/netdevice.h>
6#include <linux/rculist.h>
7#include <linux/skbuff.h>
8#include <linux/if_ether.h>
9#include <net/ip.h>
10#include <net/netlink.h>
11#include <net/switchdev.h>
12#if IS_ENABLED(CONFIG_IPV6)
13#include <net/ipv6.h>
14#include <net/addrconf.h>
15#endif
16
17#include "br_private.h"
18
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/err.h>
3#include <linux/igmp.h>
4#include <linux/kernel.h>
5#include <linux/netdevice.h>
6#include <linux/rculist.h>
7#include <linux/skbuff.h>
8#include <linux/if_ether.h>
9#include <net/ip.h>
10#include <net/netlink.h>
11#include <net/switchdev.h>
12#if IS_ENABLED(CONFIG_IPV6)
13#include <net/ipv6.h>
14#include <net/addrconf.h>
15#endif
16
17#include "br_private.h"
18
19static bool br_rports_have_mc_router(struct net_bridge *br)
20{
21#if IS_ENABLED(CONFIG_IPV6)
22 return !hlist_empty(&br->ip4_mc_router_list) ||
23 !hlist_empty(&br->ip6_mc_router_list);
24#else
25 return !hlist_empty(&br->ip4_mc_router_list);
26#endif
27}
28
29static bool
30br_ip4_rports_get_timer(struct net_bridge_port *port, unsigned long *timer)
31{
32 *timer = br_timer_value(&port->multicast_ctx.ip4_mc_router_timer);
33 return !hlist_unhashed(&port->multicast_ctx.ip4_rlist);
34}
35
36static bool
37br_ip6_rports_get_timer(struct net_bridge_port *port, unsigned long *timer)
38{
39#if IS_ENABLED(CONFIG_IPV6)
40 *timer = br_timer_value(&port->multicast_ctx.ip6_mc_router_timer);
41 return !hlist_unhashed(&port->multicast_ctx.ip6_rlist);
42#else
43 *timer = 0;
44 return false;
45#endif
46}
47
19static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
20 struct net_device *dev)
21{
22 struct net_bridge *br = netdev_priv(dev);
48static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
49 struct net_device *dev)
50{
51 struct net_bridge *br = netdev_priv(dev);
23 struct net_bridge_port *p;
52 bool have_ip4_mc_rtr, have_ip6_mc_rtr;
53 unsigned long ip4_timer, ip6_timer;
24 struct nlattr *nest, *port_nest;
54 struct nlattr *nest, *port_nest;
55 struct net_bridge_port *p;
25
56
26 if (!br->multicast_router || hlist_empty(&br->router_list))
57 if (!br->multicast_router)
27 return 0;
28
58 return 0;
59
60 if (!br_rports_have_mc_router(br))
61 return 0;
62
29 nest = nla_nest_start_noflag(skb, MDBA_ROUTER);
30 if (nest == NULL)
31 return -EMSGSIZE;
32
63 nest = nla_nest_start_noflag(skb, MDBA_ROUTER);
64 if (nest == NULL)
65 return -EMSGSIZE;
66
33 hlist_for_each_entry_rcu(p, &br->router_list, rlist) {
34 if (!p)
67 list_for_each_entry_rcu(p, &br->port_list, list) {
68 have_ip4_mc_rtr = br_ip4_rports_get_timer(p, &ip4_timer);
69 have_ip6_mc_rtr = br_ip6_rports_get_timer(p, &ip6_timer);
70
71 if (!have_ip4_mc_rtr && !have_ip6_mc_rtr)
35 continue;
72 continue;
73
36 port_nest = nla_nest_start_noflag(skb, MDBA_ROUTER_PORT);
37 if (!port_nest)
38 goto fail;
74 port_nest = nla_nest_start_noflag(skb, MDBA_ROUTER_PORT);
75 if (!port_nest)
76 goto fail;
77
39 if (nla_put_nohdr(skb, sizeof(u32), &p->dev->ifindex) ||
40 nla_put_u32(skb, MDBA_ROUTER_PATTR_TIMER,
78 if (nla_put_nohdr(skb, sizeof(u32), &p->dev->ifindex) ||
79 nla_put_u32(skb, MDBA_ROUTER_PATTR_TIMER,
41 br_timer_value(&p->multicast_router_timer)) ||
80 max(ip4_timer, ip6_timer)) ||
42 nla_put_u8(skb, MDBA_ROUTER_PATTR_TYPE,
81 nla_put_u8(skb, MDBA_ROUTER_PATTR_TYPE,
43 p->multicast_router)) {
82 p->multicast_ctx.multicast_router) ||
83 (have_ip4_mc_rtr &&
84 nla_put_u32(skb, MDBA_ROUTER_PATTR_INET_TIMER,
85 ip4_timer)) ||
86 (have_ip6_mc_rtr &&
87 nla_put_u32(skb, MDBA_ROUTER_PATTR_INET6_TIMER,
88 ip6_timer))) {
44 nla_nest_cancel(skb, port_nest);
45 goto fail;
46 }
47 nla_nest_end(skb, port_nest);
48 }
49
50 nla_nest_end(skb, nest);
51 return 0;

--- 465 unchanged lines hidden (view full) ---

517#endif
518 else
519 ether_addr_copy(mdb->addr, mp->addr.dst.mac_addr);
520
521 mdb->vid = mp->addr.vid;
522}
523
524static int br_mdb_replay_one(struct notifier_block *nb, struct net_device *dev,
89 nla_nest_cancel(skb, port_nest);
90 goto fail;
91 }
92 nla_nest_end(skb, port_nest);
93 }
94
95 nla_nest_end(skb, nest);
96 return 0;

--- 465 unchanged lines hidden (view full) ---

562#endif
563 else
564 ether_addr_copy(mdb->addr, mp->addr.dst.mac_addr);
565
566 mdb->vid = mp->addr.vid;
567}
568
569static int br_mdb_replay_one(struct notifier_block *nb, struct net_device *dev,
525 struct switchdev_obj_port_mdb *mdb,
570 const struct switchdev_obj_port_mdb *mdb,
571 unsigned long action, const void *ctx,
526 struct netlink_ext_ack *extack)
527{
528 struct switchdev_notifier_port_obj_info obj_info = {
529 .info = {
530 .dev = dev,
531 .extack = extack,
572 struct netlink_ext_ack *extack)
573{
574 struct switchdev_notifier_port_obj_info obj_info = {
575 .info = {
576 .dev = dev,
577 .extack = extack,
578 .ctx = ctx,
532 },
533 .obj = &mdb->obj,
534 };
535 int err;
536
579 },
580 .obj = &mdb->obj,
581 };
582 int err;
583
537 err = nb->notifier_call(nb, SWITCHDEV_PORT_OBJ_ADD, &obj_info);
584 err = nb->notifier_call(nb, action, &obj_info);
538 return notifier_to_errno(err);
539}
540
541static int br_mdb_queue_one(struct list_head *mdb_list,
542 enum switchdev_obj_id id,
543 const struct net_bridge_mdb_entry *mp,
544 struct net_device *orig_dev)
545{

--- 7 unchanged lines hidden (view full) ---

553 mdb->obj.orig_dev = orig_dev;
554 br_switchdev_mdb_populate(mdb, mp);
555 list_add_tail(&mdb->obj.list, mdb_list);
556
557 return 0;
558}
559
560int br_mdb_replay(struct net_device *br_dev, struct net_device *dev,
585 return notifier_to_errno(err);
586}
587
588static int br_mdb_queue_one(struct list_head *mdb_list,
589 enum switchdev_obj_id id,
590 const struct net_bridge_mdb_entry *mp,
591 struct net_device *orig_dev)
592{

--- 7 unchanged lines hidden (view full) ---

600 mdb->obj.orig_dev = orig_dev;
601 br_switchdev_mdb_populate(mdb, mp);
602 list_add_tail(&mdb->obj.list, mdb_list);
603
604 return 0;
605}
606
607int br_mdb_replay(struct net_device *br_dev, struct net_device *dev,
561 struct notifier_block *nb, struct netlink_ext_ack *extack)
608 const void *ctx, bool adding, struct notifier_block *nb,
609 struct netlink_ext_ack *extack)
562{
610{
563 struct net_bridge_mdb_entry *mp;
611 const struct net_bridge_mdb_entry *mp;
564 struct switchdev_obj *obj, *tmp;
565 struct net_bridge *br;
612 struct switchdev_obj *obj, *tmp;
613 struct net_bridge *br;
614 unsigned long action;
566 LIST_HEAD(mdb_list);
567 int err = 0;
568
569 ASSERT_RTNL();
570
571 if (!netif_is_bridge_master(br_dev) || !netif_is_bridge_port(dev))
572 return -EINVAL;
573

--- 8 unchanged lines hidden (view full) ---

582 * switchdev event, so since both br->multicast_lock and RCU read side
583 * critical sections are atomic, we have no choice but to pick the RCU
584 * read side lock, queue up all our events, leave the critical section
585 * and notify switchdev from blocking context.
586 */
587 rcu_read_lock();
588
589 hlist_for_each_entry_rcu(mp, &br->mdb_list, mdb_node) {
615 LIST_HEAD(mdb_list);
616 int err = 0;
617
618 ASSERT_RTNL();
619
620 if (!netif_is_bridge_master(br_dev) || !netif_is_bridge_port(dev))
621 return -EINVAL;
622

--- 8 unchanged lines hidden (view full) ---

631 * switchdev event, so since both br->multicast_lock and RCU read side
632 * critical sections are atomic, we have no choice but to pick the RCU
633 * read side lock, queue up all our events, leave the critical section
634 * and notify switchdev from blocking context.
635 */
636 rcu_read_lock();
637
638 hlist_for_each_entry_rcu(mp, &br->mdb_list, mdb_node) {
590 struct net_bridge_port_group __rcu **pp;
591 struct net_bridge_port_group *p;
639 struct net_bridge_port_group __rcu * const *pp;
640 const struct net_bridge_port_group *p;
592
593 if (mp->host_joined) {
594 err = br_mdb_queue_one(&mdb_list,
595 SWITCHDEV_OBJ_ID_HOST_MDB,
596 mp, br_dev);
597 if (err) {
598 rcu_read_unlock();
599 goto out_free_mdb;

--- 12 unchanged lines hidden (view full) ---

612 rcu_read_unlock();
613 goto out_free_mdb;
614 }
615 }
616 }
617
618 rcu_read_unlock();
619
641
642 if (mp->host_joined) {
643 err = br_mdb_queue_one(&mdb_list,
644 SWITCHDEV_OBJ_ID_HOST_MDB,
645 mp, br_dev);
646 if (err) {
647 rcu_read_unlock();
648 goto out_free_mdb;

--- 12 unchanged lines hidden (view full) ---

661 rcu_read_unlock();
662 goto out_free_mdb;
663 }
664 }
665 }
666
667 rcu_read_unlock();
668
669 if (adding)
670 action = SWITCHDEV_PORT_OBJ_ADD;
671 else
672 action = SWITCHDEV_PORT_OBJ_DEL;
673
620 list_for_each_entry(obj, &mdb_list, list) {
621 err = br_mdb_replay_one(nb, dev, SWITCHDEV_OBJ_PORT_MDB(obj),
674 list_for_each_entry(obj, &mdb_list, list) {
675 err = br_mdb_replay_one(nb, dev, SWITCHDEV_OBJ_PORT_MDB(obj),
622 extack);
676 action, ctx, extack);
623 if (err)
624 goto out_free_mdb;
625 }
626
627out_free_mdb:
628 list_for_each_entry_safe(obj, tmp, &mdb_list, list) {
629 list_del(&obj->list);
630 kfree(SWITCHDEV_OBJ_PORT_MDB(obj));

--- 622 unchanged lines hidden ---
677 if (err)
678 goto out_free_mdb;
679 }
680
681out_free_mdb:
682 list_for_each_entry_safe(obj, tmp, &mdb_list, list) {
683 list_del(&obj->list);
684 kfree(SWITCHDEV_OBJ_PORT_MDB(obj));

--- 622 unchanged lines hidden ---