svn commit: r191685 - projects/mesh11s/sys/net80211

Rui Paulo rpaulo at FreeBSD.org
Thu Apr 30 12:16:16 UTC 2009


Author: rpaulo
Date: Thu Apr 30 12:16:15 2009
New Revision: 191685
URL: http://svn.freebsd.org/changeset/base/191685

Log:
  Initial implementation of Mesh Peering. This makes it possible to
  establish a mesh link with a Linux mesh node, but the code is still
  imature.
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/mesh11s/sys/net80211/ieee80211_ht.c
  projects/mesh11s/sys/net80211/ieee80211_mesh.c
  projects/mesh11s/sys/net80211/ieee80211_mesh.h
  projects/mesh11s/sys/net80211/ieee80211_node.h

Modified: projects/mesh11s/sys/net80211/ieee80211_ht.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_ht.c	Thu Apr 30 12:14:52 2009	(r191684)
+++ projects/mesh11s/sys/net80211/ieee80211_ht.c	Thu Apr 30 12:16:15 2009	(r191685)
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
 
 #include <net80211/ieee80211_var.h>
 #include <net80211/ieee80211_input.h>
+#include <net80211/ieee80211_mesh.h>
 
 /* define here, used throughout file */
 #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
@@ -2121,7 +2122,7 @@ ieee80211_send_action(struct ieee80211_n
 	struct mbuf *m;
 	uint8_t *frm;
 	uint16_t baparamset;
-	int ret;
+	int ret, addsize;
 
 	KASSERT(ni != NULL, ("null node"));
 
@@ -2137,11 +2138,29 @@ ieee80211_send_action(struct ieee80211_n
 		ieee80211_node_refcnt(ni)+1);
 	ieee80211_ref_node(ni);
 
+	addsize = 0;
+	switch (category) {
+	case IEEE80211_ACTION_CAT_BA:
+	case IEEE80211_ACTION_CAT_HT:
+		addsize += sizeof(struct ieee80211_action_ba_addbaresponse);
+		break;
+	case IEEE80211_ACTION_CAT_MESHPEERING:
+		addsize += sizeof(uint16_t);		/* capabilities */
+		addsize += 2 + vap->iv_meshidlen;	/* Mesh ID */
+		addsize += sizeof(struct ieee80211_meshconf_ie);
+		/* On Open frames, the peer link ID is not sent */
+		if (action == IEEE80211_ACTION_MESHPEERING_OPEN)
+			addsize += sizeof(struct ieee80211_meshpeer_ie) - 2;
+		else
+			addsize += sizeof(struct ieee80211_meshpeer_ie);
+		break;
+	}
 	m = ieee80211_getmgtframe(&frm,
 		ic->ic_headroom + sizeof(struct ieee80211_frame),
 		  sizeof(uint16_t)	/* action+category */
 		/* XXX may action payload */
-		+ sizeof(struct ieee80211_action_ba_addbaresponse)
+		+ addsize
+		
 	);
 	if (m == NULL)
 		senderr(ENOMEM, is_tx_nobuf);
@@ -2210,6 +2229,43 @@ ieee80211_send_action(struct ieee80211_n
 			goto badaction;
 		}
 		break;
+	case IEEE80211_ACTION_CAT_MESHPEERING:
+
+		switch (action) {
+		case IEEE80211_ACTION_MESHPEERING_OPEN:
+			IEEE80211_NOTE(vap,
+			    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
+			    "send PEER OPEN action: lid %x", args[0]);
+			*frm++ = 0;	/* capabilites */
+			*frm++ = 0;
+			frm = ieee80211_add_meshid(frm, vap);
+			frm = ieee80211_add_meshconf(frm, vap);
+			*frm++ = IEEE80211_ELEMID_MESHPEER;
+			*frm++ = 3;			        /* len */
+			*frm++ = IEEE80211_MESH_PEER_LINK_OPEN; /* subtype */
+			ADDSHORT(frm, args[0]);		        /* local ID */
+			break;
+		case IEEE80211_ACTION_MESHPEERING_CONFIRM:
+			IEEE80211_NOTE(vap,
+			    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
+			    "send PEER CONFIRM action: lid %x, pid %x",
+			    args[0], args[1]);
+			*frm++ = 0;	/* capabilites */
+			*frm++ = 0;
+			*frm++ = 0;	/* status code */
+			*frm++ = 0;
+			*frm++ = 0;	/* AID */
+			*frm++ = 0;
+			frm = ieee80211_add_meshid(frm, vap);
+			frm = ieee80211_add_meshconf(frm, vap);
+			*frm++ = IEEE80211_ELEMID_MESHPEER;
+			*frm++ = 5;				   /* len */
+			*frm++ = IEEE80211_MESH_PEER_LINK_CONFIRM; /* subtype */
+			ADDSHORT(frm, args[0]);
+			ADDSHORT(frm, args[1]);
+			break;
+		}
+		break;
 	default:
 	badaction:
 		IEEE80211_NOTE(vap,

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c	Thu Apr 30 12:14:52 2009	(r191684)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c	Thu Apr 30 12:16:15 2009	(r191685)
@@ -68,6 +68,7 @@ static int	mesh_input(struct ieee80211_n
 		    uint32_t);
 static void	mesh_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
 		    int, int, uint32_t);
+static void	mesh_recv_action(struct ieee80211_node *, struct mbuf *);
 
 void
 ieee80211_mesh_attach(struct ieee80211com *ic)
@@ -314,6 +315,7 @@ static void
 mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
     int rssi, int noise, uint32_t rstamp)
 {
+	static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211_frame *wh;
@@ -327,7 +329,6 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 	case IEEE80211_FC0_SUBTYPE_BEACON:
 	{
 		struct ieee80211_scanparams scan;
-
 		/*
 		 * We process beacon/probe response
 		 * frames to discover neighbors.
@@ -363,6 +364,42 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 			return;
 		}
 
+		/* The rest of this code assumes we setup and running */
+		if (vap->iv_state != IEEE80211_S_RUN)
+			return;
+		/*
+		 * Ignore non-mesh STAs and STAs for other mesh networks.
+		 */
+		if (scan.meshid &&
+		    memcmp(scan.meshid+2, vap->iv_meshid, vap->iv_meshidlen) != 0) {
+			IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, ni,
+			    "beacon not for our mesh (%s)", scan.meshid+2);
+			return;
+		}
+		
+		/*
+		 * More validation: make sure we are talking to a Mesh node.
+		 */
+		if ((scan.capinfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) == 0 &&
+		    !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr) &&
+		    IEEE80211_ADDR_EQ(wh->i_addr3, zerobssid)) {
+			/*
+			 * Create a new entry in the neighbor table.
+			 */
+			ni = ieee80211_add_neighbor(vap, wh, &scan);
+		} else {
+			/*
+			 * Record tsf for potential resync.
+			 */
+			memcpy(ni->ni_tstamp.data, scan.tstamp,
+			    sizeof(ni->ni_tstamp));
+		}
+		if (ni != NULL) {
+			IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
+			ni->ni_noise = noise;
+			ni->ni_rstamp = rstamp;
+		}
+
 		/*
 		 * If it's a beacon for our mesh and we haven't already
 		 * peered with this node, send him a mgmt frame with
@@ -443,11 +480,15 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 		break;
 	}
 	case IEEE80211_FC0_SUBTYPE_ACTION:
-		if (vap->iv_state == IEEE80211_S_RUN) {
-			if (ieee80211_parse_action(ni, m0) == 0)
-				ic->ic_recv_action(ni, frm, efrm);
-		} else
+		if (vap->iv_state != IEEE80211_S_RUN) {
 			vap->iv_stats.is_rx_mgtdiscard++;
+			break;
+		}
+		/* XXX parse_action is a bit useless now */
+		if (ieee80211_parse_action(ni, m0) == 0) {
+			mesh_recv_action(ni, m0);
+			ic->ic_recv_action(ni, frm, efrm);
+		}
 		break;
 	case IEEE80211_FC0_SUBTYPE_AUTH:
 	case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
