Search Linux Wireless

[PATCH 2/9] mac80211: Limit amount of HWMP frames and forwarded data packets in queues on mesh interfaces

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Pedro Larbig <pedro.larbig@xxxxxxxx>

To avoid contention problems in a mesh network's high load areas, this patch
adds a 2-stage packet dropping mechanism:
* If the transmit queue for HWMP frames is filled with 256 or more packets,
additional HWMP frames will be dropped
* If the transmit queue for forwarded packets is at 384 or more, drop those,
too

This way, if a node runs into contention issues, it first reduces the amount
of HWMP messages, and only if this is not enough, starts also dropping data
packets from other nodes.

So, instead of eating up memory and crashing, a node does only behave selfish
in such situations.
This patch has been tested several hours in a 20-node testbed under heavy
iperf load.

Signed-off-by: Pedro Larbig <pedro.larbig@xxxxxxxx>
Signed-off-by: Javier Cardona <javier@xxxxxxxxxxx>
---
 net/mac80211/debugfs.c     |    4 ++++
 net/mac80211/ieee80211_i.h |    2 ++
 net/mac80211/mesh.h        |    5 +++++
 net/mac80211/mesh_hwmp.c   |   21 +++++++++++++++++++--
 net/mac80211/rx.c          |   13 ++++++++++++-
 5 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 186e02f..8aefd2e 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -496,6 +496,10 @@ void debugfs_hw_add(struct ieee80211_local *local)
 		local->tx_handlers_drop_not_assoc);
 	DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port,
 		local->tx_handlers_drop_unauth_port);
+	DEBUGFS_STATS_ADD(tx_handlers_drop_mesh_mgmt,
+		local->tx_handlers_drop_mesh_mgmt);
+	DEBUGFS_STATS_ADD(tx_handlers_drop_mesh_fwd,
+		local->tx_handlers_drop_mesh_fwd);
 	DEBUGFS_STATS_ADD(rx_handlers_drop, local->rx_handlers_drop);
 	DEBUGFS_STATS_ADD(rx_handlers_queued, local->rx_handlers_queued);
 	DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c204cee..12ad787 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -922,6 +922,8 @@ struct ieee80211_local {
 	unsigned int tx_handlers_drop_wep;
 	unsigned int tx_handlers_drop_not_assoc;
 	unsigned int tx_handlers_drop_unauth_port;
+	unsigned int tx_handlers_drop_mesh_mgmt;
+	unsigned int tx_handlers_drop_mesh_fwd;
 	unsigned int rx_handlers_drop;
 	unsigned int rx_handlers_queued;
 	unsigned int rx_handlers_drop_nullfunc;
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 2027207..6b57b11 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -186,6 +186,11 @@ struct mesh_rmc {
 /* Maximum number of paths per interface */
 #define MESH_MAX_MPATHS		1024
 
+/* Maximum number of data frames to be forwarded in tx queue */
+#define MESH_MAX_FWDING_QUEUE  384
+/* Maximum number of HWMP management frames in tx queue */
+#define MESH_MGMT_QUEUE_LEN    256
+
 /* Public interfaces */
 /* Various */
 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 fd4f76a..f09e5e8 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -105,6 +105,23 @@ enum mpath_frame_type {
 
 static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
+static void mesh_tx_skb(struct ieee80211_sub_if_data *sdata,
+			struct sk_buff *skb)
+{
+	struct ieee80211_local *local = sdata->local;
+
+	/* Frames going through ieee80211_tx_skb will be on the voice queue,
+	 * Therefor we need to check only IEEE80211_AC_VO */
+	if (unlikely(skb_queue_len(&local->pending[IEEE80211_AC_VO]) >=
+	   MESH_MGMT_QUEUE_LEN)) {
+		kfree_skb(skb);
+		I802_DEBUG_INC(local->tx_handlers_drop_mesh_mgmt);
+		return;
+	}
+
+	ieee80211_tx_skb(sdata, skb);
+}
+
 static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
 		u8 *orig_addr, __le32 orig_sn, u8 target_flags, u8 *target,
 		__le32 target_sn, const u8 *da, u8 hop_count, u8 ttl,
@@ -198,7 +215,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
 		pos += 4;
 	}
 
-	ieee80211_tx_skb(sdata, skb);
+	mesh_tx_skb(sdata, skb);
 	return 0;
 }
 
@@ -263,7 +280,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
 	pos += 4;
 	memcpy(pos, &target_rcode, 2);
 
-	ieee80211_tx_skb(sdata, skb);
+	mesh_tx_skb(sdata, skb);
 	return 0;
 }
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c4453fd..9b5daa1 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1817,7 +1817,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_hdr *hdr;
 	struct ieee80211s_hdr *mesh_hdr;
-	unsigned int hdrlen;
+	unsigned int hdrlen, q;
 	struct sk_buff *skb = rx->skb, *fwd_skb;
 	struct ieee80211_local *local = rx->local;
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
@@ -1915,6 +1915,17 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 			}
 			IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh,
 						     fwded_frames);
+
+			/* Check selected queue's size and drop if full */
+			q = skb_get_queue_mapping(fwd_skb);
+			if (unlikely(skb_queue_len(&local->pending[q]) >=
+			    MESH_MAX_FWDING_QUEUE)) {
+				kfree_skb(fwd_skb);
+				I802_DEBUG_INC(local->
+					       tx_handlers_drop_mesh_fwd);
+				return RX_DROP_MONITOR;
+			}
+
 			ieee80211_add_pending_skb(local, fwd_skb);
 		}
 	}
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux