Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102095983
D35841.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D35841.diff
View Options
diff --git a/sys/dev/wtap/if_wtap.c b/sys/dev/wtap/if_wtap.c
--- a/sys/dev/wtap/if_wtap.c
+++ b/sys/dev/wtap/if_wtap.c
@@ -41,6 +41,7 @@
#include <net80211/ieee80211_ratectl.h>
#include "if_medium.h"
+#include "wtap_hal/hal.h"
/*
* This _requires_ vimage to be useful.
@@ -149,10 +150,39 @@
int subtype, const struct ieee80211_rx_stats *stats, int rssi, int nf)
{
struct ieee80211vap *vap = ni->ni_vap;
+ struct wtap_softc *sc = vap->iv_ic->ic_softc;
#if 0
DWTAP_PRINTF("[%d] %s\n", myath_id(ni), __func__);
#endif
+ /*
+ * Call up first so subsequent work can use information
+ * potentially stored in the node (e.g. for ibss merge).
+ */
WTAP_VAP(vap)->av_recv_mgmt(ni, m, subtype, stats, rssi, nf);
+
+ switch (subtype) {
+ case IEEE80211_FC0_SUBTYPE_BEACON:
+ case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
+ if (vap->iv_opmode == IEEE80211_M_IBSS &&
+ vap->iv_state == IEEE80211_S_RUN &&
+ ieee80211_ibss_merge_check(ni)) {
+ uint64_t tsf = wtap_hal_get_tsf(sc->hal);
+
+ /*
+ * Handle ibss merge as needed; check the tsf on the
+ * frame before attempting the merge. The 802.11 spec
+ * says the station should change it's bssid to match
+ * the oldest station with the same ssid, where oldest
+ * is determined by the tsf. Note that hardware
+ * reconfiguration happens through callback to
+ * ath_newstate as the state machine will go from
+ * RUN -> RUN when this happens.
+ */
+ if (le64toh(ni->ni_tstamp.tsf) >= tsf)
+ (void) ieee80211_ibss_merge(ni);
+ }
+ break;
+ }
}
static int
@@ -193,7 +223,6 @@
printf("%s: cannot get mbuf\n", __func__);
return ENOMEM;
}
- callout_init(&avp->av_swba, 0);
avp->bf_node = ieee80211_ref_node(ni);
return 0;
@@ -202,7 +231,6 @@
static void
wtap_beacon_config(struct wtap_softc *sc, struct ieee80211vap *vap)
{
-
DWTAP_PRINTF("%s\n", __func__);
}
@@ -211,7 +239,10 @@
{
struct wtap_vap *avp = arg;
struct ieee80211vap *vap = arg;
+ struct wtap_softc *sc = vap->iv_ic->ic_softc;
+ struct ieee80211_frame *wh;
struct mbuf *m;
+ uint64_t tsf;
if (vap->iv_state < IEEE80211_S_RUN) {
DWTAP_PRINTF("Skip beacon, not running, state %d", vap->iv_state);
@@ -230,6 +261,11 @@
" changed size.\n",__func__);
}
+ /* Get TSF from HAL, and insert it into beacon frame */
+ tsf = wtap_hal_get_tsf(sc->hal);
+ wh = mtod(m, struct ieee80211_frame *);
+ memcpy(&wh[1], &tsf, sizeof(tsf));
+
if (ieee80211_radiotap_active_vap(vap))
ieee80211_radiotap_tx(vap, m);
@@ -264,11 +300,37 @@
ieee80211_free_node(ni);
ni = ieee80211_ref_node(vap->iv_bss);
switch (vap->iv_opmode) {
+ case IEEE80211_M_IBSS:
case IEEE80211_M_MBSS:
+ /*
+ * Stop any previous beacon callout. This may be
+ * necessary, for example, when an ibss merge
+ * causes reconfiguration; there will be a state
+ * transition from RUN->RUN that means we may
+ * be called with beacon transmission active.
+ */
+ callout_stop(&avp->av_swba);
+
error = wtap_beacon_alloc(sc, ni);
if (error != 0)
goto bad;
+
+ /*
+ * If joining an adhoc network defer beacon timer
+ * configuration to the next beacon frame so we
+ * have a current TSF to use. Otherwise we're
+ * starting an ibss/bss so there's no need to delay;
+ * if this is the first vap moving to RUN state, then
+ * beacon state needs to be [re]configured.
+ */
+ if (vap->iv_opmode == IEEE80211_M_IBSS &&
+ ni->ni_tstamp.tsf != 0)
+ break;
+
wtap_beacon_config(sc, vap);
+
+ /* Start TSF timer from now, and start s/w beacon alert */
+ wtap_hal_reset_tsf(sc->hal);
callout_reset(&avp->av_swba, avp->av_bcinterval,
wtap_beacon_intrp, vap);
break;
@@ -314,7 +376,7 @@
avp->av_md = sc->sc_md;
avp->av_bcinterval = msecs_to_ticks(BEACON_INTRERVAL + 100*sc->id);
vap = (struct ieee80211vap *) avp;
- error = ieee80211_vap_setup(ic, vap, name, unit, IEEE80211_M_MBSS,
+ error = ieee80211_vap_setup(ic, vap, name, unit, opmode,
flags | IEEE80211_CLONE_NOBEACONS, bssid);
if (error) {
free(avp, M_80211_VAP);
@@ -337,6 +399,7 @@
avp->av_dev = make_dev(&wtap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
"%s", (const char *)vap->iv_ifp->if_xname);
avp->av_dev->si_drv1 = sc;
+ callout_init(&avp->av_swba, 0);
/* TODO this is a hack to force it to choose the rate we want */
ni = ieee80211_ref_node(vap->iv_bss);
@@ -460,6 +523,13 @@
free(bf, M_WTAP_RXBUF);
return;
}
+
+ /*
+ * It's weird to do this, but sometimes wtap will
+ * receive AMPDU packets (like ping(8)) even when
+ * the ic does not supports 11n HT.
+ */
+ m->m_flags &= ~M_AMPDU;
#if 0
ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0);
#endif
@@ -585,7 +655,7 @@
ic->ic_name = sc->name;
ic->ic_phytype = IEEE80211_T_DS;
ic->ic_opmode = IEEE80211_M_MBSS;
- ic->ic_caps = IEEE80211_C_MBSS;
+ ic->ic_caps = IEEE80211_C_MBSS | IEEE80211_C_IBSS;
ic->ic_max_keyix = 128; /* A value read from Atheros ATH_KEYMAX */
diff --git a/sys/dev/wtap/if_wtapvar.h b/sys/dev/wtap/if_wtapvar.h
--- a/sys/dev/wtap/if_wtapvar.h
+++ b/sys/dev/wtap/if_wtapvar.h
@@ -134,6 +134,7 @@
int32_t id;
int32_t up;
struct wtap_medium *sc_md; /* interface medium */
+ struct wtap_hal *hal;
struct ieee80211_node* (* sc_node_alloc)
(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]);
void (*sc_node_free)(struct ieee80211_node *);
diff --git a/sys/dev/wtap/wtap_hal/hal.h b/sys/dev/wtap/wtap_hal/hal.h
--- a/sys/dev/wtap/wtap_hal/hal.h
+++ b/sys/dev/wtap/wtap_hal/hal.h
@@ -38,11 +38,19 @@
#include "../plugins/wtap_plugin.h"
#include "handler.h"
+#define HAL_TIMER_INTVAL 50 /* in msecs */
+
struct wtap_hal {
struct wtap_medium *hal_md;
struct mtx hal_mtx;
struct wtap_plugin *plugin;
struct wtap_softc *hal_devs[MAX_NBR_WTAP];
+ /* hardware information */
+ struct hw {
+ struct callout timer_intr;
+ uint32_t timer_intr_intval;
+ uint64_t tsf;
+ } hw;
};
void init_hal(struct wtap_hal *);
@@ -51,5 +59,8 @@
void deregister_plugin(struct wtap_hal *);
int32_t new_wtap(struct wtap_hal *, int32_t id);
int32_t free_wtap(struct wtap_hal *, int32_t id);
+void wtap_hal_timer_intr(void *);
+void wtap_hal_reset_tsf(struct wtap_hal *);
+uint64_t wtap_hal_get_tsf(struct wtap_hal *);
#endif
diff --git a/sys/dev/wtap/wtap_hal/hal.c b/sys/dev/wtap/wtap_hal/hal.c
--- a/sys/dev/wtap/wtap_hal/hal.c
+++ b/sys/dev/wtap/wtap_hal/hal.c
@@ -73,6 +73,9 @@
init_medium(hal->hal_md);
/* register event handler for packets */
TASK_INIT(&hal->hal_md->tx_handler->proc, 0, hal_tx_proc, hal);
+
+ callout_init_mtx(&hal->hw.timer_intr, &hal->hal_mtx, 0);
+ hal->hw.timer_intr_intval = msecs_to_ticks(HAL_TIMER_INTVAL);
}
void
@@ -182,6 +185,7 @@
sizeof(struct wtap_softc), M_WTAP, M_NOWAIT | M_ZERO);
hal->hal_devs[id]->sc_md = hal->hal_md;
hal->hal_devs[id]->id = id;
+ hal->hal_devs[id]->hal = hal;
snprintf(hal->hal_devs[id]->name, sizeof(hal->hal_devs[id]->name),
"wtap%d", id);
mtx_init(&hal->hal_devs[id]->sc_mtx, "wtap_softc mtx", NULL,
@@ -212,3 +216,33 @@
hal->hal_devs[id] = NULL;
return 0;
}
+
+void
+wtap_hal_timer_intr(void *arg)
+{
+ struct wtap_hal *hal = arg;
+ uint32_t intval = hal->hw.timer_intr_intval;
+
+ hal->hw.tsf += ticks_to_msecs(intval);
+
+ callout_schedule(&hal->hw.timer_intr, intval);
+}
+
+void
+wtap_hal_reset_tsf(struct wtap_hal *hal)
+{
+ mtx_lock(&hal->hal_mtx);
+
+ callout_stop(&hal->hw.timer_intr);
+ hal->hw.tsf = 0;
+ callout_reset(&hal->hw.timer_intr, hal->hw.timer_intr_intval,
+ wtap_hal_timer_intr, hal);
+
+ mtx_unlock(&hal->hal_mtx);
+}
+
+uint64_t
+wtap_hal_get_tsf(struct wtap_hal *hal)
+{
+ return (hal->hw.tsf);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 8, 1:45 PM (20 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14536013
Default Alt Text
D35841.diff (7 KB)
Attached To
Mode
D35841: wtap(4): Implement IBSS mode on wtap(4)
Attached
Detach File
Event Timeline
Log In to Comment