aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Pedersen <thomas@cozybit.com>2012-08-09 21:15:40 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-08-20 07:25:05 -0400
commit4bd4c2dd8e734868ae9f0ceb87a6edd27df8f45c (patch)
tree81c3fc65c74c5ba83ef4e23597c99848b7c1f635
parentb22bd5221cfe80ee3d345d9deccfd29edf9bafb4 (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.h3
-rw-r--r--net/mac80211/mesh_hwmp.c2
-rw-r--r--net/mac80211/mesh_pathtbl.c34
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 */
220int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, 223int 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;