diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-03-21 16:42:06 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 01:28:45 -0400 |
commit | 467aea0ddfd1f0f1158c57cbef0e8941dd63374c (patch) | |
tree | b5bcccfd80d189a67cd347940ceee916a8d5cf22 /net/bridge/br_input.c | |
parent | 6229e362dd49b9e8387126bd4483ab0574d23e9c (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.c | 17 |
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: | ||
158 | drop: | ||
159 | kfree_skb(skb); | ||
154 | } | 160 | } |
155 | |||
156 | err: | ||
157 | kfree_skb(skb); | ||
158 | return NULL; | 161 | return NULL; |
159 | } | 162 | } |