@@ -467,6 +508,97 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 		break;
 	}
 }
+static void
+mesh_recv_action(struct ieee80211_node *ni, struct mbuf *m0)
+{
+	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211_action *ia;
+	struct ieee80211_frame *wh;
+	struct ieee80211_meshid_ie *meshid;
+	struct ieee80211_meshconf_ie *meshconf;
+	struct ieee80211_meshpeer_ie *meshpeer;
+	uint8_t *frm, *efrm;
+	uint16_t args[4];
+		
+	wh = mtod(m0, struct ieee80211_frame *);
+	ia = (struct ieee80211_action *) &wh[1];
+	frm = (uint8_t *)&wh[1];
+	frm += sizeof(ia);
+	efrm = mtod(m0, uint8_t *) + m0->m_len;
+
+	/* XXX explain frame format */
+	meshid = NULL;
+	meshpeer = NULL;
+	meshconf = NULL;
+	while (efrm - frm > 1) {
+		IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
+		switch (*frm) {
+		case IEEE80211_ELEMID_MESHID:
+			meshid = (struct ieee80211_meshid_ie *) frm;
+			break;
+		case IEEE80211_ELEMID_MESHCONF:
+			meshconf = (struct ieee80211_meshconf_ie *) frm;
+			break;
+		case IEEE80211_ELEMID_MESHPEER:
+			meshpeer = (struct ieee80211_meshpeer_ie *) frm;
+			break;
+		}
+		frm += frm[1] + 2;
+	}
+	/*
+	 * Check if we agree on Mesh ID and Configuration.
+	 * XXX: TBD
+	 */
+	if (!meshid || !meshconf || !meshpeer) {
+		IEEE80211_DISCARD(vap,
+		    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+		    wh, NULL, "%s", "action frame not for our mesh");
+		vap->iv_stats.is_rx_mgtdiscard++;
+		return;
+	}
+	switch (ia->ia_category) {
+	case IEEE80211_ACTION_CAT_MESHPEERING:
+		switch (ia->ia_action) {
+		case IEEE80211_ACTION_MESHPEERING_OPEN:
+			IEEE80211_NOTE(vap,
+			    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
+			    "%s", "recv peering open");
+			ni->ni_peerstate = IEEE80211_NODE_MESH_OPENRCV;
+			ni->ni_llid = meshpeer->peer_llinkid;
+			ni->ni_plid = 0xf4ef;
+			args[0] = ni->ni_plid;
+			ieee80211_send_action(ni,
+			    IEEE80211_ACTION_CAT_MESHPEERING,
+			    IEEE80211_ACTION_MESHPEERING_OPEN, args);
+			break;
+		case IEEE80211_ACTION_MESHPEERING_CONFIRM:
+			IEEE80211_NOTE(vap,
+			    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni,
+			    "%s", "recv peering confirm");
+			if (ni->ni_peerstate != IEEE80211_NODE_MESH_OPNSENT &&
+			    ni->ni_peerstate != IEEE80211_NODE_MESH_OPENRCV) {
+				IEEE80211_DISCARD(vap,
+				    IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+				    wh, NULL, "received confirm in invalid "
+				    "state %d", ni->ni_peerstate);
+				vap->iv_stats.is_rx_mgtdiscard++;
+				return;
+			}
+			ni->ni_peerstate = IEEE80211_NODE_MESH_CONFIRMRECV;
+			args[0] = 0xf4ef;
+			args[1] = ni->ni_llid;
+			ieee80211_send_action(ni,
+			    IEEE80211_ACTION_CAT_MESHPEERING,
+			    IEEE80211_ACTION_MESHPEERING_CONFIRM, args);
+		}
+		break;
+	default:
+		IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH,
+		    wh, NULL, "%s", "not handled");
+		vap->iv_stats.is_rx_mgtdiscard++;
+	}
+}
+
 /*
  * Parse a MESH ID ie on station join.
  */

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.h	Thu Apr 30 12:14:52 2009	(r191684)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.h	Thu Apr 30 12:16:15 2009	(r191685)
@@ -250,6 +250,20 @@ struct ieee80211_meshpuc_ie {
 	uint8_t		puc_daddr[IEEE80211_ADDR_LEN];
 } __packed;
 
