diff options
-rw-r--r-- | net/bridge/br_forward.c | 33 | ||||
-rw-r--r-- | net/bridge/br_input.c | 5 | ||||
-rw-r--r-- | net/bridge/br_private.h | 3 |
3 files changed, 25 insertions, 16 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index bc1704ac6cd9..6cd50c6e57cf 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -105,8 +105,9 @@ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | |||
105 | 105 | ||
106 | /* called under bridge lock */ | 106 | /* called under bridge lock */ |
107 | static void br_flood(struct net_bridge *br, struct sk_buff *skb, | 107 | static void br_flood(struct net_bridge *br, struct sk_buff *skb, |
108 | void (*__packet_hook)(const struct net_bridge_port *p, | 108 | struct sk_buff *skb0, |
109 | struct sk_buff *skb)) | 109 | void (*__packet_hook)(const struct net_bridge_port *p, |
110 | struct sk_buff *skb)) | ||
110 | { | 111 | { |
111 | struct net_bridge_port *p; | 112 | struct net_bridge_port *p; |
112 | struct net_bridge_port *prev; | 113 | struct net_bridge_port *prev; |
@@ -120,8 +121,7 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, | |||
120 | 121 | ||
121 | if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { | 122 | if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) { |
122 | br->dev->stats.tx_dropped++; | 123 | br->dev->stats.tx_dropped++; |
123 | kfree_skb(skb); | 124 | goto out; |
124 | return; | ||
125 | } | 125 | } |
126 | 126 | ||
127 | __packet_hook(prev, skb2); | 127 | __packet_hook(prev, skb2); |
@@ -131,23 +131,34 @@ static void br_flood(struct net_bridge *br, struct sk_buff *skb, | |||
131 | } | 131 | } |
132 | } | 132 | } |
133 | 133 | ||
134 | if (prev != NULL) { | 134 | if (!prev) |
135 | __packet_hook(prev, skb); | 135 | goto out; |
136 | return; | 136 | |
137 | if (skb0) { | ||
138 | skb = skb_clone(skb, GFP_ATOMIC); | ||
139 | if (!skb) { | ||
140 | br->dev->stats.tx_dropped++; | ||
141 | goto out; | ||
142 | } | ||
137 | } | 143 | } |
144 | __packet_hook(prev, skb); | ||
145 | return; | ||
138 | 146 | ||
139 | kfree_skb(skb); | 147 | out: |
148 | if (!skb0) | ||
149 | kfree_skb(skb); | ||
140 | } | 150 | } |
141 | 151 | ||
142 | 152 | ||
143 | /* called with rcu_read_lock */ | 153 | /* called with rcu_read_lock */ |
144 | void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb) | 154 | void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb) |
145 | { | 155 | { |
146 | br_flood(br, skb, __br_deliver); | 156 | br_flood(br, skb, NULL, __br_deliver); |
147 | } | 157 | } |
148 | 158 | ||
149 | /* called under bridge lock */ | 159 | /* called under bridge lock */ |
150 | void br_flood_forward(struct net_bridge *br, struct sk_buff *skb) | 160 | void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, |
161 | struct sk_buff *skb2) | ||
151 | { | 162 | { |
152 | br_flood(br, skb, __br_forward); | 163 | br_flood(br, skb, skb2, __br_forward); |
153 | } | 164 | } |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index be5ab8df6661..edfdaef44296 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -72,14 +72,11 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
72 | skb = NULL; | 72 | skb = NULL; |
73 | } | 73 | } |
74 | 74 | ||
75 | if (skb2 == skb) | ||
76 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
77 | |||
78 | if (skb) { | 75 | if (skb) { |
79 | if (dst) | 76 | if (dst) |
80 | br_forward(dst->dst, skb); | 77 | br_forward(dst->dst, skb); |
81 | else | 78 | else |
82 | br_flood_forward(br, skb); | 79 | br_flood_forward(br, skb, skb2); |
83 | } | 80 | } |
84 | 81 | ||
85 | if (skb2) | 82 | if (skb2) |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 16513793156e..fad5a2669d34 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -180,7 +180,8 @@ extern void br_forward(const struct net_bridge_port *to, | |||
180 | struct sk_buff *skb); | 180 | struct sk_buff *skb); |
181 | extern int br_forward_finish(struct sk_buff *skb); | 181 | extern int br_forward_finish(struct sk_buff *skb); |
182 | extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); | 182 | extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb); |
183 | extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb); | 183 | extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, |
184 | struct sk_buff *skb2); | ||
184 | 185 | ||
185 | /* br_if.c */ | 186 | /* br_if.c */ |
186 | extern void br_port_carrier_check(struct net_bridge_port *p); | 187 | extern void br_port_carrier_check(struct net_bridge_port *p); |