From 59aa14a91db84e940b6732cd1ff069f0268793bf Mon Sep 17 00:00:00 2001 From: Rui Paulo Date: Sat, 11 Jul 2009 15:02:45 +0000 Subject: Implementation of the upcoming Wireless Mesh standard, 802.11s, on the net80211 wireless stack. This work is based on the March 2009 D3.0 draft standard. This standard is expected to become final next year. This includes two main net80211 modules, ieee80211_mesh.c which deals with peer link management, link metric calculation, routing table control and mesh configuration and ieee80211_hwmp.c which deals with the actually routing process on the mesh network. HWMP is the mandatory routing protocol on by the mesh standard, but others, such as RA-OLSR, can be implemented. Authentication and encryption are not implemented. There are several scripts under tools/tools/net80211/scripts that can be used to test different mesh network topologies and they also teach you how to setup a mesh vap (for the impatient: ifconfig wlan0 create wlandev ... wlanmode mesh). A new build option is available: IEEE80211_SUPPORT_MESH and it's enabled by default on GENERIC kernels for i386, amd64, sparc64 and pc98. Drivers that support mesh networks right now are: ath, ral and mwl. More information at: http://wiki.freebsd.org/WifiMesh Please note that this work is experimental. Also, please note that bridging a mesh vap with another network interface is not yet supported. Many thanks to the FreeBSD Foundation for sponsoring this project and to Sam Leffler for his support. Also, I would like to thank Gateworks Corporation for sending me a Cambria board which was used during the development of this project. Reviewed by: sam Approved by: re (kensmith) Obtained from: projects/mesh11s --- sys/dev/ath/if_ath.c | 39 ++++++++++++++++++++++++++++----------- sys/dev/ath/if_athvar.h | 1 + sys/dev/mwl/if_mwl.c | 17 +++++++++++++---- sys/dev/ral/rt2560.c | 12 +++++++++--- sys/dev/ral/rt2661.c | 9 +++++++-- 5 files changed, 58 insertions(+), 20 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 7d0eb5ebce43..c201265d6c05 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -578,6 +578,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) | IEEE80211_C_MONITOR /* monitor mode */ | IEEE80211_C_AHDEMO /* adhoc demo mode */ | IEEE80211_C_WDS /* 4-address traffic works */ + | IEEE80211_C_MBSS /* mesh point link mode */ | IEEE80211_C_SHPREAMBLE /* short preamble supported */ | IEEE80211_C_SHSLOT /* short slot time supported */ | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ @@ -655,6 +656,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) if (ath_hal_hasbursting(ah)) ic->ic_caps |= IEEE80211_C_BURST; sc->sc_hasbmask = ath_hal_hasbssidmask(ah); + sc->sc_hasbmatch = ath_hal_hasbssidmatch(ah); sc->sc_hastsfadd = ath_hal_hastsfadjust(ah); if (ath_hal_hasfastframes(ah)) ic->ic_caps |= IEEE80211_C_FF; @@ -918,6 +920,7 @@ ath_vap_create(struct ieee80211com *ic, } break; case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: needbeacon = 1; break; case IEEE80211_M_WDS: @@ -936,7 +939,6 @@ ath_vap_create(struct ieee80211com *ic, ic_opmode = IEEE80211_M_HOSTAP; else ic_opmode = ic->ic_opmode; - break; default: device_printf(sc->sc_dev, "unknown opmode %d\n", opmode); goto bad; @@ -950,7 +952,7 @@ ath_vap_create(struct ieee80211com *ic, } /* STA, AHDEMO? */ - if (opmode == IEEE80211_M_HOSTAP) { + if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_MBSS) { assign_address(sc, mac, flags & IEEE80211_CLONE_BSSID); ath_hal_setbssidmask(sc->sc_ah, sc->sc_hwbssidmask); } @@ -1042,6 +1044,7 @@ ath_vap_create(struct ieee80211com *ic, /* fall thru... */ #endif case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: sc->sc_opmode = HAL_M_HOSTAP; break; case IEEE80211_M_MONITOR: @@ -1129,7 +1132,8 @@ ath_vap_delete(struct ieee80211vap *vap) sc->sc_nstavaps--; if (sc->sc_nstavaps == 0 && sc->sc_swbmiss) sc->sc_swbmiss = 0; - } else if (vap->iv_opmode == IEEE80211_M_HOSTAP) { + } else if (vap->iv_opmode == IEEE80211_M_HOSTAP || + vap->iv_opmode == IEEE80211_M_MBSS) { reclaim_address(sc, vap->iv_myaddr); ath_hal_setbssidmask(ah, sc->sc_hwbssidmask); } @@ -2330,7 +2334,7 @@ ath_key_update_end(struct ieee80211vap *vap) * NB: older hal's add rx filter bits out of sight and we need to * blindly preserve them * o probe request frames are accepted only when operating in - * hostap, adhoc, or monitor modes + * hostap, adhoc, mesh, or monitor modes * o enable promiscuous mode * - when in monitor mode * - if interface marked PROMISC (assumes bridge setting is filtered) @@ -2343,6 +2347,7 @@ ath_key_update_end(struct ieee80211vap *vap) * - when doing s/w beacon miss (e.g. for ap+sta) * - when operating in ap mode in 11g to detect overlapping bss that * require protection + * - when operating in mesh mode to detect neighbors * o accept control frames: * - when in monitor mode * XXX BAR frames for 11n @@ -2375,6 +2380,13 @@ ath_calcrxfilter(struct ath_softc *sc) if (ic->ic_opmode == IEEE80211_M_HOSTAP && IEEE80211_IS_CHAN_ANYG(ic->ic_curchan)) rfilt |= HAL_RX_FILTER_BEACON; + if (ic->ic_opmode == IEEE80211_M_MBSS) { + rfilt |= HAL_RX_FILTER_BEACON; + if (sc->sc_hasbmatch) + rfilt |= HAL_RX_FILTER_BSSID; + else + rfilt |= HAL_RX_FILTER_PROM; + } if (ic->ic_opmode == IEEE80211_M_MONITOR) rfilt |= HAL_RX_FILTER_CONTROL; DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x, %s if_flags 0x%x\n", @@ -2500,7 +2512,8 @@ ath_updateslot(struct ifnet *ifp) * immediately. For other operation we defer the change * until beacon updates have propagated to the stations. */ - if (ic->ic_opmode == IEEE80211_M_HOSTAP) + if (ic->ic_opmode == IEEE80211_M_HOSTAP || + ic->ic_opmode == IEEE80211_M_MBSS) sc->sc_updateslot = UPDATE; else ath_setslottime(sc); @@ -2535,7 +2548,8 @@ ath_beaconq_config(struct ath_softc *sc) HAL_TXQ_INFO qi; ath_hal_gettxqueueprops(ah, sc->sc_bhalq, &qi); - if (ic->ic_opmode == IEEE80211_M_HOSTAP) { + if (ic->ic_opmode == IEEE80211_M_HOSTAP || + ic->ic_opmode == IEEE80211_M_MBSS) { /* * Always burst out beacon and CAB traffic. */ @@ -3087,9 +3101,10 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) /* extract tstamp from last beacon and convert to TU */ nexttbtt = TSF_TO_TU(LE_READ_4(ni->ni_tstamp.data + 4), LE_READ_4(ni->ni_tstamp.data)); - if (ic->ic_opmode == IEEE80211_M_HOSTAP) { + if (ic->ic_opmode == IEEE80211_M_HOSTAP || + ic->ic_opmode == IEEE80211_M_MBSS) { /* - * For multi-bss ap support beacons are either staggered + * For multi-bss ap/mesh support beacons are either staggered * evenly over N slots or burst together. For the former * arrange for the SWBA to be delivered for each slot. * Slots that are not occupied will generate nothing. @@ -3230,10 +3245,11 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) } while (nexttbtt < tsftu); } ath_beaconq_config(sc); - } else if (ic->ic_opmode == IEEE80211_M_HOSTAP) { + } else if (ic->ic_opmode == IEEE80211_M_HOSTAP || + ic->ic_opmode == IEEE80211_M_MBSS) { /* - * In AP mode we enable the beacon timers and - * SWBA interrupts to prepare beacon frames. + * In AP/mesh mode we enable the beacon timers + * and SWBA interrupts to prepare beacon frames. */ intval |= HAL_BEACON_ENA; sc->sc_imask |= HAL_INT_SWBA; /* beacon prepare */ @@ -5602,6 +5618,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) #endif case IEEE80211_M_HOSTAP: case IEEE80211_M_IBSS: + case IEEE80211_M_MBSS: /* * Allocate and setup the beacon frame. * diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 6a1ece223daa..0bd3ea2f5cb2 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -235,6 +235,7 @@ struct ath_softc { sc_outdoor : 1,/* outdoor operation */ sc_dturbo : 1,/* dynamic turbo in use */ sc_hasbmask : 1,/* bssid mask support */ + sc_hasbmatch: 1,/* bssid match disable support*/ sc_hastsfadd: 1,/* tsf adjust support */ sc_beacons : 1,/* beacons running */ sc_swbmiss : 1,/* sta mode using sw bmiss */ diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index dbbdca728352..c320cdb49c3c 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -420,6 +420,7 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc) | IEEE80211_C_IBSS /* ibss, nee adhoc, mode */ | IEEE80211_C_AHDEMO /* adhoc demo mode */ #endif + | IEEE80211_C_MBSS /* mesh point link mode */ | IEEE80211_C_WDS /* WDS supported */ | IEEE80211_C_SHPREAMBLE /* short preamble supported */ | IEEE80211_C_SHSLOT /* short slot time supported */ @@ -615,6 +616,7 @@ mwl_vap_create(struct ieee80211com *ic, IEEE80211_ADDR_COPY(mac, mac0); switch (opmode) { case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: if ((flags & IEEE80211_CLONE_MACADDR) == 0) assign_address(sc, mac, flags & IEEE80211_CLONE_BSSID); hvap = mwl_hal_newvap(mh, MWL_HAL_AP, mac); @@ -686,7 +688,7 @@ mwl_vap_create(struct ieee80211com *ic, vap->iv_key_delete = mwl_key_delete; vap->iv_key_set = mwl_key_set; #ifdef MWL_HOST_PS_SUPPORT - if (opmode == IEEE80211_M_HOSTAP) { + if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_MBSS) { vap->iv_update_ps = mwl_update_ps; mvp->mv_set_tim = vap->iv_set_tim; vap->iv_set_tim = mwl_set_tim; @@ -706,12 +708,14 @@ mwl_vap_create(struct ieee80211com *ic, switch (vap->iv_opmode) { case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: case IEEE80211_M_STA: /* * Setup sta db entry for local address. */ mwl_localstadb(vap); - if (vap->iv_opmode == IEEE80211_M_HOSTAP) + if (vap->iv_opmode == IEEE80211_M_HOSTAP || + vap->iv_opmode == IEEE80211_M_MBSS) sc->sc_napvaps++; else sc->sc_nstavaps++; @@ -753,11 +757,12 @@ mwl_vap_delete(struct ieee80211vap *vap) ieee80211_vap_detach(vap); switch (opmode) { case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: case IEEE80211_M_STA: KASSERT(hvap != NULL, ("no hal vap handle")); (void) mwl_hal_delstation(hvap, vap->iv_myaddr); mwl_hal_delvap(hvap); - if (opmode == IEEE80211_M_HOSTAP) + if (opmode == IEEE80211_M_HOSTAP || opmode == IEEE80211_M_MBSS) sc->sc_napvaps--; else sc->sc_nstavaps--; @@ -1281,6 +1286,7 @@ mwl_reset_vap(struct ieee80211vap *vap, int state) /* re-setup beacons */ if (state == IEEE80211_S_RUN && (vap->iv_opmode == IEEE80211_M_HOSTAP || + vap->iv_opmode == IEEE80211_M_MBSS || vap->iv_opmode == IEEE80211_M_IBSS)) { mwl_setapmode(vap, vap->iv_bss->ni_chan); mwl_hal_setnprotmode(hvap, @@ -4184,6 +4190,7 @@ mwl_localstadb(struct ieee80211vap *vap) mwl_setglobalkeys(vap); break; case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: error = mwl_hal_newstation(hvap, vap->iv_myaddr, 0, 0, NULL, vap->iv_flags & IEEE80211_F_WME, 0); if (error == 0) @@ -4248,7 +4255,8 @@ mwl_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) (void) mwl_peerstadb(ni, 0, 0, NULL); } else if (nstate == IEEE80211_S_CSA) { /* XXX move to below? */ - if (vap->iv_opmode == IEEE80211_M_HOSTAP) + if (vap->iv_opmode == IEEE80211_M_HOSTAP || + vap->iv_opmode == IEEE80211_M_MBSS) mwl_startcsa(vap); } else if (nstate == IEEE80211_S_CAC) { /* XXX move to below? */ @@ -4282,6 +4290,7 @@ mwl_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) mwl_localstadb(vap); switch (vap->iv_opmode) { case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: if (ostate == IEEE80211_S_CAC) { /* enable in-service radar detection */ mwl_hal_setradardetection(mh, diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index 7bb785c371a6..455b5ad8e723 100644 --- a/sys/dev/ral/rt2560.c +++ b/sys/dev/ral/rt2560.c @@ -285,6 +285,7 @@ rt2560_attach(device_t dev, int id) | IEEE80211_C_MONITOR /* monitor mode */ | IEEE80211_C_AHDEMO /* adhoc demo mode */ | IEEE80211_C_WDS /* 4-address traffic works */ + | IEEE80211_C_MBSS /* mesh point link mode */ | IEEE80211_C_SHPREAMBLE /* short preamble supported */ | IEEE80211_C_SHSLOT /* short slot time supported */ | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ @@ -391,6 +392,8 @@ rt2560_vap_create(struct ieee80211com *ic, case IEEE80211_M_AHDEMO: case IEEE80211_M_MONITOR: case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: + /* XXXRP: TBD */ if (!TAILQ_EMPTY(&ic->ic_vaps)) { if_printf(ifp, "only 1 vap supported\n"); return NULL; @@ -811,7 +814,8 @@ rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) } if (vap->iv_opmode == IEEE80211_M_HOSTAP || - vap->iv_opmode == IEEE80211_M_IBSS) { + vap->iv_opmode == IEEE80211_M_IBSS || + vap->iv_opmode == IEEE80211_M_MBSS) { m = ieee80211_beacon_alloc(ni, &rvp->ral_bo); if (m == NULL) { if_printf(ifp, "could not allocate beacon\n"); @@ -1343,7 +1347,8 @@ rt2560_beacon_expire(struct rt2560_softc *sc) struct rt2560_tx_data *data; if (ic->ic_opmode != IEEE80211_M_IBSS && - ic->ic_opmode != IEEE80211_M_HOSTAP) + ic->ic_opmode != IEEE80211_M_HOSTAP && + ic->ic_opmode != IEEE80211_M_MBSS) return; data = &sc->bcnq.data[sc->bcnq.next]; @@ -2690,7 +2695,8 @@ rt2560_init_locked(struct rt2560_softc *sc) tmp = RT2560_DROP_PHY_ERROR | RT2560_DROP_CRC_ERROR; if (ic->ic_opmode != IEEE80211_M_MONITOR) { tmp |= RT2560_DROP_CTL | RT2560_DROP_VERSION_ERROR; - if (ic->ic_opmode != IEEE80211_M_HOSTAP) + if (ic->ic_opmode != IEEE80211_M_HOSTAP && + ic->ic_opmode != IEEE80211_M_MBSS) tmp |= RT2560_DROP_TODS; if (!(ifp->if_flags & IFF_PROMISC)) tmp |= RT2560_DROP_NOT_TO_ME; diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c index 8b30c9b34bbc..9e6693f43d18 100644 --- a/sys/dev/ral/rt2661.c +++ b/sys/dev/ral/rt2661.c @@ -287,6 +287,7 @@ rt2661_attach(device_t dev, int id) | IEEE80211_C_MONITOR /* monitor mode */ | IEEE80211_C_AHDEMO /* adhoc demo mode */ | IEEE80211_C_WDS /* 4-address traffic works */ + | IEEE80211_C_MBSS /* mesh point link mode */ | IEEE80211_C_SHPREAMBLE /* short preamble supported */ | IEEE80211_C_SHSLOT /* short slot time supported */ | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ @@ -387,6 +388,8 @@ rt2661_vap_create(struct ieee80211com *ic, case IEEE80211_M_AHDEMO: case IEEE80211_M_MONITOR: case IEEE80211_M_HOSTAP: + case IEEE80211_M_MBSS: + /* XXXRP: TBD */ if (!TAILQ_EMPTY(&ic->ic_vaps)) { if_printf(ifp, "only 1 vap supported\n"); return NULL; @@ -818,7 +821,8 @@ rt2661_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) } if (vap->iv_opmode == IEEE80211_M_HOSTAP || - vap->iv_opmode == IEEE80211_M_IBSS) { + vap->iv_opmode == IEEE80211_M_IBSS || + vap->iv_opmode == IEEE80211_M_MBSS) { error = rt2661_prepare_beacon(sc, vap); if (error != 0) return error; @@ -2428,7 +2432,8 @@ rt2661_init_locked(struct rt2661_softc *sc) if (ic->ic_opmode != IEEE80211_M_MONITOR) { tmp |= RT2661_DROP_CTL | RT2661_DROP_VER_ERROR | RT2661_DROP_ACKCTS; - if (ic->ic_opmode != IEEE80211_M_HOSTAP) + if (ic->ic_opmode != IEEE80211_M_HOSTAP && + ic->ic_opmode != IEEE80211_M_MBSS) tmp |= RT2661_DROP_TODS; if (!(ifp->if_flags & IFF_PROMISC)) tmp |= RT2661_DROP_NOT_TO_ME; -- cgit v1.3