Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Apr 2009 10:19:26 +0000 (UTC)
From:      Rui Paulo <rpaulo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r191459 - projects/mesh11s/sys/net80211
Message-ID:  <200904241019.n3OAJQhT015146@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rpaulo
Date: Fri Apr 24 10:19:25 2009
New Revision: 191459
URL: http://svn.freebsd.org/changeset/base/191459

Log:
  Use a bunch of code from the IBSS operation to process input and
  management frames. Due to this, add Sam's copyright.
  Initial work on scanning mesh nodes. It works just like IBSS for now,
  but will needed to be changed later.
  
  Sponsored by:	The FreeBSD Foundation

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

Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_mesh.c	Fri Apr 24 10:18:06 2009	(r191458)
+++ projects/mesh11s/sys/net80211/ieee80211_mesh.c	Fri Apr 24 10:19:25 2009	(r191459)
@@ -1,4 +1,5 @@
 /*- 
+ * Copyright (c) 2007-2009 Sam Leffler, Errno Consulting
  * Copyright (c) 2009 The FreeBSD Foundation 
  * All rights reserved. 
  * 
@@ -125,6 +126,33 @@ mesh_newstate(struct ieee80211vap *vap, 
 	case IEEE80211_S_SCAN:
 		switch (ostate) {
 		case IEEE80211_S_INIT:
+			if (vap->iv_des_chan != IEEE80211_CHAN_ANYC &&
+			    !IEEE80211_IS_CHAN_RADAR(vap->iv_des_chan)) {
+			    /*
+			     * Already have a channel; bypass the
+			     * scan and startup immediately.
+			     */
+			     /* ieee80211_create_mesh(vap, vap->iv_des_chan); */
+			     break;
+			}
+			/*
+			 * Initiate a scan.  We can come here as a result
+			 * of an IEEE80211_IOC_SCAN_REQ too in which case
+			 * the vap will be marked with IEEE80211_FEXT_SCANREQ
+			 * and the scan request parameters will be present
+			 * in iv_scanreq.  Otherwise we do the default.
+			*/
+			if (vap->iv_flags_ext & IEEE80211_FEXT_SCANREQ) {
+				ieee80211_check_scan(vap,
+				    vap->iv_scanreq_flags,
+				    vap->iv_scanreq_duration,
+				    vap->iv_scanreq_mindwell,
+				    vap->iv_scanreq_maxdwell,
+				    vap->iv_scanreq_nssid, vap->iv_scanreq_ssid);
+				vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANREQ;
+			} else
+				ieee80211_check_scan_current(vap);
+				break;
 		default:
 			break;
 		}
@@ -141,12 +169,128 @@ mesh_newstate(struct ieee80211vap *vap, 
 	return 0;
 }
 
