Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Apr 2009 18:15:41 +0000 (UTC)
From:      Rui Paulo <rpaulo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r191574 - projects/mesh11s/sys/net80211
Message-ID:  <200904271815.n3RIFfVK022268@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rpaulo
Date: Mon Apr 27 18:15:41 2009
New Revision: 191574
URL: http://svn.freebsd.org/changeset/base/191574

Log:
  * Simplify and fix add_meshid function()
  * Implement code to deal with probe request frames (similar to other
  operating modes)
  * Setup the bss id (technically there's no BSS ID in mesh, so I must
  revisit this in the future).
  
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/mesh11s/sys/net80211/ieee80211_mesh.c

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c	Mon Apr 27 18:10:42 2009	(r191573)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c	Mon Apr 27 18:15:41 2009	(r191574)
@@ -293,6 +293,22 @@ out:
 	return type;
 }
 
+static int
+is11bclient(const uint8_t *rates, const uint8_t *xrates)
+{
+	static const uint32_t brates = (1<<2*1)|(1<<2*2)|(1<<11)|(1<<2*11);
+	int i;
+ 
+	/* NB: the 11b clients we care about will not have xrates */
+	if (xrates != NULL || rates == NULL)
+		return 0;
+	for (i = 0; i < rates[1]; i++) {
+		int r = rates[2+i] & IEEE80211_RATE_VAL;
+		if (r > 2*11 || ((1<<r) & brates) == 0)
+			return 0;
+	}
+	return 1;
+}
 
 static void
 mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
@@ -349,7 +365,76 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 		break;
 	}
 	case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
+	{
+		uint8_t *ssid, *meshid, *rates, *xrates;
+		uint8_t *sfrm;
+
+		if (vap->iv_state != IEEE80211_S_RUN) {
+			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
+			    wh, NULL, "wrong state %s",
+			    ieee80211_state_name[vap->iv_state]);
+			vap->iv_stats.is_rx_mgtdiscard++;
+			return;
+		}
+		if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
+			/* frame must be directed */
+			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
+			    wh, NULL, "%s", "not unicast");
+			vap->iv_stats.is_rx_mgtdiscard++;       /* XXX stat */
+			return;
+		}
+
+		/*
+		 * prreq frame format
+		 *      [tlv] ssid
+		 *      [tlv] supported rates
+		 *      [tlv] extended supported rates
+		 *	[tlv] Mesh ID
+                 */
+		ssid = meshid = rates = xrates = NULL;
+		sfrm = frm;
+		while (efrm - frm > 1) {
+			IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return);
+			switch (*frm) {
+			case IEEE80211_ELEMID_SSID:
+				ssid = frm;
+				break;
+			case IEEE80211_ELEMID_RATES:
+				rates = frm;
+				break;
+			case IEEE80211_ELEMID_XRATES:
+				xrates = frm;
+				break;
+			case IEEE80211_ELEMID_MESHID:
+				meshid = frm;
+				break;
+			}
+			frm += frm[2] + 2;
+		}
+		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN, return);
+		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, return);
+		if (xrates != NULL)
+			IEEE80211_VERIFY_ELEMENT(xrates,
+			    IEEE80211_RATE_MAXSIZE - rates[1], return);
+		if (meshid != NULL)
+			IEEE80211_VERIFY_ELEMENT(meshid,
+			    IEEE80211_MESHID_LEN, return);
+		IEEE80211_VERIFY_SSID(vap->iv_bss, ssid, return);
+		/* XXX add verify meshid ? */
+
+		/* XXX find a better class or define it's own */
+		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_INPUT, wh->i_addr2,
+		    "%s", "recv probe req");
+		/*
+		 * Some legacy 11b clients cannot hack a complete
+		 * probe response frame.  When the request includes
+		 * only a bare-bones rate set, communicate this to
+		 * the transmit side.
+		 */
+		ieee80211_send_proberesp(vap, wh->i_addr2,
+		    is11bclient(rates, xrates) ? IEEE80211_SEND_LEGACY_11B : 0);
 		break;
+	}
 	case IEEE80211_FC0_SUBTYPE_ACTION:
 		break;
 	case IEEE80211_FC0_SUBTYPE_AUTH:
@@ -399,11 +484,10 @@ ieee80211_add_meshid(uint8_t *frm, struc
 	KASSERT(vap->iv_opmode == IEEE80211_M_MBSS, ("not a mbss vap"));
 
 	*frm++ = IEEE80211_ELEMID_MESHID;
-	*frm++ = sizeof(struct ieee80211_meshid_ie) + vap->iv_meshidlen;
+	*frm++ = vap->iv_meshidlen;
 	memcpy(frm, vap->iv_meshid, vap->iv_meshidlen);
-	frm += vap->iv_meshidlen;
-	
-	return frm; 
+
+	return frm + vap->iv_meshidlen;
 }
 
 void
@@ -421,12 +505,20 @@ ieee80211_create_mbss(struct ieee80211va
 		/* XXX recovery? */
 		return;
 	}
+	IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr);
 	ni->ni_meshidlen = vap->iv_meshidlen;
 	memcpy(ni->ni_meshid, vap->iv_meshid, ni->ni_meshidlen);
 	ni->ni_intval = ic->ic_bintval;
+	/*
+	 * Fix the channel and related attributes.
+	 */
+	/* clear DFS CAC state on previous channel */
+	if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
+	    ic->ic_bsschan->ic_freq != chan->ic_freq &&
+	    IEEE80211_IS_CHAN_CACDONE(ic->ic_bsschan))
+		ieee80211_dfs_cac_clear(ic, ic->ic_bsschan);
 	ic->ic_bsschan = chan;
 	ieee80211_node_set_chan(ni, chan);
-	ieee80211_setcurchan(ic, ni->ni_chan);
 	ic->ic_curmode = ieee80211_chan2mode(chan);
 	/*
 	 * Do mode-specific setup.
@@ -454,6 +546,9 @@ ieee80211_create_mbss(struct ieee80211va
 			    IEEE80211_MODE_11B);
 		}
 	}
+	ieee80211_ref_node(ni);
+	vap->iv_bss = ni;
+	ieee80211_setcurchan(ic, ni->ni_chan);
 	/*
 	 * Set the erp state (mostly the slot time) to deal with
 	 * the auto-select case; this should be redundant if the



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