aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2010-04-17 23:42:07 -0400
committerYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2010-04-23 00:35:55 -0400
commit8ef2a9a59854994bace13b5c4f7edc2c8d4d124e (patch)
treeef123540d1bb398ec1c6cc9b713425e1da8b5f04 /net
parent6e7cb8370760ec17e10098399822292def8d84f3 (diff)
bridge br_multicast: Make functions less ipv4 dependent.
Introduce struct br_ip{} to store ip address and protocol and make functions more generic so that we can support both IPv4 and IPv6 with less pain. Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_multicast.c197
-rw-r--r--net/bridge/br_private.h12
2 files changed, 151 insertions, 58 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 81bfdfe14ce5..64a3e4f74348 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -27,48 +27,86 @@
27 27
28#include "br_private.h" 28#include "br_private.h"
29 29
30static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb, __be32 ip) 30static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
31{
32 if (a->proto != b->proto)
33 return 0;
34 switch (a->proto) {
35 case htons(ETH_P_IP):
36 return a->u.ip4 == b->u.ip4;
37 }
38 return 0;
39}
40
41static inline int __br_ip4_hash(struct net_bridge_mdb_htable *mdb, __be32 ip)
31{ 42{
32 return jhash_1word(mdb->secret, (__force u32)ip) & (mdb->max - 1); 43 return jhash_1word(mdb->secret, (__force u32)ip) & (mdb->max - 1);
33} 44}
34 45
46static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb,
47 struct br_ip *ip)
48{
49 switch (ip->proto) {
50 case htons(ETH_P_IP):
51 return __br_ip4_hash(mdb, ip->u.ip4);
52 }
53 return 0;
54}
55
35static struct net_bridge_mdb_entry *__br_mdb_ip_get( 56static struct net_bridge_mdb_entry *__br_mdb_ip_get(
36 struct net_bridge_mdb_htable *mdb, __be32 dst, int hash) 57 struct net_bridge_mdb_htable *mdb, struct br_ip *dst, int hash)
37{ 58{
38 struct net_bridge_mdb_entry *mp; 59 struct net_bridge_mdb_entry *mp;
39 struct hlist_node *p; 60 struct hlist_node *p;
40 61
41 hlist_for_each_entry_rcu(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { 62 hlist_for_each_entry_rcu(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) {
42 if (dst == mp->addr) 63 if (br_ip_equal(&mp->addr, dst))
43 return mp; 64 return mp;
44 } 65 }
45 66
46 return NULL; 67 return NULL;
47} 68}
48 69
49static struct net_bridge_mdb_entry *br_mdb_ip_get( 70static struct net_bridge_mdb_entry *br_mdb_ip4_get(
50 struct net_bridge_mdb_htable *mdb, __be32 dst) 71 struct net_bridge_mdb_htable *mdb, __be32 dst)
51{ 72{
52 if (!mdb) 73 struct br_ip br_dst;
53 return NULL; 74
75 br_dst.u.ip4 = dst;
76 br_dst.proto = htons(ETH_P_IP);
54 77
78 return __br_mdb_ip_get(mdb, &br_dst, __br_ip4_hash(mdb, dst));
79}
80
81static struct net_bridge_mdb_entry *br_mdb_ip_get(
82 struct net_bridge_mdb_htable *mdb, struct br_ip *dst)
83{
55 return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst)); 84 return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst));
56} 85}
57 86
58struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, 87struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
59 struct sk_buff *skb) 88 struct sk_buff *skb)
60{ 89{
61 if (br->multicast_disabled) 90 struct net_bridge_mdb_htable *mdb = br->mdb;
91 struct br_ip ip;
92
93 if (!mdb || br->multicast_disabled)
94 return NULL;
95
96 if (BR_INPUT_SKB_CB(skb)->igmp)
62 return NULL; 97 return NULL;
63 98
99 ip.proto = skb->protocol;
100
64 switch (skb->protocol) { 101 switch (skb->protocol) {
65 case htons(ETH_P_IP): 102 case htons(ETH_P_IP):
66 if (BR_INPUT_SKB_CB(skb)->igmp) 103 ip.u.ip4 = ip_hdr(skb)->daddr;
67 break; 104 break;
68 return br_mdb_ip_get(br->mdb, ip_hdr(skb)->daddr); 105 default:
106 return NULL;
69 } 107 }
70 108
71 return NULL; 109 return br_mdb_ip_get(mdb, &ip);
72} 110}
73 111
74static void br_mdb_free(struct rcu_head *head) 112static void br_mdb_free(struct rcu_head *head)
@@ -95,7 +133,7 @@ static int br_mdb_copy(struct net_bridge_mdb_htable *new,
95 for (i = 0; i < old->max; i++) 133 for (i = 0; i < old->max; i++)
96 hlist_for_each_entry(mp, p, &old->mhash[i], hlist[old->ver]) 134 hlist_for_each_entry(mp, p, &old->mhash[i], hlist[old->ver])
97 hlist_add_head(&mp->hlist[new->ver], 135 hlist_add_head(&mp->hlist[new->ver],
98 &new->mhash[br_ip_hash(new, mp->addr)]); 136 &new->mhash[br_ip_hash(new, &mp->addr)]);
99 137
100 if (!elasticity) 138 if (!elasticity)
101 return 0; 139 return 0;
@@ -163,7 +201,7 @@ static void br_multicast_del_pg(struct net_bridge *br,
163 struct net_bridge_port_group *p; 201 struct net_bridge_port_group *p;
164 struct net_bridge_port_group **pp; 202 struct net_bridge_port_group **pp;
165 203
166 mp = br_mdb_ip_get(mdb, pg->addr); 204 mp = br_mdb_ip_get(mdb, &pg->addr);
167 if (WARN_ON(!mp)) 205 if (WARN_ON(!mp))
168 return; 206 return;
169 207
@@ -249,8 +287,8 @@ out:
249 return 0; 287 return 0;
250} 288}
251 289
252static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, 290static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br,
253 __be32 group) 291 __be32 group)
254{ 292{
255 struct sk_buff *skb; 293 struct sk_buff *skb;
256 struct igmphdr *ih; 294 struct igmphdr *ih;
@@ -314,12 +352,22 @@ out:
314 return skb; 352 return skb;
315} 353}
316 354
355static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
356 struct br_ip *addr)
357{
358 switch (addr->proto) {
359 case htons(ETH_P_IP):
360 return br_ip4_multicast_alloc_query(br, addr->u.ip4);
361 }
362 return NULL;
363}
364
317static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) 365static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp)
318{ 366{
319 struct net_bridge *br = mp->br; 367 struct net_bridge *br = mp->br;
320 struct sk_buff *skb; 368 struct sk_buff *skb;
321 369
322 skb = br_multicast_alloc_query(br, mp->addr); 370 skb = br_multicast_alloc_query(br, &mp->addr);
323 if (!skb) 371 if (!skb)
324 goto timer; 372 goto timer;
325 373
@@ -353,7 +401,7 @@ static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg)
353 struct net_bridge *br = port->br; 401 struct net_bridge *br = port->br;
354 struct sk_buff *skb; 402 struct sk_buff *skb;
355 403
356 skb = br_multicast_alloc_query(br, pg->addr); 404 skb = br_multicast_alloc_query(br, &pg->addr);
357 if (!skb) 405 if (!skb)
358 goto timer; 406 goto timer;
359 407
@@ -383,8 +431,8 @@ out:
383} 431}
384 432
385static struct net_bridge_mdb_entry *br_multicast_get_group( 433static struct net_bridge_mdb_entry *br_multicast_get_group(
386 struct net_bridge *br, struct net_bridge_port *port, __be32 group, 434 struct net_bridge *br, struct net_bridge_port *port,
387 int hash) 435 struct br_ip *group, int hash)
388{ 436{
389 struct net_bridge_mdb_htable *mdb = br->mdb; 437 struct net_bridge_mdb_htable *mdb = br->mdb;
390 struct net_bridge_mdb_entry *mp; 438 struct net_bridge_mdb_entry *mp;
@@ -396,9 +444,8 @@ static struct net_bridge_mdb_entry *br_multicast_get_group(
396 444
397 hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) { 445 hlist_for_each_entry(mp, p, &mdb->mhash[hash], hlist[mdb->ver]) {
398 count++; 446 count++;
399 if (unlikely(group == mp->addr)) { 447 if (unlikely(br_ip_equal(group, &mp->addr)))
400 return mp; 448 return mp;
401 }
402 } 449 }
403 450
404 elasticity = 0; 451 elasticity = 0;
@@ -463,7 +510,8 @@ err:
463} 510}
464 511
465static struct net_bridge_mdb_entry *br_multicast_new_group( 512static struct net_bridge_mdb_entry *br_multicast_new_group(
466 struct net_bridge *br, struct net_bridge_port *port, __be32 group) 513 struct net_bridge *br, struct net_bridge_port *port,
514 struct br_ip *group)
467{ 515{
468 struct net_bridge_mdb_htable *mdb = br->mdb; 516 struct net_bridge_mdb_htable *mdb = br->mdb;
469 struct net_bridge_mdb_entry *mp; 517 struct net_bridge_mdb_entry *mp;
@@ -496,7 +544,7 @@ rehash:
496 goto out; 544 goto out;
497 545
498 mp->br = br; 546 mp->br = br;
499 mp->addr = group; 547 mp->addr = *group;
500 setup_timer(&mp->timer, br_multicast_group_expired, 548 setup_timer(&mp->timer, br_multicast_group_expired,
501 (unsigned long)mp); 549 (unsigned long)mp);
502 setup_timer(&mp->query_timer, br_multicast_group_query_expired, 550 setup_timer(&mp->query_timer, br_multicast_group_query_expired,
@@ -510,7 +558,8 @@ out:
510} 558}
511 559
512static int br_multicast_add_group(struct net_bridge *br, 560static int br_multicast_add_group(struct net_bridge *br,
513 struct net_bridge_port *port, __be32 group) 561 struct net_bridge_port *port,
562 struct br_ip *group)
514{ 563{
515 struct net_bridge_mdb_entry *mp; 564 struct net_bridge_mdb_entry *mp;
516 struct net_bridge_port_group *p; 565 struct net_bridge_port_group *p;
@@ -518,9 +567,6 @@ static int br_multicast_add_group(struct net_bridge *br,
518 unsigned long now = jiffies; 567 unsigned long now = jiffies;
519 int err; 568 int err;
520 569
521 if (ipv4_is_local_multicast(group))
522 return 0;
523
524 spin_lock(&br->multicast_lock); 570 spin_lock(&br->multicast_lock);
525 if (!netif_running(br->dev) || 571 if (!netif_running(br->dev) ||
526 (port && port->state == BR_STATE_DISABLED)) 572 (port && port->state == BR_STATE_DISABLED))
@@ -549,7 +595,7 @@ static int br_multicast_add_group(struct net_bridge *br,
549 if (unlikely(!p)) 595 if (unlikely(!p))
550 goto err; 596 goto err;
551 597
552 p->addr = group; 598 p->addr = *group;
553 p->port = port; 599 p->port = port;
554 p->next = *pp; 600 p->next = *pp;
555 hlist_add_head(&p->mglist, &port->mglist); 601 hlist_add_head(&p->mglist, &port->mglist);
@@ -570,6 +616,21 @@ err:
570 return err; 616 return err;
571} 617}
572 618
619static int br_ip4_multicast_add_group(struct net_bridge *br,
620 struct net_bridge_port *port,
621 __be32 group)
622{
623 struct br_ip br_group;
624
625 if (ipv4_is_local_multicast(group))
626 return 0;
627
628 br_group.u.ip4 = group;
629 br_group.proto = htons(ETH_P_IP);
630
631 return br_multicast_add_group(br, port, &br_group);
632}
633
573static void br_multicast_router_expired(unsigned long data) 634static void br_multicast_router_expired(unsigned long data)
574{ 635{
575 struct net_bridge_port *port = (void *)data; 636 struct net_bridge_port *port = (void *)data;
@@ -591,19 +652,15 @@ static void br_multicast_local_router_expired(unsigned long data)
591{ 652{
592} 653}
593 654
594static void br_multicast_send_query(struct net_bridge *br, 655static void __br_multicast_send_query(struct net_bridge *br,
595 struct net_bridge_port *port, u32 sent) 656 struct net_bridge_port *port,
657 struct br_ip *ip)
596{ 658{
597 unsigned long time;
598 struct sk_buff *skb; 659 struct sk_buff *skb;
599 660
600 if (!netif_running(br->dev) || br->multicast_disabled || 661 skb = br_multicast_alloc_query(br, ip);
601 timer_pending(&br->multicast_querier_timer))
602 return;
603
604 skb = br_multicast_alloc_query(br, 0);
605 if (!skb) 662 if (!skb)
606 goto timer; 663 return;
607 664
608 if (port) { 665 if (port) {
609 __skb_push(skb, sizeof(struct ethhdr)); 666 __skb_push(skb, sizeof(struct ethhdr));
@@ -612,8 +669,23 @@ static void br_multicast_send_query(struct net_bridge *br,
612 dev_queue_xmit); 669 dev_queue_xmit);
613 } else 670 } else
614 netif_rx(skb); 671 netif_rx(skb);
672}
673
674static void br_multicast_send_query(struct net_bridge *br,
675 struct net_bridge_port *port, u32 sent)
676{
677 unsigned long time;
678 struct br_ip br_group;
679
680 if (!netif_running(br->dev) || br->multicast_disabled ||
681 timer_pending(&br->multicast_querier_timer))
682 return;
683
684 br_group.u.ip4 = 0;
685 br_group.proto = htons(ETH_P_IP);
686
687 __br_multicast_send_query(br, port, &br_group);
615 688
616timer:
617 time = jiffies; 689 time = jiffies;
618 time += sent < br->multicast_startup_query_count ? 690 time += sent < br->multicast_startup_query_count ?
619 br->multicast_startup_query_interval : 691 br->multicast_startup_query_interval :
@@ -698,9 +770,9 @@ void br_multicast_disable_port(struct net_bridge_port *port)
698 spin_unlock(&br->multicast_lock); 770 spin_unlock(&br->multicast_lock);
699} 771}
700 772
701static int br_multicast_igmp3_report(struct net_bridge *br, 773static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
702 struct net_bridge_port *port, 774 struct net_bridge_port *port,
703 struct sk_buff *skb) 775 struct sk_buff *skb)
704{ 776{
705 struct igmpv3_report *ih; 777 struct igmpv3_report *ih;
706 struct igmpv3_grec *grec; 778 struct igmpv3_grec *grec;
@@ -745,7 +817,7 @@ static int br_multicast_igmp3_report(struct net_bridge *br,
745 continue; 817 continue;
746 } 818 }
747 819
748 err = br_multicast_add_group(br, port, group); 820 err = br_ip4_multicast_add_group(br, port, group);
749 if (err) 821 if (err)
750 break; 822 break;
751 } 823 }
@@ -800,7 +872,7 @@ timer:
800 872
801static void br_multicast_query_received(struct net_bridge *br, 873static void br_multicast_query_received(struct net_bridge *br,
802 struct net_bridge_port *port, 874 struct net_bridge_port *port,
803 __be32 saddr) 875 int saddr)
804{ 876{
805 if (saddr) 877 if (saddr)
806 mod_timer(&br->multicast_querier_timer, 878 mod_timer(&br->multicast_querier_timer,
@@ -811,9 +883,9 @@ static void br_multicast_query_received(struct net_bridge *br,
811 br_multicast_mark_router(br, port); 883 br_multicast_mark_router(br, port);
812} 884}
813 885
814static int br_multicast_query(struct net_bridge *br, 886static int br_ip4_multicast_query(struct net_bridge *br,
815 struct net_bridge_port *port, 887 struct net_bridge_port *port,
816 struct sk_buff *skb) 888 struct sk_buff *skb)
817{ 889{
818 struct iphdr *iph = ip_hdr(skb); 890 struct iphdr *iph = ip_hdr(skb);
819 struct igmphdr *ih = igmp_hdr(skb); 891 struct igmphdr *ih = igmp_hdr(skb);
@@ -831,7 +903,7 @@ static int br_multicast_query(struct net_bridge *br,
831 (port && port->state == BR_STATE_DISABLED)) 903 (port && port->state == BR_STATE_DISABLED))
832 goto out; 904 goto out;
833 905
834 br_multicast_query_received(br, port, iph->saddr); 906 br_multicast_query_received(br, port, !!iph->saddr);
835 907
836 group = ih->group; 908 group = ih->group;
837 909
@@ -859,7 +931,7 @@ static int br_multicast_query(struct net_bridge *br,
859 if (!group) 931 if (!group)
860 goto out; 932 goto out;
861 933
862 mp = br_mdb_ip_get(br->mdb, group); 934 mp = br_mdb_ip4_get(br->mdb, group);
863 if (!mp) 935 if (!mp)
864 goto out; 936 goto out;
865 937
@@ -885,7 +957,7 @@ out:
885 957
886static void br_multicast_leave_group(struct net_bridge *br, 958static void br_multicast_leave_group(struct net_bridge *br,
887 struct net_bridge_port *port, 959 struct net_bridge_port *port,
888 __be32 group) 960 struct br_ip *group)
889{ 961{
890 struct net_bridge_mdb_htable *mdb; 962 struct net_bridge_mdb_htable *mdb;
891 struct net_bridge_mdb_entry *mp; 963 struct net_bridge_mdb_entry *mp;
@@ -893,9 +965,6 @@ static void br_multicast_leave_group(struct net_bridge *br,
893 unsigned long now; 965 unsigned long now;
894 unsigned long time; 966 unsigned long time;
895 967
896 if (ipv4_is_local_multicast(group))
897 return;
898
899 spin_lock(&br->multicast_lock); 968 spin_lock(&br->multicast_lock);
900 if (!netif_running(br->dev) || 969 if (!netif_running(br->dev) ||
901 (port && port->state == BR_STATE_DISABLED) || 970 (port && port->state == BR_STATE_DISABLED) ||
@@ -946,6 +1015,22 @@ out:
946 spin_unlock(&br->multicast_lock); 1015 spin_unlock(&br->multicast_lock);
947} 1016}
948 1017
1018static void br_ip4_multicast_leave_group(struct net_bridge *br,
1019 struct net_bridge_port *port,
1020 __be32 group)
1021{
1022 struct br_ip br_group;
1023
1024 if (ipv4_is_local_multicast(group))
1025 return;
1026
1027 br_group.u.ip4 = group;
1028 br_group.proto = htons(ETH_P_IP);
1029
1030 br_multicast_leave_group(br, port, &br_group);
1031}
1032
1033
949static int br_multicast_ipv4_rcv(struct net_bridge *br, 1034static int br_multicast_ipv4_rcv(struct net_bridge *br,
950 struct net_bridge_port *port, 1035 struct net_bridge_port *port,
951 struct sk_buff *skb) 1036 struct sk_buff *skb)
@@ -1023,16 +1108,16 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
1023 case IGMP_HOST_MEMBERSHIP_REPORT: 1108 case IGMP_HOST_MEMBERSHIP_REPORT:
1024 case IGMPV2_HOST_MEMBERSHIP_REPORT: 1109 case IGMPV2_HOST_MEMBERSHIP_REPORT:
1025 BR_INPUT_SKB_CB(skb2)->mrouters_only = 1; 1110 BR_INPUT_SKB_CB(skb2)->mrouters_only = 1;
1026 err = br_multicast_add_group(br, port, ih->group); 1111 err = br_ip4_multicast_add_group(br, port, ih->group);
1027 break; 1112 break;
1028 case IGMPV3_HOST_MEMBERSHIP_REPORT: 1113 case IGMPV3_HOST_MEMBERSHIP_REPORT:
1029 err = br_multicast_igmp3_report(br, port, skb2); 1114 err = br_ip4_multicast_igmp3_report(br, port, skb2);
1030 break; 1115 break;
1031 case IGMP_HOST_MEMBERSHIP_QUERY: 1116 case IGMP_HOST_MEMBERSHIP_QUERY:
1032 err = br_multicast_query(br, port, skb2); 1117 err = br_ip4_multicast_query(br, port, skb2);
1033 break; 1118 break;
1034 case IGMP_HOST_LEAVE_MESSAGE: 1119 case IGMP_HOST_LEAVE_MESSAGE:
1035 br_multicast_leave_group(br, port, ih->group); 1120 br_ip4_multicast_leave_group(br, port, ih->group);
1036 break; 1121 break;
1037 } 1122 }
1038 1123
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 63181e4a2a67..45d11e49fbbb 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -45,6 +45,14 @@ struct mac_addr
45 unsigned char addr[6]; 45 unsigned char addr[6];
46}; 46};
47 47
48struct br_ip
49{
50 union {
51 __be32 ip4;
52 } u;
53 __be16 proto;
54};
55
48struct net_bridge_fdb_entry 56struct net_bridge_fdb_entry
49{ 57{
50 struct hlist_node hlist; 58 struct hlist_node hlist;
@@ -64,7 +72,7 @@ struct net_bridge_port_group {
64 struct rcu_head rcu; 72 struct rcu_head rcu;
65 struct timer_list timer; 73 struct timer_list timer;
66 struct timer_list query_timer; 74 struct timer_list query_timer;
67 __be32 addr; 75 struct br_ip addr;
68 u32 queries_sent; 76 u32 queries_sent;
69}; 77};
70 78
@@ -77,7 +85,7 @@ struct net_bridge_mdb_entry
77 struct rcu_head rcu; 85 struct rcu_head rcu;
78 struct timer_list timer; 86 struct timer_list timer;
79 struct timer_list query_timer; 87 struct timer_list query_timer;
80 __be32 addr; 88 struct br_ip addr;
81 u32 queries_sent; 89 u32 queries_sent;
82}; 90};
83 91