aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_multicast.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r--net/bridge/br_multicast.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 0b39dcc65b94..0752796fe0ba 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -283,6 +283,8 @@ static void br_multicast_del_pg(struct net_bridge *br,
283 rcu_assign_pointer(*pp, p->next); 283 rcu_assign_pointer(*pp, p->next);
284 hlist_del_init(&p->mglist); 284 hlist_del_init(&p->mglist);
285 del_timer(&p->timer); 285 del_timer(&p->timer);
286 br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB,
287 p->state);
286 call_rcu_bh(&p->rcu, br_multicast_free_pg); 288 call_rcu_bh(&p->rcu, br_multicast_free_pg);
287 289
288 if (!mp->ports && !mp->mglist && 290 if (!mp->ports && !mp->mglist &&
@@ -704,7 +706,7 @@ static int br_multicast_add_group(struct net_bridge *br,
704 if (unlikely(!p)) 706 if (unlikely(!p))
705 goto err; 707 goto err;
706 rcu_assign_pointer(*pp, p); 708 rcu_assign_pointer(*pp, p);
707 br_mdb_notify(br->dev, port, group, RTM_NEWMDB); 709 br_mdb_notify(br->dev, port, group, RTM_NEWMDB, MDB_TEMPORARY);
708 710
709found: 711found:
710 mod_timer(&p->timer, now + br->multicast_membership_interval); 712 mod_timer(&p->timer, now + br->multicast_membership_interval);
@@ -764,6 +766,7 @@ static void br_multicast_router_expired(unsigned long data)
764 goto out; 766 goto out;
765 767
766 hlist_del_init_rcu(&port->rlist); 768 hlist_del_init_rcu(&port->rlist);
769 br_rtr_notify(br->dev, port, RTM_DELMDB);
767 770
768out: 771out:
769 spin_unlock(&br->multicast_lock); 772 spin_unlock(&br->multicast_lock);
@@ -924,6 +927,15 @@ void br_multicast_add_port(struct net_bridge_port *port)
924 927
925void br_multicast_del_port(struct net_bridge_port *port) 928void br_multicast_del_port(struct net_bridge_port *port)
926{ 929{
930 struct net_bridge *br = port->br;
931 struct net_bridge_port_group *pg;
932 struct hlist_node *n;
933
934 /* Take care of the remaining groups, only perm ones should be left */
935 spin_lock_bh(&br->multicast_lock);
936 hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
937 br_multicast_del_pg(br, pg);
938 spin_unlock_bh(&br->multicast_lock);
927 del_timer_sync(&port->multicast_router_timer); 939 del_timer_sync(&port->multicast_router_timer);
928} 940}
929 941
@@ -963,10 +975,13 @@ void br_multicast_disable_port(struct net_bridge_port *port)
963 975
964 spin_lock(&br->multicast_lock); 976 spin_lock(&br->multicast_lock);
965 hlist_for_each_entry_safe(pg, n, &port->mglist, mglist) 977 hlist_for_each_entry_safe(pg, n, &port->mglist, mglist)
966 br_multicast_del_pg(br, pg); 978 if (pg->state == MDB_TEMPORARY)
979 br_multicast_del_pg(br, pg);
967 980
968 if (!hlist_unhashed(&port->rlist)) 981 if (!hlist_unhashed(&port->rlist)) {
969 hlist_del_init_rcu(&port->rlist); 982 hlist_del_init_rcu(&port->rlist);
983 br_rtr_notify(br->dev, port, RTM_DELMDB);
984 }
970 del_timer(&port->multicast_router_timer); 985 del_timer(&port->multicast_router_timer);
971 del_timer(&port->ip4_own_query.timer); 986 del_timer(&port->ip4_own_query.timer);
972#if IS_ENABLED(CONFIG_IPV6) 987#if IS_ENABLED(CONFIG_IPV6)
@@ -1204,6 +1219,7 @@ static void br_multicast_add_router(struct net_bridge *br,
1204 hlist_add_behind_rcu(&port->rlist, slot); 1219 hlist_add_behind_rcu(&port->rlist, slot);
1205 else 1220 else
1206 hlist_add_head_rcu(&port->rlist, &br->router_list); 1221 hlist_add_head_rcu(&port->rlist, &br->router_list);
1222 br_rtr_notify(br->dev, port, RTM_NEWMDB);
1207} 1223}
1208 1224
1209static void br_multicast_mark_router(struct net_bridge *br, 1225static void br_multicast_mark_router(struct net_bridge *br,
@@ -1437,7 +1453,8 @@ br_multicast_leave_group(struct net_bridge *br,
1437 hlist_del_init(&p->mglist); 1453 hlist_del_init(&p->mglist);
1438 del_timer(&p->timer); 1454 del_timer(&p->timer);
1439 call_rcu_bh(&p->rcu, br_multicast_free_pg); 1455 call_rcu_bh(&p->rcu, br_multicast_free_pg);
1440 br_mdb_notify(br->dev, port, group, RTM_DELMDB); 1456 br_mdb_notify(br->dev, port, group, RTM_DELMDB,
1457 p->state);
1441 1458
1442 if (!mp->ports && !mp->mglist && 1459 if (!mp->ports && !mp->mglist &&
1443 netif_running(br->dev)) 1460 netif_running(br->dev))
@@ -1754,12 +1771,6 @@ void br_multicast_open(struct net_bridge *br)
1754 1771
1755void br_multicast_stop(struct net_bridge *br) 1772void br_multicast_stop(struct net_bridge *br)
1756{ 1773{
1757 struct net_bridge_mdb_htable *mdb;
1758 struct net_bridge_mdb_entry *mp;
1759 struct hlist_node *n;
1760 u32 ver;
1761 int i;
1762
1763 del_timer_sync(&br->multicast_router_timer); 1774 del_timer_sync(&br->multicast_router_timer);
1764 del_timer_sync(&br->ip4_other_query.timer); 1775 del_timer_sync(&br->ip4_other_query.timer);
1765 del_timer_sync(&br->ip4_own_query.timer); 1776 del_timer_sync(&br->ip4_own_query.timer);
@@ -1767,6 +1778,15 @@ void br_multicast_stop(struct net_bridge *br)
1767 del_timer_sync(&br->ip6_other_query.timer); 1778 del_timer_sync(&br->ip6_other_query.timer);
1768 del_timer_sync(&br->ip6_own_query.timer); 1779 del_timer_sync(&br->ip6_own_query.timer);
1769#endif 1780#endif
1781}
1782
1783void br_multicast_dev_del(struct net_bridge *br)
1784{
1785 struct net_bridge_mdb_htable *mdb;
1786 struct net_bridge_mdb_entry *mp;
1787 struct hlist_node *n;
1788 u32 ver;
1789 int i;
1770 1790
1771 spin_lock_bh(&br->multicast_lock); 1791 spin_lock_bh(&br->multicast_lock);
1772 mdb = mlock_dereference(br->mdb, br); 1792 mdb = mlock_dereference(br->mdb, br);
@@ -1834,8 +1854,10 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
1834 p->multicast_router = val; 1854 p->multicast_router = val;
1835 err = 0; 1855 err = 0;
1836 1856
1837 if (val < 2 && !hlist_unhashed(&p->rlist)) 1857 if (val < 2 && !hlist_unhashed(&p->rlist)) {
1838 hlist_del_init_rcu(&p->rlist); 1858 hlist_del_init_rcu(&p->rlist);
1859 br_rtr_notify(br->dev, p, RTM_DELMDB);
1860 }
1839 1861
1840 if (val == 1) 1862 if (val == 1)
1841 break; 1863 break;