diff options
author | Thomas Pedersen <thomas@cozybit.com> | 2012-08-09 21:15:40 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-08-20 07:25:05 -0400 |
commit | 4bd4c2dd8e734868ae9f0ceb87a6edd27df8f45c (patch) | |
tree | 81c3fc65c74c5ba83ef4e23597c99848b7c1f635 | |
parent | b22bd5221cfe80ee3d345d9deccfd29edf9bafb4 (diff) |
mac80211: clean up mpath_move_to_queue()
Use skb_queue_walk_safe instead, and fix a few issues:
- didn't free old skbs on moving
- didn't react to failed skb alloc
- needlessly held a local pointer to the destination frame queue
- didn't check destination queue length before adding skb
Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | net/mac80211/mesh.h | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 2 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 34 |
3 files changed, 21 insertions, 18 deletions
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index faaa39bcfd10..e4d911ffd5d1 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -215,6 +215,9 @@ struct mesh_rmc { | |||
215 | /* Maximum number of paths per interface */ | 215 | /* Maximum number of paths per interface */ |
216 | #define MESH_MAX_MPATHS 1024 | 216 | #define MESH_MAX_MPATHS 1024 |
217 | 217 | ||
218 | /* Number of frames buffered per destination for unresolved destinations */ | ||
219 | #define MESH_FRAME_QUEUE_LEN 10 | ||
220 | |||
218 | /* Public interfaces */ | 221 | /* Public interfaces */ |
219 | /* Various */ | 222 | /* Various */ |
220 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 223 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 494bc39f61a4..47aeee2d8db1 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #define MAX_METRIC 0xffffffff | 17 | #define MAX_METRIC 0xffffffff |
18 | #define ARITH_SHIFT 8 | 18 | #define ARITH_SHIFT 8 |
19 | 19 | ||
20 | /* Number of frames buffered per destination for unresolved destinations */ | ||
21 | #define MESH_FRAME_QUEUE_LEN 10 | ||
22 | #define MAX_PREQ_QUEUE_LEN 64 | 20 | #define MAX_PREQ_QUEUE_LEN 64 |
23 | 21 | ||
24 | /* Destination only */ | 22 | /* Destination only */ |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index b819d6b847d0..aa749818860e 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -279,40 +279,42 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, | |||
279 | struct mesh_path *from_mpath, | 279 | struct mesh_path *from_mpath, |
280 | bool copy) | 280 | bool copy) |
281 | { | 281 | { |
282 | struct sk_buff *skb, *cp_skb = NULL; | 282 | struct sk_buff *skb, *fskb, *tmp; |
283 | struct sk_buff_head gateq, failq; | 283 | struct sk_buff_head failq; |
284 | unsigned long flags; | 284 | unsigned long flags; |
285 | int num_skbs; | ||
286 | 285 | ||
287 | BUG_ON(gate_mpath == from_mpath); | 286 | BUG_ON(gate_mpath == from_mpath); |
288 | BUG_ON(!gate_mpath->next_hop); | 287 | BUG_ON(!gate_mpath->next_hop); |
289 | 288 | ||
290 | __skb_queue_head_init(&gateq); | ||
291 | __skb_queue_head_init(&failq); | 289 | __skb_queue_head_init(&failq); |
292 | 290 | ||
293 | spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); | 291 | spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); |
294 | skb_queue_splice_init(&from_mpath->frame_queue, &failq); | 292 | skb_queue_splice_init(&from_mpath->frame_queue, &failq); |
295 | spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); | 293 | spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); |
296 | 294 | ||
297 | num_skbs = skb_queue_len(&failq); | 295 | skb_queue_walk_safe(&failq, fskb, tmp) { |
298 | 296 | if (skb_queue_len(&gate_mpath->frame_queue) >= | |
299 | while (num_skbs--) { | 297 | MESH_FRAME_QUEUE_LEN) { |
300 | skb = __skb_dequeue(&failq); | 298 | mpath_dbg(gate_mpath->sdata, "mpath queue full!\n"); |
301 | if (copy) { | 299 | break; |
302 | cp_skb = skb_copy(skb, GFP_ATOMIC); | ||
303 | if (cp_skb) | ||
304 | __skb_queue_tail(&failq, cp_skb); | ||
305 | } | 300 | } |
306 | 301 | ||
302 | skb = skb_copy(fskb, GFP_ATOMIC); | ||
303 | if (WARN_ON(!skb)) | ||
304 | break; | ||
305 | |||
307 | prepare_for_gate(skb, gate_mpath->dst, gate_mpath); | 306 | prepare_for_gate(skb, gate_mpath->dst, gate_mpath); |
308 | __skb_queue_tail(&gateq, skb); | 307 | skb_queue_tail(&gate_mpath->frame_queue, skb); |
308 | |||
309 | if (copy) | ||
310 | continue; | ||
311 | |||
312 | __skb_unlink(fskb, &failq); | ||
313 | kfree_skb(fskb); | ||
309 | } | 314 | } |
310 | 315 | ||
311 | spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags); | ||
312 | skb_queue_splice(&gateq, &gate_mpath->frame_queue); | ||
313 | mpath_dbg(gate_mpath->sdata, "Mpath queue for gate %pM has %d frames\n", | 316 | mpath_dbg(gate_mpath->sdata, "Mpath queue for gate %pM has %d frames\n", |
314 | gate_mpath->dst, skb_queue_len(&gate_mpath->frame_queue)); | 317 | gate_mpath->dst, skb_queue_len(&gate_mpath->frame_queue)); |
315 | spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags); | ||
316 | 318 | ||
317 | if (!copy) | 319 | if (!copy) |
318 | return; | 320 | return; |