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.c88
1 files changed, 57 insertions, 31 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index f19e347f56f6..f03e2e98cd44 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -33,6 +33,9 @@
33 33
34#include "br_private.h" 34#include "br_private.h"
35 35
36#define mlock_dereference(X, br) \
37 rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock))
38
36#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 39#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
37static inline int ipv6_is_local_multicast(const struct in6_addr *addr) 40static inline int ipv6_is_local_multicast(const struct in6_addr *addr)
38{ 41{
@@ -135,7 +138,7 @@ static struct net_bridge_mdb_entry *br_mdb_ip6_get(
135struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, 138struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
136 struct sk_buff *skb) 139 struct sk_buff *skb)
137{ 140{
138 struct net_bridge_mdb_htable *mdb = br->mdb; 141 struct net_bridge_mdb_htable *mdb = rcu_dereference(br->mdb);
139 struct br_ip ip; 142 struct br_ip ip;
140 143
141 if (br->multicast_disabled) 144 if (br->multicast_disabled)
@@ -235,7 +238,8 @@ static void br_multicast_group_expired(unsigned long data)
235 if (mp->ports) 238 if (mp->ports)
236 goto out; 239 goto out;
237 240
238 mdb = br->mdb; 241 mdb = mlock_dereference(br->mdb, br);
242
239 hlist_del_rcu(&mp->hlist[mdb->ver]); 243 hlist_del_rcu(&mp->hlist[mdb->ver]);
240 mdb->size--; 244 mdb->size--;
241 245
@@ -249,16 +253,20 @@ out:
249static void br_multicast_del_pg(struct net_bridge *br, 253static void br_multicast_del_pg(struct net_bridge *br,
250 struct net_bridge_port_group *pg) 254 struct net_bridge_port_group *pg)
251{ 255{
252 struct net_bridge_mdb_htable *mdb = br->mdb; 256 struct net_bridge_mdb_htable *mdb;
253 struct net_bridge_mdb_entry *mp; 257 struct net_bridge_mdb_entry *mp;
254 struct net_bridge_port_group *p; 258 struct net_bridge_port_group *p;
255 struct net_bridge_port_group **pp; 259 struct net_bridge_port_group __rcu **pp;
260
261 mdb = mlock_dereference(br->mdb, br);
256 262
257 mp = br_mdb_ip_get(mdb, &pg->addr); 263 mp = br_mdb_ip_get(mdb, &pg->addr);
258 if (WARN_ON(!mp)) 264 if (WARN_ON(!mp))
259 return; 265 return;
260 266
261 for (pp = &mp->ports; (p = *pp); pp = &p->next) { 267 for (pp = &mp->ports;
268 (p = mlock_dereference(*pp, br)) != NULL;
269 pp = &p->next) {
262 if (p != pg) 270 if (p != pg)
263 continue; 271 continue;
264 272
@@ -294,10 +302,10 @@ out:
294 spin_unlock(&br->multicast_lock); 302 spin_unlock(&br->multicast_lock);
295} 303}
296 304
297static int br_mdb_rehash(struct net_bridge_mdb_htable **mdbp, int max, 305static int br_mdb_rehash(struct net_bridge_mdb_htable __rcu **mdbp, int max,
298 int elasticity) 306 int elasticity)
299{ 307{
300 struct net_bridge_mdb_htable *old = *mdbp; 308 struct net_bridge_mdb_htable *old = rcu_dereference_protected(*mdbp, 1);
301 struct net_bridge_mdb_htable *mdb; 309 struct net_bridge_mdb_htable *mdb;
302 int err; 310 int err;
303 311
@@ -569,7 +577,7 @@ static struct net_bridge_mdb_entry *br_multicast_get_group(
569 struct net_bridge *br, struct net_bridge_port *port, 577 struct net_bridge *br, struct net_bridge_port *port,
570 struct br_ip *group, int hash) 578 struct br_ip *group, int hash)
571{ 579{
572 struct net_bridge_mdb_htable *mdb = br->mdb; 580 struct net_bridge_mdb_htable *mdb;
573 struct net_bridge_mdb_entry *mp; 581 struct net_bridge_mdb_entry *mp;
574 struct hlist_node *p; 582 struct hlist_node *p;
575 unsigned count = 0; 583 unsigned count = 0;
@@ -577,6 +585,7 @@ static struct net_bridge_mdb_entry *br_multicast_get_group(
577 int elasticity; 585 int elasticity;
578 int err; 586 int err;
579 587
588 mdb = rcu_dereference_protected(br->mdb, 1);
580 hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { 589 hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) {
581 count++; 590 count++;
582 if (unlikely(br_ip_equal(group, &mp->addr))) 591 if (unlikely(br_ip_equal(group, &mp->addr)))
@@ -642,13 +651,16 @@ static struct net_bridge_mdb_entry *br_multicast_new_group(
642 struct net_bridge *br, struct net_bridge_port *port, 651 struct net_bridge *br, struct net_bridge_port *port,
643 struct br_ip *group) 652 struct br_ip *group)
644{ 653{
645 struct net_bridge_mdb_htable *mdb = br->mdb; 654 struct net_bridge_mdb_htable *mdb;
646 struct net_bridge_mdb_entry *mp; 655 struct net_bridge_mdb_entry *mp;
647 int hash; 656 int hash;
657 int err;
648 658
659 mdb = rcu_dereference_protected(br->mdb, 1);
649 if (!mdb) { 660 if (!mdb) {
650 if (br_mdb_rehash(&br->mdb, BR_HASH_SIZE, 0)) 661 err = br_mdb_rehash(&br->mdb, BR_HASH_SIZE, 0);
651 return NULL; 662 if (err)
663 return ERR_PTR(err);
652 goto rehash; 664 goto rehash;
653 } 665 }
654 666
@@ -660,7 +672,7 @@ static struct net_bridge_mdb_entry *br_multicast_new_group(
660 672
661 case -EAGAIN: 673 case -EAGAIN:
662rehash: 674rehash:
663 mdb = br->mdb; 675 mdb = rcu_dereference_protected(br->mdb, 1);
664 hash = br_ip_hash(mdb, group); 676 hash = br_ip_hash(mdb, group);
665 break; 677 break;
666 678
@@ -670,7 +682,7 @@ rehash:
670 682
671 mp = kzalloc(sizeof(*mp), GFP_ATOMIC); 683 mp = kzalloc(sizeof(*mp), GFP_ATOMIC);
672 if (unlikely(!mp)) 684 if (unlikely(!mp))
673 goto out; 685 return ERR_PTR(-ENOMEM);
674 686
675 mp->br = br; 687 mp->br = br;
676 mp->addr = *group; 688 mp->addr = *group;
@@ -692,7 +704,7 @@ static int br_multicast_add_group(struct net_bridge *br,
692{ 704{
693 struct net_bridge_mdb_entry *mp; 705 struct net_bridge_mdb_entry *mp;
694 struct net_bridge_port_group *p; 706 struct net_bridge_port_group *p;
695 struct net_bridge_port_group **pp; 707 struct net_bridge_port_group __rcu **pp;
696 unsigned long now = jiffies; 708 unsigned long now = jiffies;
697 int err; 709 int err;
698 710
@@ -703,7 +715,7 @@ static int br_multicast_add_group(struct net_bridge *br,
703 715
704 mp = br_multicast_new_group(br, port, group); 716 mp = br_multicast_new_group(br, port, group);
705 err = PTR_ERR(mp); 717 err = PTR_ERR(mp);
706 if (unlikely(IS_ERR(mp) || !mp)) 718 if (IS_ERR(mp))
707 goto err; 719 goto err;
708 720
709 if (!port) { 721 if (!port) {
@@ -712,7 +724,9 @@ static int br_multicast_add_group(struct net_bridge *br,
712 goto out; 724 goto out;
713 } 725 }
714 726
715 for (pp = &mp->ports; (p = *pp); pp = &p->next) { 727 for (pp = &mp->ports;
728 (p = mlock_dereference(*pp, br)) != NULL;
729 pp = &p->next) {
716 if (p->port == port) 730 if (p->port == port)
717 goto found; 731 goto found;
718 if ((unsigned long)p->port < (unsigned long)port) 732 if ((unsigned long)p->port < (unsigned long)port)
@@ -1106,7 +1120,7 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1106 struct net_bridge_mdb_entry *mp; 1120 struct net_bridge_mdb_entry *mp;
1107 struct igmpv3_query *ih3; 1121 struct igmpv3_query *ih3;
1108 struct net_bridge_port_group *p; 1122 struct net_bridge_port_group *p;
1109 struct net_bridge_port_group **pp; 1123 struct net_bridge_port_group __rcu **pp;
1110 unsigned long max_delay; 1124 unsigned long max_delay;
1111 unsigned long now = jiffies; 1125 unsigned long now = jiffies;
1112 __be32 group; 1126 __be32 group;
@@ -1145,7 +1159,7 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1145 if (!group) 1159 if (!group)
1146 goto out; 1160 goto out;
1147 1161
1148 mp = br_mdb_ip4_get(br->mdb, group); 1162 mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group);
1149 if (!mp) 1163 if (!mp)
1150 goto out; 1164 goto out;
1151 1165
@@ -1157,7 +1171,9 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1157 try_to_del_timer_sync(&mp->timer) >= 0)) 1171 try_to_del_timer_sync(&mp->timer) >= 0))
1158 mod_timer(&mp->timer, now + max_delay); 1172 mod_timer(&mp->timer, now + max_delay);
1159 1173
1160 for (pp = &mp->ports; (p = *pp); pp = &p->next) { 1174 for (pp = &mp->ports;
1175 (p = mlock_dereference(*pp, br)) != NULL;
1176 pp = &p->next) {
1161 if (timer_pending(&p->timer) ? 1177 if (timer_pending(&p->timer) ?
1162 time_after(p->timer.expires, now + max_delay) : 1178 time_after(p->timer.expires, now + max_delay) :
1163 try_to_del_timer_sync(&p->timer) >= 0) 1179 try_to_del_timer_sync(&p->timer) >= 0)
@@ -1178,7 +1194,8 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1178 struct mld_msg *mld = (struct mld_msg *) icmp6_hdr(skb); 1194 struct mld_msg *mld = (struct mld_msg *) icmp6_hdr(skb);
1179 struct net_bridge_mdb_entry *mp; 1195 struct net_bridge_mdb_entry *mp;
1180 struct mld2_query *mld2q; 1196 struct mld2_query *mld2q;
1181 struct net_bridge_port_group *p, **pp; 1197 struct net_bridge_port_group *p;
1198 struct net_bridge_port_group __rcu **pp;
1182 unsigned long max_delay; 1199 unsigned long max_delay;
1183 unsigned long now = jiffies; 1200 unsigned long now = jiffies;
1184 struct in6_addr *group = NULL; 1201 struct in6_addr *group = NULL;
@@ -1214,7 +1231,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1214 if (!group) 1231 if (!group)
1215 goto out; 1232 goto out;
1216 1233
1217 mp = br_mdb_ip6_get(br->mdb, group); 1234 mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group);
1218 if (!mp) 1235 if (!mp)
1219 goto out; 1236 goto out;
1220 1237
@@ -1225,7 +1242,9 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1225 try_to_del_timer_sync(&mp->timer) >= 0)) 1242 try_to_del_timer_sync(&mp->timer) >= 0))
1226 mod_timer(&mp->timer, now + max_delay); 1243 mod_timer(&mp->timer, now + max_delay);
1227 1244
1228 for (pp = &mp->ports; (p = *pp); pp = &p->next) { 1245 for (pp = &mp->ports;
1246 (p = mlock_dereference(*pp, br)) != NULL;
1247 pp = &p->next) {
1229 if (timer_pending(&p->timer) ? 1248 if (timer_pending(&p->timer) ?
1230 time_after(p->timer.expires, now + max_delay) : 1249 time_after(p->timer.expires, now + max_delay) :
1231 try_to_del_timer_sync(&p->timer) >= 0) 1250 try_to_del_timer_sync(&p->timer) >= 0)
@@ -1254,7 +1273,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
1254 timer_pending(&br->multicast_querier_timer)) 1273 timer_pending(&br->multicast_querier_timer))
1255 goto out; 1274 goto out;
1256 1275
1257 mdb = br->mdb; 1276 mdb = mlock_dereference(br->mdb, br);
1258 mp = br_mdb_ip_get(mdb, group); 1277 mp = br_mdb_ip_get(mdb, group);
1259 if (!mp) 1278 if (!mp)
1260 goto out; 1279 goto out;
@@ -1277,7 +1296,9 @@ static void br_multicast_leave_group(struct net_bridge *br,
1277 goto out; 1296 goto out;
1278 } 1297 }
1279 1298
1280 for (p = mp->ports; p; p = p->next) { 1299 for (p = mlock_dereference(mp->ports, br);
1300 p != NULL;
1301 p = mlock_dereference(p->next, br)) {
1281 if (p->port != port) 1302 if (p->port != port)
1282 continue; 1303 continue;
1283 1304
@@ -1625,7 +1646,7 @@ void br_multicast_stop(struct net_bridge *br)
1625 del_timer_sync(&br->multicast_query_timer); 1646 del_timer_sync(&br->multicast_query_timer);
1626 1647
1627 spin_lock_bh(&br->multicast_lock); 1648 spin_lock_bh(&br->multicast_lock);
1628 mdb = br->mdb; 1649 mdb = mlock_dereference(br->mdb, br);
1629 if (!mdb) 1650 if (!mdb)
1630 goto out; 1651 goto out;
1631 1652
@@ -1729,6 +1750,7 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val)
1729{ 1750{
1730 struct net_bridge_port *port; 1751 struct net_bridge_port *port;
1731 int err = 0; 1752 int err = 0;
1753 struct net_bridge_mdb_htable *mdb;
1732 1754
1733 spin_lock(&br->multicast_lock); 1755 spin_lock(&br->multicast_lock);
1734 if (br->multicast_disabled == !val) 1756 if (br->multicast_disabled == !val)
@@ -1741,15 +1763,16 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val)
1741 if (!netif_running(br->dev)) 1763 if (!netif_running(br->dev))
1742 goto unlock; 1764 goto unlock;
1743 1765
1744 if (br->mdb) { 1766 mdb = mlock_dereference(br->mdb, br);
1745 if (br->mdb->old) { 1767 if (mdb) {
1768 if (mdb->old) {
1746 err = -EEXIST; 1769 err = -EEXIST;
1747rollback: 1770rollback:
1748 br->multicast_disabled = !!val; 1771 br->multicast_disabled = !!val;
1749 goto unlock; 1772 goto unlock;
1750 } 1773 }
1751 1774
1752 err = br_mdb_rehash(&br->mdb, br->mdb->max, 1775 err = br_mdb_rehash(&br->mdb, mdb->max,
1753 br->hash_elasticity); 1776 br->hash_elasticity);
1754 if (err) 1777 if (err)
1755 goto rollback; 1778 goto rollback;
@@ -1774,6 +1797,7 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
1774{ 1797{
1775 int err = -ENOENT; 1798 int err = -ENOENT;
1776 u32 old; 1799 u32 old;
1800 struct net_bridge_mdb_htable *mdb;
1777 1801
1778 spin_lock(&br->multicast_lock); 1802 spin_lock(&br->multicast_lock);
1779 if (!netif_running(br->dev)) 1803 if (!netif_running(br->dev))
@@ -1782,7 +1806,9 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
1782 err = -EINVAL; 1806 err = -EINVAL;
1783 if (!is_power_of_2(val)) 1807 if (!is_power_of_2(val))
1784 goto unlock; 1808 goto unlock;
1785 if (br->mdb && val < br->mdb->size) 1809
1810 mdb = mlock_dereference(br->mdb, br);
1811 if (mdb && val < mdb->size)
1786 goto unlock; 1812 goto unlock;
1787 1813
1788 err = 0; 1814 err = 0;
@@ -1790,8 +1816,8 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val)
1790 old = br->hash_max; 1816 old = br->hash_max;
1791 br->hash_max = val; 1817 br->hash_max = val;
1792 1818
1793 if (br->mdb) { 1819 if (mdb) {
1794 if (br->mdb->old) { 1820 if (mdb->old) {
1795 err = -EEXIST; 1821 err = -EEXIST;
1796rollback: 1822rollback:
1797 br->hash_max = old; 1823 br->hash_max = old;