+/*
+ * Decide if a received management frame should be
+ * printed when debugging is enabled.  This filters some
+ * of the less interesting frames that come frequently
+ * (e.g. beacons).
+ */
+static __inline int
+doprint(struct ieee80211vap *vap, int subtype)
+{
+	switch (subtype) {
+	case IEEE80211_FC0_SUBTYPE_BEACON:
+		return (vap->iv_ic->ic_flags & IEEE80211_F_SCAN);
+	case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
+		return 1;
+	}
+	return 1;
+}
+
 static int
 mesh_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int noise,
     uint32_t rstamp)
 {
+	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211com *ic = ni->ni_ic;
+	struct ifnet *ifp = vap->iv_ifp;
+	struct ieee80211_frame *wh;
+	int need_tap;
+	uint8_t dir, type, subtype;
 
-	return 0;
+	KASSERT(ni != NULL, ("null node"));
+	ni->ni_inact = ni->ni_inact_reload;
+
+	need_tap = 1;			/* mbuf need to be tapped. */
+	type = -1;			/* undefined */
+
+	if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
+		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+		    ni->ni_macaddr, NULL,
+		    "too short (1): len %u", m->m_pkthdr.len);
+		vap->iv_stats.is_rx_tooshort++;
+		goto out;
+	}
+	/*
+	 * Bit of a cheat here, we use a pointer for a 3-address
+	 * frame format but don't reference fields past outside
+	 * ieee80211_frame_min w/o first validating the data is
+	 * present.
+	*/
+	wh = mtod(m, struct ieee80211_frame *);
+
+	if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
+	    IEEE80211_FC0_VERSION_0) {
+		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+		    ni->ni_macaddr, NULL, "wrong version %x", wh->i_fc[0]);
+		vap->iv_stats.is_rx_badversion++;
+		goto err;
+	}
+
+	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
+	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+	if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
+	}
+
+	switch (type) {
+	case IEEE80211_FC0_TYPE_DATA:
+	case IEEE80211_FC0_TYPE_MGT:
+		vap->iv_stats.is_rx_mgmt++;
+		IEEE80211_NODE_STAT(ni, rx_mgmt);
+		if (dir != IEEE80211_FC1_DIR_NODS) {
+			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
+			    wh, "data", "incorrect dir 0x%x", dir);
+			vap->iv_stats.is_rx_wrongdir++;
+			goto err;
+		}
+		if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) {
+			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+			    ni->ni_macaddr, "mgt", "too short: len %u",
+			    m->m_pkthdr.len);
+			vap->iv_stats.is_rx_tooshort++;
+			goto out;
+		}
+#ifdef IEEE80211_DEBUG
+		if ((ieee80211_msg_debug(vap) && doprint(vap, subtype)) ||
+		    ieee80211_msg_dumppkts(vap)) {
+			if_printf(ifp, "received %s from %s rssi %d\n",
+			    ieee80211_mgt_subtype_name[subtype >>
+			    IEEE80211_FC0_SUBTYPE_SHIFT],
+			    ether_sprintf(wh->i_addr2), rssi);
+		}
+#endif
+		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
+			IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
+			    wh, NULL, "%s", "WEP set but not permitted");
+			vap->iv_stats.is_rx_mgtdiscard++; /* XXX */
+			goto out;
+		}
+		if (bpf_peers_present(vap->iv_rawbpf))
+			bpf_mtap(vap->iv_rawbpf, m);
+		vap->iv_recv_mgmt(ni, m, subtype, rssi, noise, rstamp);
+		m_freem(m);
+		return IEEE80211_FC0_TYPE_MGT;
+
+	case IEEE80211_FC0_TYPE_CTL:
+		vap->iv_stats.is_rx_ctl++;
+		IEEE80211_NODE_STAT(ni, rx_ctrl);
+		goto out;
+	default:
+		IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
+		    wh, "bad", "frame type 0x%x", type);
+		/* should not come here */
+		break;
+        }
+err:
+	ifp->if_ierrors++;
+out:
+	if (m != NULL) {
+		if (bpf_peers_present(vap->iv_rawbpf) && need_tap)
+			bpf_mtap(vap->iv_rawbpf, m);
+		m_freem(m);
+	}
+	return type;
 }
 
 