+/*
+ * 802.11s Action Frames
+ */
+#define	IEEE80211_ACTION_CAT_MESHPEERING	30	/* XXX Linux */
+#define	IEEE80211_ACTION_CAT_MESHLINK		13
+#define	IEEE80211_ACTION_CAT_PATHSEL		14
+#define	IEEE80211_ACTION_CAT_INTERWORK		15
+#define	IEEE80211_ACTION_CAT_RESOURCE		16
+#define	IEEE80211_ACTION_CAT_PROXY		17
+
+#define	IEEE80211_ACTION_MESHPEERING_OPEN	0
+#define	IEEE80211_ACTION_MESHPEERING_CONFIRM	1
+#define	IEEE80211_ACTION_MESHPEERING_CLOSE	2
+
 void		ieee80211_mesh_attach(struct ieee80211com *);
 void		ieee80211_mesh_detach(struct ieee80211com *);
 void		ieee80211_parse_meshid(struct ieee80211_node *, const uint8_t *);

Modified: projects/mesh11s/sys/net80211/ieee80211_node.h
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_node.h	Thu Apr 30 12:14:52 2009	(r191684)
+++ projects/mesh11s/sys/net80211/ieee80211_node.h	Thu Apr 30 12:16:15 2009	(r191685)
@@ -36,7 +36,7 @@
  * Each ieee80211com instance has a single timer that fires every
  * IEEE80211_INACT_WAIT seconds to handle "inactivity processing".
  * This is used to do node inactivity processing when operating
- * as an AP or in adhoc mode.  For inactivity processing each node
+ * as an AP, adhoc or mesh mode.  For inactivity processing each node
  * has a timeout set in it's ni_inact field that is decremented
  * on each timeout and the node is reclaimed when the counter goes
  * to zero.  We use different inactivity timeout values depending
@@ -175,6 +175,17 @@ struct ieee80211_node {
 	uint8_t			ni_dtim_period;	/* DTIM period */
 	uint8_t			ni_dtim_count;	/* DTIM count for last bcn */
 
+	/* mesh */
+#define IEEE80211_NODE_MESH_IDLE	0
+#define IEEE80211_NODE_MESH_OPNSENT	1	/* Peer Open Frame Received */
+#define IEEE80211_NODE_MESH_OPENRCV	2	/* Peer Open Frame Sent */
+#define IEEE80211_NODE_MESH_CONFIRMRECV	3	/* Peer Confirm Frame Recvived */
+#define IEEE80211_NODE_MESH_ESTABLISHED	4	/* Peer Link Established */
+#define IEEE80211_NODE_MESH_HOLDING	5	/* Peer Link Closing */
+	int8_t			ni_peerstate;	/* Mesh Peering state */
+	uint16_t		ni_llid;	/* local link ID */
+	uint16_t		ni_plid;	/* peer link ID */
+
 	/* 11n state */
 	uint16_t		ni_htcap;	/* HT capabilities */
 	uint8_t			ni_htparam;	/* HT params */


More information about the svn-src-projects mailing list