Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 May 2015 23:39:44 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r282401 - head/sys/dev/wpi
Message-ID:  <201505032339.t43NdiEX096022@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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@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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505032339.t43NdiEX096022>