svn commit: r282401 - head/sys/dev/wpi
Adrian Chadd
adrian at FreeBSD.org
Sun May 3 23:39:45 UTC 2015
Author: adrian
Date: Sun May 3 23:39:44 2015
New Revision: 282401
URL: https://svnweb.freebsd.org/changeset/base/282401
Log:
Handle properly IBSS merges (works with patch from bug 199632).
PR: kern/197143
Submitted by: Andriy Voskoboinyk <s3erios at gmail.com>
Modified:
head/sys/dev/wpi/if_wpi.c
head/sys/dev/wpi/if_wpivar.h
Modified: head/sys/dev/wpi/if_wpi.c
==============================================================================
--- head/sys/dev/wpi/if_wpi.c Sun May 3 23:39:02 2015 (r282400)
+++ head/sys/dev/wpi/if_wpi.c Sun May 3 23:39:44 2015 (r282401)
@@ -174,9 +174,13 @@ static int wpi_setregdomain(struct ieee8
struct ieee80211_channel[]);
static int wpi_read_eeprom_group(struct wpi_softc *, int);
static int wpi_add_node_entry_adhoc(struct wpi_softc *);
-static void wpi_node_free(struct ieee80211_node *);
static struct ieee80211_node *wpi_node_alloc(struct ieee80211vap *,
const uint8_t mac[IEEE80211_ADDR_LEN]);
+static void wpi_node_free(struct ieee80211_node *);
+static void wpi_recv_mgmt(struct ieee80211_node *, struct mbuf *, int, int,
+ int);
+static void wpi_restore_node(void *, struct ieee80211_node *);
+static void wpi_restore_node_table(struct wpi_softc *, struct wpi_vap *);
static int wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static void wpi_calib_timeout(void *);
static void wpi_rx_done(struct wpi_softc *, struct wpi_rx_desc *,
@@ -654,6 +658,8 @@ wpi_vap_create(struct ieee80211com *ic,
/* Override with driver methods. */
vap->iv_key_set = wpi_key_set;
vap->iv_key_delete = wpi_key_delete;
+ wvp->wv_recv_mgmt = vap->iv_recv_mgmt;
+ vap->iv_recv_mgmt = wpi_recv_mgmt;
wvp->wv_newstate = vap->iv_newstate;
vap->iv_newstate = wpi_newstate;
vap->iv_update_beacon = wpi_update_beacon;
@@ -1685,6 +1691,66 @@ wpi_check_bss_filter(struct wpi_softc *s
return (sc->rxon.filter & htole32(WPI_FILTER_BSS)) != 0;
}
+static void
+wpi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype, int rssi,
+ int nf)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct wpi_vap *wvp = WPI_VAP(vap);
+ uint64_t ni_tstamp, rx_tstamp;
+
+ wvp->wv_recv_mgmt(ni, m, subtype, rssi, nf);
+
+ if (vap->iv_opmode == IEEE80211_M_IBSS &&
+ vap->iv_state == IEEE80211_S_RUN &&
+ (subtype == IEEE80211_FC0_SUBTYPE_BEACON ||
+ subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) {
+ ni_tstamp = le64toh(ni->ni_tstamp.tsf);
+ rx_tstamp = le64toh(sc->rx_tstamp);
+
+ if (ni_tstamp >= rx_tstamp) {
+ DPRINTF(sc, WPI_DEBUG_STATE,
+ "ibss merge, tsf %ju tstamp %ju\n",
+ (uintmax_t)rx_tstamp, (uintmax_t)ni_tstamp);
+ (void) ieee80211_ibss_merge(ni);
+ }
+ }
+}
+
+static void
+wpi_restore_node(void *arg, struct ieee80211_node *ni)
+{
+ struct wpi_softc *sc = arg;
+ struct wpi_node *wn = WPI_NODE(ni);
+ int error;
+
+ WPI_NT_LOCK(sc);
+ if (wn->id != WPI_ID_UNDEFINED) {
+ wn->id = WPI_ID_UNDEFINED;
+ if ((error = wpi_add_ibss_node(sc, ni)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not add IBSS node, error %d\n",
+ __func__, error);
+ }
+ }
+ WPI_NT_UNLOCK(sc);
+}
+
+static void
+wpi_restore_node_table(struct wpi_softc *sc, struct wpi_vap *wvp)
+{
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+
+ /* Set group keys once. */
+ WPI_NT_LOCK(sc);
+ wvp->wv_gtk = 0;
+ WPI_NT_UNLOCK(sc);
+
+ ieee80211_iterate_nodes(&ic->ic_sta, wpi_restore_node, sc);
+ ieee80211_crypto_reload_keys(ic);
+}
+
/**
* Called by net80211 when ever there is a change to 80211 state machine
*/
@@ -1751,13 +1817,36 @@ wpi_newstate(struct ieee80211vap *vap, e
case IEEE80211_S_RUN:
/*
- * RUN -> RUN transition; Just restart the timers.
+ * RUN -> RUN transition:
+ * STA mode: Just restart the timers.
+ * IBSS mode: Process IBSS merge.
*/
if (vap->iv_state == IEEE80211_S_RUN) {
- WPI_RXON_LOCK(sc);
- wpi_calib_timeout(sc);
- WPI_RXON_UNLOCK(sc);
- break;
+ if (vap->iv_opmode != IEEE80211_M_IBSS) {
+ WPI_RXON_LOCK(sc);
+ wpi_calib_timeout(sc);
+ WPI_RXON_UNLOCK(sc);
+ break;
+ } else {
+ /*
+ * Drop the BSS_FILTER bit
+ * (there is no another way to change bssid).
+ */
+ WPI_RXON_LOCK(sc);
+ sc->rxon.filter &= ~htole32(WPI_FILTER_BSS);
+ if ((error = wpi_send_rxon(sc, 0, 1)) != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not send RXON\n",
+ __func__);
+ }
+ WPI_RXON_UNLOCK(sc);
+
+ /* Restore all what was lost. */
+ wpi_restore_node_table(sc, wvp);
+
+ /* XXX set conditionally? */
+ wpi_updateedca(ic);
+ }
}
/*
@@ -1945,6 +2034,7 @@ wpi_rx_done(struct wpi_softc *sc, struct
}
ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
+ sc->rx_tstamp = tail->tstamp;
if (ieee80211_radiotap_active(ic)) {
struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap;
Modified: head/sys/dev/wpi/if_wpivar.h
==============================================================================
--- head/sys/dev/wpi/if_wpivar.h Sun May 3 23:39:02 2015 (r282400)
+++ head/sys/dev/wpi/if_wpivar.h Sun May 3 23:39:44 2015 (r282401)
@@ -121,17 +121,19 @@ struct wpi_buf {
};
struct wpi_vap {
- struct ieee80211vap wv_vap;
+ struct ieee80211vap wv_vap;
- struct wpi_buf wv_bcbuf;
- struct ieee80211_beacon_offsets wv_boff;
- struct mtx wv_mtx;
-
- uint32_t wv_gtk;
-#define WPI_VAP_KEY(kid) (1 << kid)
-
- int (*wv_newstate)(struct ieee80211vap *,
- enum ieee80211_state, int);
+ struct wpi_buf wv_bcbuf;
+ struct ieee80211_beacon_offsets wv_boff;
+ struct mtx wv_mtx;
+
+ uint32_t wv_gtk;
+#define WPI_VAP_KEY(kid) (1 << kid)
+
+ int (*wv_newstate)(struct ieee80211vap *,
+ enum ieee80211_state, int);
+ void (*wv_recv_mgmt)(struct ieee80211_node *,
+ struct mbuf *, int, int, int);
};
#define WPI_VAP(vap) ((struct wpi_vap *)(vap))
@@ -180,6 +182,7 @@ struct wpi_softc {
uint32_t txq_active;
struct wpi_rx_ring rxq;
+ uint64_t rx_tstamp;
/* TX Thermal Callibration. */
struct callout calib_to;
More information about the svn-src-all
mailing list