aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-08-01 02:52:20 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-01 02:52:20 -0400
commit5510b3c2a173921374ec847848fb20b98e1c698a (patch)
treec9e185281ef17280ce0dc30be7923124874736b0 /net/bridge
parent17f901e8915cb922c2ca710835ef34f166f53ee9 (diff)
parent7c764cec3703583247c4ab837c652975a3d41f4b (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: arch/s390/net/bpf_jit_comp.c drivers/net/ethernet/ti/netcp_ethss.c net/bridge/br_multicast.c net/ipv4/ip_fragment.c All four conflicts were cases of simple overlapping changes. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_forward.c29
-rw-r--r--net/bridge/br_mdb.c1
-rw-r--r--net/bridge/br_multicast.c52
-rw-r--r--net/bridge/br_netlink.c10
-rw-r--r--net/bridge/br_stp.c5
-rw-r--r--net/bridge/br_stp_if.c13
-rw-r--r--net/bridge/br_stp_timer.c4
7 files changed, 77 insertions, 37 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 0ff6e1bbca91..fa7bfced888e 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -37,15 +37,30 @@ static inline int should_deliver(const struct net_bridge_port *p,
37 37
38int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb) 38int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb)
39{ 39{
40 if (!is_skb_forwardable(skb->dev, skb)) { 40 if (!is_skb_forwardable(skb->dev, skb))
41 kfree_skb(skb); 41 goto drop;
42 } else { 42
43 skb_push(skb, ETH_HLEN); 43 skb_push(skb, ETH_HLEN);
44 br_drop_fake_rtable(skb); 44 br_drop_fake_rtable(skb);
45 skb_sender_cpu_clear(skb); 45 skb_sender_cpu_clear(skb);
46 dev_queue_xmit(skb); 46
47 if (skb->ip_summed == CHECKSUM_PARTIAL &&
48 (skb->protocol == htons(ETH_P_8021Q) ||
49 skb->protocol == htons(ETH_P_8021AD))) {
50 int depth;
51
52 if (!__vlan_get_protocol(skb, skb->protocol, &depth))
53 goto drop;
54
55 skb_set_network_header(skb, depth);
47 } 56 }
48 57
58 dev_queue_xmit(skb);
59
60 return 0;
61
62drop:
63 kfree_skb(skb);
49 return 0; 64 return 0;
50} 65}
51EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit); 66EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index 5e9d1c5e1194..6a592856da1c 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -519,6 +519,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
519 if (p->port->state == BR_STATE_DISABLED) 519 if (p->port->state == BR_STATE_DISABLED)
520 goto unlock; 520 goto unlock;
521 521
522 entry->state = p->state;
522 rcu_assign_pointer(*pp, p->next); 523 rcu_assign_pointer(*pp, p->next);
523 hlist_del_init(&p->mglist); 524 hlist_del_init(&p->mglist);
524 del_timer(&p->timer); 525 del_timer(&p->timer);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index fd238587e032..0752796fe0ba 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1432,8 +1432,7 @@ br_multicast_leave_group(struct net_bridge *br,
1432 1432
1433 spin_lock(&br->multicast_lock); 1433 spin_lock(&br->multicast_lock);
1434 if (!netif_running(br->dev) || 1434 if (!netif_running(br->dev) ||
1435 (port && port->state == BR_STATE_DISABLED) || 1435 (port && port->state == BR_STATE_DISABLED))
1436 timer_pending(&other_query->timer))
1437 goto out; 1436 goto out;
1438 1437
1439 mdb = mlock_dereference(br->mdb, br); 1438 mdb = mlock_dereference(br->mdb, br);
@@ -1441,6 +1440,32 @@ br_multicast_leave_group(struct net_bridge *br,
1441 if (!mp) 1440 if (!mp)
1442 goto out; 1441 goto out;
1443 1442
1443 if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
1444 struct net_bridge_port_group __rcu **pp;
1445
1446 for (pp = &mp->ports;
1447 (p = mlock_dereference(*pp, br)) != NULL;
1448 pp = &p->next) {
1449 if (p->port != port)
1450 continue;
1451
1452 rcu_assign_pointer(*pp, p->next);
1453 hlist_del_init(&p->mglist);
1454 del_timer(&p->timer);
1455 call_rcu_bh(&p->rcu, br_multicast_free_pg);
1456 br_mdb_notify(br->dev, port, group, RTM_DELMDB,
1457 p->state);
1458
1459 if (!mp->ports && !mp->mglist &&
1460 netif_running(br->dev))
1461 mod_timer(&mp->timer, jiffies);
1462 }
1463 goto out;
1464 }
1465
1466 if (timer_pending(&other_query->timer))
1467 goto out;
1468
1444 if (br->multicast_querier) { 1469 if (br->multicast_querier) {
1445 __br_multicast_send_query(br, port, &mp->addr); 1470 __br_multicast_send_query(br, port, &mp->addr);
1446 1471
@@ -1466,29 +1491,6 @@ br_multicast_leave_group(struct net_bridge *br,
1466 } 1491 }
1467 } 1492 }
1468 1493
1469 if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
1470 struct net_bridge_port_group __rcu **pp;
1471
1472 for (pp = &mp->ports;
1473 (p = mlock_dereference(*pp, br)) != NULL;
1474 pp = &p->next) {
1475 if (p->port != port)
1476 continue;
1477
1478 rcu_assign_pointer(*pp, p->next);
1479 hlist_del_init(&p->mglist);
1480 del_timer(&p->timer);
1481 br_mdb_notify(br->dev, port, group, RTM_DELMDB,
1482 p->state);
1483 call_rcu_bh(&p->rcu, br_multicast_free_pg);
1484
1485 if (!mp->ports && !mp->mglist &&
1486 netif_running(br->dev))
1487 mod_timer(&mp->timer, jiffies);
1488 }
1489 goto out;
1490 }
1491
1492 now = jiffies; 1494 now = jiffies;
1493 time = now + br->multicast_last_member_count * 1495 time = now + br->multicast_last_member_count *
1494 br->multicast_last_member_interval; 1496 br->multicast_last_member_interval;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 793d247ac2ca..91a2e08c2bb8 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -691,9 +691,17 @@ static int br_port_slave_changelink(struct net_device *brdev,
691 struct nlattr *tb[], 691 struct nlattr *tb[],
692 struct nlattr *data[]) 692 struct nlattr *data[])
693{ 693{
694 struct net_bridge *br = netdev_priv(brdev);
695 int ret;
696
694 if (!data) 697 if (!data)
695 return 0; 698 return 0;
696 return br_setport(br_port_get_rtnl(dev), data); 699
700 spin_lock_bh(&br->lock);
701 ret = br_setport(br_port_get_rtnl(dev), data);
702 spin_unlock_bh(&br->lock);
703
704 return ret;
697} 705}
698 706
699static int br_port_fill_slave_info(struct sk_buff *skb, 707static int br_port_fill_slave_info(struct sk_buff *skb,
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index b4b6dab9c285..ed74ffaa851f 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -209,8 +209,9 @@ void br_transmit_config(struct net_bridge_port *p)
209 br_send_config_bpdu(p, &bpdu); 209 br_send_config_bpdu(p, &bpdu);
210 p->topology_change_ack = 0; 210 p->topology_change_ack = 0;
211 p->config_pending = 0; 211 p->config_pending = 0;
212 mod_timer(&p->hold_timer, 212 if (p->br->stp_enabled == BR_KERNEL_STP)
213 round_jiffies(jiffies + BR_HOLD_TIME)); 213 mod_timer(&p->hold_timer,
214 round_jiffies(jiffies + BR_HOLD_TIME));
214 } 215 }
215} 216}
216 217
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index a2730e7196cd..4ca449a16132 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -48,7 +48,8 @@ void br_stp_enable_bridge(struct net_bridge *br)
48 struct net_bridge_port *p; 48 struct net_bridge_port *p;
49 49
50 spin_lock_bh(&br->lock); 50 spin_lock_bh(&br->lock);
51 mod_timer(&br->hello_timer, jiffies + br->hello_time); 51 if (br->stp_enabled == BR_KERNEL_STP)
52 mod_timer(&br->hello_timer, jiffies + br->hello_time);
52 mod_timer(&br->gc_timer, jiffies + HZ/10); 53 mod_timer(&br->gc_timer, jiffies + HZ/10);
53 54
54 br_config_bpdu_generation(br); 55 br_config_bpdu_generation(br);
@@ -127,6 +128,7 @@ static void br_stp_start(struct net_bridge *br)
127 int r; 128 int r;
128 char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL }; 129 char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
129 char *envp[] = { NULL }; 130 char *envp[] = { NULL };
131 struct net_bridge_port *p;
130 132
131 r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); 133 r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
132 134
@@ -140,6 +142,10 @@ static void br_stp_start(struct net_bridge *br)
140 if (r == 0) { 142 if (r == 0) {
141 br->stp_enabled = BR_USER_STP; 143 br->stp_enabled = BR_USER_STP;
142 br_debug(br, "userspace STP started\n"); 144 br_debug(br, "userspace STP started\n");
145 /* Stop hello and hold timers */
146 del_timer(&br->hello_timer);
147 list_for_each_entry(p, &br->port_list, list)
148 del_timer(&p->hold_timer);
143 } else { 149 } else {
144 br->stp_enabled = BR_KERNEL_STP; 150 br->stp_enabled = BR_KERNEL_STP;
145 br_debug(br, "using kernel STP\n"); 151 br_debug(br, "using kernel STP\n");
@@ -156,12 +162,17 @@ static void br_stp_stop(struct net_bridge *br)
156 int r; 162 int r;
157 char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL }; 163 char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL };
158 char *envp[] = { NULL }; 164 char *envp[] = { NULL };
165 struct net_bridge_port *p;
159 166
160 if (br->stp_enabled == BR_USER_STP) { 167 if (br->stp_enabled == BR_USER_STP) {
161 r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); 168 r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
162 br_info(br, "userspace STP stopped, return code %d\n", r); 169 br_info(br, "userspace STP stopped, return code %d\n", r);
163 170
164 /* To start timers on any ports left in blocking */ 171 /* To start timers on any ports left in blocking */
172 mod_timer(&br->hello_timer, jiffies + br->hello_time);
173 list_for_each_entry(p, &br->port_list, list)
174 mod_timer(&p->hold_timer,
175 round_jiffies(jiffies + BR_HOLD_TIME));
165 spin_lock_bh(&br->lock); 176 spin_lock_bh(&br->lock);
166 br_port_state_selection(br); 177 br_port_state_selection(br);
167 spin_unlock_bh(&br->lock); 178 spin_unlock_bh(&br->lock);
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 7caf7fae2d5b..5f0f5af0ec35 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -40,7 +40,9 @@ static void br_hello_timer_expired(unsigned long arg)
40 if (br->dev->flags & IFF_UP) { 40 if (br->dev->flags & IFF_UP) {
41 br_config_bpdu_generation(br); 41 br_config_bpdu_generation(br);
42 42
43 mod_timer(&br->hello_timer, round_jiffies(jiffies + br->hello_time)); 43 if (br->stp_enabled != BR_USER_STP)
44 mod_timer(&br->hello_timer,
45 round_jiffies(jiffies + br->hello_time));
44 } 46 }
45 spin_unlock(&br->lock); 47 spin_unlock(&br->lock);
46} 48}