diff options
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r-- | net/bridge/br_multicast.c | 44 |
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 | ||
709 | found: | 711 | found: |
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 | ||
768 | out: | 771 | out: |
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 | ||
925 | void br_multicast_del_port(struct net_bridge_port *port) | 928 | void 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 | ||
1209 | static void br_multicast_mark_router(struct net_bridge *br, | 1225 | static 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 | ||
1755 | void br_multicast_stop(struct net_bridge *br) | 1772 | void 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 | |||
1783 | void 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; |