Page MenuHomeFreeBSD

D35841.diff
No OneTemporary

D35841.diff

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

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)

Event Timeline