svn commit: r191459 - projects/mesh11s/sys/net80211
Rui Paulo
rpaulo at FreeBSD.org
Fri Apr 24 10:19:26 UTC 2009
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);
More information about the svn-src-projects
mailing list