br_multicast.c (eb1d16414339a6e113d89e2cca2556005d7ce919) br_multicast.c (0909e11758bd28848aeb6646e021ec1e031a3f0f)
1/*
2 * Bridge multicast support.
3 *
4 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)

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

741 err = br_multicast_add_group(br, port, group);
742 if (err)
743 break;
744 }
745
746 return err;
747}
748
1/*
2 * Bridge multicast support.
3 *
4 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)

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

741 err = br_multicast_add_group(br, port, group);
742 if (err)
743 break;
744 }
745
746 return err;
747}
748
749static void br_multicast_add_router(struct net_bridge *br,
750 struct net_bridge_port *port)
751{
752 struct hlist_node *p;
753 struct hlist_node **h;
754
755 for (h = &br->router_list.first;
756 (p = *h) &&
757 (unsigned long)container_of(p, struct net_bridge_port, rlist) >
758 (unsigned long)port;
759 h = &p->next)
760 ;
761
762 port->rlist.pprev = h;
763 port->rlist.next = p;
764 rcu_assign_pointer(*h, &port->rlist);
765 if (p)
766 p->pprev = &port->rlist.next;
767}
768
749static void br_multicast_mark_router(struct net_bridge *br,
750 struct net_bridge_port *port)
751{
752 unsigned long now = jiffies;
769static void br_multicast_mark_router(struct net_bridge *br,
770 struct net_bridge_port *port)
771{
772 unsigned long now = jiffies;
753 struct hlist_node *p;
754 struct hlist_node **h;
755
756 if (!port) {
757 if (br->multicast_router == 1)
758 mod_timer(&br->multicast_router_timer,
759 now + br->multicast_querier_interval);
760 return;
761 }
762
763 if (port->multicast_router != 1)
764 return;
765
766 if (!hlist_unhashed(&port->rlist))
767 goto timer;
768
773
774 if (!port) {
775 if (br->multicast_router == 1)
776 mod_timer(&br->multicast_router_timer,
777 now + br->multicast_querier_interval);
778 return;
779 }
780
781 if (port->multicast_router != 1)
782 return;
783
784 if (!hlist_unhashed(&port->rlist))
785 goto timer;
786
769 for (h = &br->router_list.first;
770 (p = *h) &&
771 (unsigned long)container_of(p, struct net_bridge_port, rlist) >
772 (unsigned long)port;
773 h = &p->next)
774 ;
787 br_multicast_add_router(br, port);
775
788
776 port->rlist.pprev = h;
777 port->rlist.next = p;
778 rcu_assign_pointer(*h, &port->rlist);
779 if (p)
780 p->pprev = &port->rlist.next;
781
782timer:
783 mod_timer(&port->multicast_router_timer,
784 now + br->multicast_querier_interval);
785}
786
787static void br_multicast_query_received(struct net_bridge *br,
788 struct net_bridge_port *port,
789 __be32 saddr)

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

1128 }
1129
1130 mdb->old = mdb;
1131 call_rcu_bh(&mdb->rcu, br_mdb_free);
1132
1133out:
1134 spin_unlock_bh(&br->multicast_lock);
1135}
789timer:
790 mod_timer(&port->multicast_router_timer,
791 now + br->multicast_querier_interval);
792}
793
794static void br_multicast_query_received(struct net_bridge *br,
795 struct net_bridge_port *port,
796 __be32 saddr)

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

1135 }
1136
1137 mdb->old = mdb;
1138 call_rcu_bh(&mdb->rcu, br_mdb_free);
1139
1140out:
1141 spin_unlock_bh(&br->multicast_lock);
1142}
1143
1144int br_multicast_set_router(struct net_bridge *br, unsigned long val)
1145{
1146 int err = -ENOENT;
1147
1148 spin_lock_bh(&br->multicast_lock);
1149 if (!netif_running(br->dev))
1150 goto unlock;
1151
1152 switch (val) {
1153 case 0:
1154 case 2:
1155 del_timer(&br->multicast_router_timer);
1156 /* fall through */
1157 case 1:
1158 br->multicast_router = val;
1159 err = 0;
1160 break;
1161
1162 default:
1163 err = -EINVAL;
1164 break;
1165 }
1166
1167unlock:
1168 spin_unlock_bh(&br->multicast_lock);
1169
1170 return err;
1171}
1172
1173int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val)
1174{
1175 struct net_bridge *br = p->br;
1176 int err = -ENOENT;
1177
1178 spin_lock(&br->multicast_lock);
1179 if (!netif_running(br->dev) || p->state == BR_STATE_DISABLED)
1180 goto unlock;
1181
1182 switch (val) {
1183 case 0:
1184 case 1:
1185 case 2:
1186 p->multicast_router = val;
1187 err = 0;
1188
1189 if (val < 2 && !hlist_unhashed(&p->rlist))
1190 hlist_del_init_rcu(&p->rlist);
1191
1192 if (val == 1)
1193 break;
1194
1195 del_timer(&p->multicast_router_timer);
1196
1197 if (val == 0)
1198 break;
1199
1200 br_multicast_add_router(br, p);
1201 break;
1202
1203 default:
1204 err = -EINVAL;
1205 break;
1206 }
1207
1208unlock:
1209 spin_unlock(&br->multicast_lock);
1210
1211 return err;
1212}