aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_input.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-03-21 16:42:06 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:28:45 -0400
commit467aea0ddfd1f0f1158c57cbef0e8941dd63374c (patch)
treeb5bcccfd80d189a67cd347940ceee916a8d5cf22 /net/bridge/br_input.c
parent6229e362dd49b9e8387126bd4483ab0574d23e9c (diff)
bridge: don't route packets while learning
While in the STP learning state, don't route packets; wait until forwarding delay has expired. The purpose of the forwarding delay is to detect loops in the network, and if a brouter started up and started forwarding, it could cause a flood. Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Diffstat (limited to 'net/bridge/br_input.c')
-rw-r--r--net/bridge/br_input.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 2f5c379d9ffa..8a5527632092 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -129,7 +129,7 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
129 const unsigned char *dest = eth_hdr(skb)->h_dest; 129 const unsigned char *dest = eth_hdr(skb)->h_dest;
130 130
131 if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) 131 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
132 goto err; 132 goto drop;
133 133
134 if (unlikely(is_link_local(dest))) { 134 if (unlikely(is_link_local(dest))) {
135 skb->pkt_type = PACKET_HOST; 135 skb->pkt_type = PACKET_HOST;
@@ -138,22 +138,25 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
138 NULL, br_handle_local_finish) == 0) ? skb : NULL; 138 NULL, br_handle_local_finish) == 0) ? skb : NULL;
139 } 139 }
140 140
141 if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) { 141 switch (p->state) {
142 case BR_STATE_FORWARDING:
143
142 if (br_should_route_hook) { 144 if (br_should_route_hook) {
143 if (br_should_route_hook(&skb)) 145 if (br_should_route_hook(&skb))
144 return skb; 146 return skb;
145 dest = eth_hdr(skb)->h_dest; 147 dest = eth_hdr(skb)->h_dest;
146 } 148 }
147 149 /* fall through */
150 case BR_STATE_LEARNING:
148 if (!compare_ether_addr(p->br->dev->dev_addr, dest)) 151 if (!compare_ether_addr(p->br->dev->dev_addr, dest))
149 skb->pkt_type = PACKET_HOST; 152 skb->pkt_type = PACKET_HOST;
150 153
151 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, 154 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
152 br_handle_frame_finish); 155 br_handle_frame_finish);
153 return NULL; 156 break;
157 default:
158drop:
159 kfree_skb(skb);
154 } 160 }
155
156err:
157 kfree_skb(skb);
158 return NULL; 161 return NULL;
159} 162}