@@ -154,8 +298,8 @@ static void
 mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype,
     int rssi, int noise, uint32_t rstamp)
 {
-	/*struct ieee80211vap *vap = ni->ni_vap;
-	struct ieee80211com *ic = ni->ni_ic;*/
+	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211_frame *wh;
 	uint8_t *frm, *efrm;
 
@@ -168,15 +312,63 @@ mesh_recv_mgmt(struct ieee80211_node *ni
 	{
 		struct ieee80211_scanparams scan;
 
-		/* Parse beacons to discover mesh neighbours */
+		/*
+		 * We process beacon/probe response
+		 * frames to discover neighbors.
+		 */
 		if (ieee80211_parse_beacon(ni, m0, &scan) != 0)
 			return;
+		/*
+		 * Count frame now that we know it's to be processed.
+		 */
+		if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
+			vap->iv_stats.is_rx_beacon++;           /* XXX remove */
+			IEEE80211_NODE_STAT(ni, rx_beacons);
+		} else
+			IEEE80211_NODE_STAT(ni, rx_proberesp);
+		/*
+		 * If scanning, just pass information to the scan module.
+		 */
+		if (ic->ic_flags & IEEE80211_F_SCAN) {
+			if (ic->ic_flags_ext & IEEE80211_FEXT_PROBECHAN) {
+				/*
+				 * Actively scanning a channel marked passive;
+				 * send a probe request now that we know there
+				 * is 802.11 traffic present.
+				 *
+				 * XXX check if the beacon we recv'd gives
+				 * us what we need and suppress the probe req
+				 */
+				ieee80211_probe_curchan(vap, 1);
+				ic->ic_flags_ext &= ~IEEE80211_FEXT_PROBECHAN;
+			}
+			ieee80211_add_scan(vap, &scan, wh,
+			    subtype, rssi, noise, rstamp);
+			return;
+		}
 		break;
 	}
+	case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
+		break;
+	case IEEE80211_FC0_SUBTYPE_ACTION:
+		break;
+	case IEEE80211_FC0_SUBTYPE_AUTH:
+	case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
+	case IEEE80211_FC0_SUBTYPE_REASSOC_REQ:
+	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
+	case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
+	case IEEE80211_FC0_SUBTYPE_DEAUTH:
+	case IEEE80211_FC0_SUBTYPE_DISASSOC:
+		IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
+		    wh, NULL, "%s", "not handled");
+		vap->iv_stats.is_rx_mgtdiscard++;
+		return;
 	default:
+		IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY,
+		    wh, "mgt", "subtype 0x%x not handled", subtype);
+		vap->iv_stats.is_rx_badsubtype++;
 		break;
 	}
-
 }
 
 

