Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 May 2012 15:42:41 +0000 (UTC)
From:      Monthadar Al Jaberi <monthadar@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r234876 - head/sys/net80211
Message-ID:  <201205011542.q41Fgf4P032422@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: monthadar
Date: Tue May  1 15:42:41 2012
New Revision: 234876
URL: http://svn.freebsd.org/changeset/base/234876

Log:
  Fixed some MPM reason codes and max number of neighbors check
  
   * Added IEEE80211_MESH_MAX_NEIGHBORS and it is set to 15, same as before;
   * Modified mesh_parse_meshpeering_action to verify MPM frame and send
   correct reason code for when a frame is rejected according to standard spec;
   * Modified mesh_recv_action_meshpeering_* according to the standard spec;
   * Modified mesh_peer_timeout_cb to always send CLOSE frame when in CONFIRMRCV
   state according to the standard spec;
  
  Approved by: adrian

Modified:
  head/sys/net80211/ieee80211_mesh.c
  head/sys/net80211/ieee80211_mesh.h

Modified: head/sys/net80211/ieee80211_mesh.c
==============================================================================
--- head/sys/net80211/ieee80211_mesh.c	Tue May  1 15:39:16 2012	(r234875)
+++ head/sys/net80211/ieee80211_mesh.c	Tue May  1 15:42:41 2012	(r234876)
@@ -1573,7 +1573,7 @@ mesh_recv_ctl(struct ieee80211_node *ni,
 }
 
 /*
- * Parse meshpeering action ie's for open+confirm frames
+ * Parse meshpeering action ie's for MPM frames
  */
 static const struct ieee80211_meshpeer_ie *
 mesh_parse_meshpeering_action(struct ieee80211_node *ni,
@@ -1583,7 +1583,9 @@ mesh_parse_meshpeering_action(struct iee
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	const struct ieee80211_meshpeer_ie *mpie;
+	uint16_t args[3];
 	const uint8_t *meshid, *meshconf, *meshpeer;
+	uint8_t sendclose = 0; /* 1 = MPM frame rejected, close will be sent */
 
 	meshid = meshconf = meshpeer = NULL;
 	while (efrm - frm > 1) {
@@ -1599,6 +1601,7 @@ mesh_parse_meshpeering_action(struct iee
 			meshpeer = frm;
 			mpie = (const struct ieee80211_meshpeer_ie *) frm;
 			memset(mp, 0, sizeof(*mp));
+			mp->peer_len = mpie->peer_len;
 			mp->peer_proto = LE_READ_2(&mpie->peer_proto);
 			mp->peer_llinkid = LE_READ_2(&mpie->peer_llinkid);
 			switch (subtype) {
@@ -1627,22 +1630,46 @@ mesh_parse_meshpeering_action(struct iee
 	}
 
 	/*
-	 * Verify the contents of the frame. Action frames with
-	 * close subtype don't have a Mesh Configuration IE.
-	 * If if fails validation, close the peer link.
+	 * Verify the contents of the frame.
+	 * If it fails validation, close the peer link.
 	 */
-	KASSERT(meshpeer != NULL &&
-	    subtype != IEEE80211_ACTION_MESHPEERING_CLOSE,
-	    ("parsing close action"));
-
-	if (mesh_verify_meshid(vap, meshid) ||
-	    mesh_verify_meshpeer(vap, subtype, meshpeer) ||
-	    mesh_verify_meshconf(vap, meshconf)) {
-		uint16_t args[3];
+	if (mesh_verify_meshpeer(vap, subtype, (const uint8_t *)mp)) {
+		sendclose = 1;
+		IEEE80211_DISCARD(vap,
+		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+		    wh, NULL, "%s", "MPM validation failed");
+	}
 
+	/* If meshid is not the same reject any frames type. */
+	if (sendclose == 0 && mesh_verify_meshid(vap, meshid)) {
+		sendclose = 1;
 		IEEE80211_DISCARD(vap,
 		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
 		    wh, NULL, "%s", "not for our mesh");
+		if (subtype == IEEE80211_ACTION_MESHPEERING_CLOSE) {
+			/*
+			 * Standard not clear about this, if we dont ignore
+			 * there will be an endless loop between nodes sending
+			 * CLOSE frames between each other with wrong meshid.
+			 * Discard and timers will bring FSM to IDLE state.
+			 */
+			return NULL;
+		}
+	}
+	
+	/*
+	 * Close frames are accepted if meshid is the same.
+	 * Verify the other two types.
+	 */
+	if (sendclose == 0 && subtype != IEEE80211_ACTION_MESHPEERING_CLOSE &&
+	    mesh_verify_meshconf(vap, meshconf)) {
+		sendclose = 1;
+		IEEE80211_DISCARD(vap,
+		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+		    wh, NULL, "%s", "configuration missmatch");
+	}
+
+	if (sendclose) {
 		vap->iv_stats.is_rx_mgtdiscard++;
 		switch (ni->ni_mlstate) {
 		case IEEE80211_NODE_MESH_IDLE:
@@ -1655,7 +1682,15 @@ mesh_parse_meshpeering_action(struct iee
 		case IEEE80211_NODE_MESH_CONFIRMRCV:
 			args[0] = ni->ni_mlpid;
 			args[1] = ni->ni_mllid;
-			args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
+			/* Reason codes for rejection */
+			switch (subtype) {
+			case IEEE80211_ACTION_MESHPEERING_OPEN:
+				args[2] = IEEE80211_REASON_MESH_CPVIOLATION;
+				break;
+			case IEEE80211_ACTION_MESHPEERING_CONFIRM:
+				args[2] = IEEE80211_REASON_MESH_INCONS_PARAMS;
+				break;
+			}
 			ieee80211_send_action(ni,
 			    IEEE80211_ACTION_CAT_SELF_PROT,
 			    IEEE80211_ACTION_MESHPEERING_CLOSE,
@@ -1666,6 +1701,7 @@ mesh_parse_meshpeering_action(struct iee
 		}
 		return NULL;
 	}
+	
 	return (const struct ieee80211_meshpeer_ie *) mp;
 }
 
@@ -1675,6 +1711,7 @@ mesh_recv_action_meshpeering_open(struct
 	const uint8_t *frm, const uint8_t *efrm)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211_meshpeer_ie ie;
 	const struct ieee80211_meshpeer_ie *meshpeer;
 	uint16_t args[3];
@@ -1692,6 +1729,19 @@ mesh_recv_action_meshpeering_open(struct
 
 	switch (ni->ni_mlstate) {
 	case IEEE80211_NODE_MESH_IDLE:
+		/* Reject open request if reached our maximum neighbor count */
+		if (ms->ms_neighbors >= IEEE80211_MESH_MAX_NEIGHBORS) {
+			args[0] = meshpeer->peer_llinkid;
+			args[1] = 0;
+			args[2] = IEEE80211_REASON_MESH_MAX_PEERS;
+			ieee80211_send_action(ni,
+			    IEEE80211_ACTION_CAT_SELF_PROT,
+			    IEEE80211_ACTION_MESHPEERING_CLOSE,
+			    args);
+			/* stay in IDLE state */
+			return (0);
+		}
+		/* Open frame accepted */
 		mesh_linkchange(ni, IEEE80211_NODE_MESH_OPENRCV);
 		ni->ni_mllid = meshpeer->peer_llinkid;
 		ni->ni_mlpid = mesh_generateid(vap);
@@ -1792,7 +1842,8 @@ mesh_recv_action_meshpeering_open(struct
 	case IEEE80211_NODE_MESH_HOLDING:
 		args[0] = ni->ni_mlpid;
 		args[1] = meshpeer->peer_llinkid;
-		args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+		/* Standard not clear about what the reaason code should be */
+		args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
 		ieee80211_send_action(ni,
 		    IEEE80211_ACTION_CAT_SELF_PROT,
 		    IEEE80211_ACTION_MESHPEERING_CLOSE,
@@ -1830,11 +1881,13 @@ mesh_recv_action_meshpeering_confirm(str
 		break;
 	case IEEE80211_NODE_MESH_OPENSNT:
 		mesh_linkchange(ni, IEEE80211_NODE_MESH_CONFIRMRCV);
+		mesh_peer_timeout_setup(ni);
 		break;
 	case IEEE80211_NODE_MESH_HOLDING:
 		args[0] = ni->ni_mlpid;
 		args[1] = meshpeer->peer_llinkid;
-		args[2] = IEEE80211_REASON_MESH_MAX_RETRIES;
+		/* Standard not clear about what the reaason code should be */
+		args[2] = IEEE80211_REASON_PEER_LINK_CANCELED;
 		ieee80211_send_action(ni,
 		    IEEE80211_ACTION_CAT_SELF_PROT,
 		    IEEE80211_ACTION_MESHPEERING_CLOSE,
@@ -1869,8 +1922,23 @@ mesh_recv_action_meshpeering_close(struc
 	const struct ieee80211_frame *wh,
 	const uint8_t *frm, const uint8_t *efrm)
 {
+	struct ieee80211_meshpeer_ie ie;
+	const struct ieee80211_meshpeer_ie *meshpeer;
 	uint16_t args[3];
 
+	/* +2 for action + code */
+	meshpeer = mesh_parse_meshpeering_action(ni, wh, frm+2, efrm, &ie,
+	    IEEE80211_ACTION_MESHPEERING_CLOSE);
+	if (meshpeer == NULL) {
+		return 0;
+	}
+
+	/*
+	 * XXX: check reason code, for example we could receive
+	 * IEEE80211_REASON_MESH_MAX_PEERS then we should not attempt
+	 * to peer again.
+	 */
+
 	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
 	    ni, "%s", "recv PEER CLOSE");
 
@@ -1894,7 +1962,7 @@ mesh_recv_action_meshpeering_close(struc
 		break;
 	case IEEE80211_NODE_MESH_HOLDING:
 		mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
-		mesh_peer_timeout_setup(ni);
+		mesh_peer_timeout_stop(ni);
 		break;
 	}
 	return 0;
@@ -2112,13 +2180,11 @@ mesh_send_action_meshpeering_close(struc
 		 * mesh peer close action frame format:
 		 *   [1] category
 		 *   [1] action
-		 *   [2] reason code
 		 *   [tlv] mesh id
 		 *   [tlv] mesh peer link mgmt
 		 */
 		*frm++ = category;
 		*frm++ = action;
-		ADDSHORT(frm, args[2]);		/* reason code */
 		frm = ieee80211_add_meshid(frm, vap);
 		frm = ieee80211_add_meshpeer(frm,
 		    IEEE80211_ACTION_MESHPEERING_CLOSE,
@@ -2260,19 +2326,13 @@ mesh_peer_timeout_cb(void *arg)
 		}
 		break;
 	case IEEE80211_NODE_MESH_CONFIRMRCV:
-		if (ni->ni_mlrcnt == ieee80211_mesh_maxretries) {
-			args[0] = ni->ni_mlpid;
-			args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
-			ieee80211_send_action(ni,
-			    IEEE80211_ACTION_CAT_SELF_PROT,
-			    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
-			ni->ni_mlrcnt = 0;
-			mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
-			mesh_peer_timeout_setup(ni);
-		} else {
-			ni->ni_mlrcnt++;
-			mesh_peer_timeout_setup(ni);
-		}
+		args[0] = ni->ni_mlpid;
+		args[2] = IEEE80211_REASON_MESH_CONFIRM_TIMEOUT;
+		ieee80211_send_action(ni,
+		    IEEE80211_ACTION_CAT_SELF_PROT,
+		    IEEE80211_ACTION_MESHPEERING_CLOSE, args);
+		mesh_linkchange(ni, IEEE80211_NODE_MESH_HOLDING);
+		mesh_peer_timeout_setup(ni);
 		break;
 	case IEEE80211_NODE_MESH_HOLDING:
 		mesh_linkchange(ni, IEEE80211_NODE_MESH_IDLE);
@@ -2418,7 +2478,8 @@ ieee80211_add_meshconf(uint8_t *frm, str
 	*frm++ = IEEE80211_MESHCONF_SYNC_NEIGHOFF;
 	*frm++ = IEEE80211_MESHCONF_AUTH_DISABLED;
 	/* NB: set the number of neighbors before the rest */
-	*frm = (ms->ms_neighbors > 15 ? 15 : ms->ms_neighbors) << 1;
+	*frm = (ms->ms_neighbors > IEEE80211_MESH_MAX_NEIGHBORS ?
+	    IEEE80211_MESH_MAX_NEIGHBORS : ms->ms_neighbors) << 1;
 	if (ms->ms_flags & IEEE80211_MESHFLAGS_PORTAL)
 		*frm |= IEEE80211_MESHCONF_FORM_MP;
 	frm += 1;

Modified: head/sys/net80211/ieee80211_mesh.h
==============================================================================
--- head/sys/net80211/ieee80211_mesh.h	Tue May  1 15:39:16 2012	(r234875)
+++ head/sys/net80211/ieee80211_mesh.h	Tue May  1 15:42:41 2012	(r234876)
@@ -32,6 +32,7 @@
 #define _NET80211_IEEE80211_MESH_H_
 
 #define	IEEE80211_MESH_DEFAULT_TTL	31
+#define	IEEE80211_MESH_MAX_NEIGHBORS	15
 
 /*
  * NB: all structures are __packed  so sizeof works on arm, et. al.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201205011542.q41Fgf4P032422>