Modified: projects/mesh11s/sys/net80211/ieee80211_scan_sta.c
==============================================================================
--- projects/mesh11s/sys/net80211/ieee80211_scan_sta.c	Fri Apr 24 10:18:06 2009	(r191458)
+++ projects/mesh11s/sys/net80211/ieee80211_scan_sta.c	Fri Apr 24 10:19:25 2009	(r191459)
@@ -112,21 +112,22 @@ static void sta_flush_table(struct sta_t
  * contents explains why.  The following flags are or'd to to this
  * mask and can be used to figure out why the entry was rejected.
  */
-#define	MATCH_CHANNEL		0x0001	/* channel mismatch */
-#define	MATCH_CAPINFO		0x0002	/* capabilities mismatch, e.g. no ess */
-#define	MATCH_PRIVACY		0x0004	/* privacy mismatch */
-#define	MATCH_RATE		0x0008	/* rate set mismatch */
-#define	MATCH_SSID		0x0010	/* ssid mismatch */
-#define	MATCH_BSSID		0x0020	/* bssid mismatch */
-#define	MATCH_FAILS		0x0040	/* too many failed auth attempts */
-#define	MATCH_NOTSEEN		0x0080	/* not seen in recent scans */
-#define	MATCH_RSSI		0x0100	/* rssi deemed too low to use */
-#define	MATCH_CC		0x0200	/* country code mismatch */
-#define	MATCH_TDMA_NOIE		0x0400	/* no TDMA ie */
-#define	MATCH_TDMA_NOTMASTER	0x0800	/* not TDMA master */
-#define	MATCH_TDMA_NOSLOT	0x1000	/* all TDMA slots occupied */
-#define	MATCH_TDMA_LOCAL	0x2000	/* local address */
-#define	MATCH_TDMA_VERSION	0x4000	/* protocol version mismatch */
+#define	MATCH_CHANNEL		0x00001	/* channel mismatch */
+#define	MATCH_CAPINFO		0x00002	/* capabilities mismatch, e.g. no ess */
+#define	MATCH_PRIVACY		0x00004	/* privacy mismatch */
+#define	MATCH_RATE		0x00008	/* rate set mismatch */
+#define	MATCH_SSID		0x00010	/* ssid mismatch */
+#define	MATCH_BSSID		0x00020	/* bssid mismatch */
+#define	MATCH_FAILS		0x00040	/* too many failed auth attempts */
+#define	MATCH_NOTSEEN		0x00080	/* not seen in recent scans */
+#define	MATCH_RSSI		0x00100	/* rssi deemed too low to use */
+#define	MATCH_CC		0x00200	/* country code mismatch */
+#define	MATCH_TDMA_NOIE		0x00400	/* no TDMA ie */
+#define	MATCH_TDMA_NOTMASTER	0x00800	/* not TDMA master */
+#define	MATCH_TDMA_NOSLOT	0x01000	/* all TDMA slots occupied */
+#define	MATCH_TDMA_LOCAL	0x02000	/* local address */
+#define	MATCH_TDMA_VERSION	0x04000	/* protocol version mismatch */
+#define	MATCH_MESH_ID		0x10000	/* no MESH ID ie */
 static int match_bss(struct ieee80211vap *,
 	const struct ieee80211_scan_state *, struct sta_entry *, int);
 static void adhoc_age(struct ieee80211_scan_state *);
@@ -989,6 +990,16 @@ match_bss(struct ieee80211vap *vap,
 #endif
 		}
 #endif /* IEEE80211_SUPPORT_TDMA */
+	} else if (vap->iv_opmode == IEEE80211_M_MBSS) {
+		/*
+		 * We are only interested in finding non IBSS/ESS nodes.
+		 */
+		if (se->se_capinfo & (IEEE80211_CAPINFO_IBSS|IEEE80211_CAPINFO_ESS))
+			fail |= MATCH_CAPINFO;
+		
+		if (vap->iv_caps & IEEE80211_C_MBSS) {
+			/* TBD */
+		}
 	} else {
 		if ((se->se_capinfo & IEEE80211_CAPINFO_ESS) == 0)
 			fail |= MATCH_CAPINFO;
@@ -1073,6 +1084,7 @@ match_bss(struct ieee80211vap *vap,
 		    fail & MATCH_TDMA_NOSLOT ? 'f' :
 		    fail & MATCH_TDMA_LOCAL ? 'l' :
 #endif
+		    fail & MATCH_MESH_ID ? 'm' :
 		    fail ? '-' : '+', ether_sprintf(se->se_macaddr));
 		printf(" %s%c", ether_sprintf(se->se_bssid),
 		    fail & MATCH_BSSID ? '!' : ' ');
@@ -1517,7 +1529,8 @@ adhoc_pick_bss(struct ieee80211_scan_sta
 	struct ieee80211_channel *chan;
 
 	KASSERT(vap->iv_opmode == IEEE80211_M_IBSS ||
-		vap->iv_opmode == IEEE80211_M_AHDEMO,
+		vap->iv_opmode == IEEE80211_M_AHDEMO ||
+		vap->iv_opmode == IEEE80211_M_MBSS,
 		("wrong opmode %u", vap->iv_opmode));
 
 	if (st->st_newscan) {
@@ -1785,6 +1798,23 @@ static const struct ieee80211_scanner ap
 	.scan_assoc_fail	= sta_assoc_fail,
 };
 
+static const struct ieee80211_scanner mesh_default = {
+	.scan_name		= "default",
+	.scan_attach		= sta_attach,
+	.scan_detach		= sta_detach,
+	.scan_start		= adhoc_start,
+	.scan_restart		= sta_restart,
+	.scan_cancel		= sta_cancel,
+	.scan_end		= adhoc_pick_bss,
+	.scan_flush		= sta_flush,
+	.scan_pickchan		= adhoc_pick_channel,
+	.scan_add		= sta_add,
+	.scan_age		= adhoc_age,
+	.scan_iterate		= sta_iterate,
+	.scan_assoc_fail	= sta_assoc_fail,
+	.scan_assoc_success	= sta_assoc_success,
+};
+
 /*
  * Module glue.
  */
@@ -1793,3 +1823,4 @@ IEEE80211_SCANNER_ALG(sta, IEEE80211_M_S
 IEEE80211_SCANNER_ALG(ibss, IEEE80211_M_IBSS, adhoc_default);
 IEEE80211_SCANNER_ALG(ahdemo, IEEE80211_M_AHDEMO, adhoc_default);
 IEEE80211_SCANNER_ALG(ap, IEEE80211_M_HOSTAP, ap_default);
+IEEE80211_SCANNER_ALG(mesh, IEEE80211_M_MBSS, mesh_default);



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