svn commit: r361822 - head/sys/net80211

Adrian Chadd adrian at FreeBSD.org
Fri Jun 5 06:21:25 UTC 2020


Author: adrian
Date: Fri Jun  5 06:21:23 2020
New Revision: 361822
URL: https://svnweb.freebsd.org/changeset/base/361822

Log:
  [net80211] Migrate short slot time configuration into per-vap and deferred taskqueue updates.
  
  The 11b/11g ERP and slot time update handling are two things which weren't
  migrated into the per-VAP state when Sam did the initial VAP work.
  That makes sense for a lot of setups where net80211 is driving radio state
  and the radio only cares about the shared state.
  
  However, as noted by a now deleted comment, the ERP and slot time updates
  aren't EXACTLY correct/accurate - they only take into account the most
  RECENTLY created VAP, and the state updates when one creates/destroys
  VAPs isn't exactly great.
  
  So:
  
  * track the short slot logic per VAP;
  * whenever the slot time configuration changes, just push it into a deferred
    task queue update so drivers don't have to serialise it themselves;
  * if a driver registers a per-VAP slot time handler then it'll just get the
    per VAP one;
  * .. if a driver registers a global one then the legacy behaviour is maintained -
    a single slot time is calculated and pushed out.
  
  Note that the calculated slot time is better than the existing logic - if ANY
  of the VAPs require long slot then it's disabled for all VAPs rather than
  whatever the last configured VAP did.
  
  Now, this isn't entirely complete - the rest of ERP tracking around short/long
  slot capable station tracking needs to be converted into per-VAP, as well
  as the preamble/barker flags.  Luckily those also can be done in a similar
  fashion - keep per-VAP counters/flags and unify them before doing the driver
  update.  I'll defer that work until later.
  
  All the existing drivers can keep doing what they're doing with the global
  slot time flags as that is maintained. One driver (iwi) used the per-VAP
  flags instead of the ic flags, so now that driver will work properly.
  
  This unblocks some ath10k porting work as the firmware takes the slot time
  configuration per-VAP rather than globally, and some firmware handles
  STA+AP and STA+STA (on same/different channels) configurations where
  the firmware will switch slot time as appropriate.
  
  Tested:
  
  * AR9380, STA/AP mode
  * AR9880 (ath10k), STA mode

Modified:
  head/sys/net80211/ieee80211.c
  head/sys/net80211/ieee80211_node.c
  head/sys/net80211/ieee80211_output.c
  head/sys/net80211/ieee80211_phy.h
  head/sys/net80211/ieee80211_proto.c
  head/sys/net80211/ieee80211_proto.h
  head/sys/net80211/ieee80211_sta.c
  head/sys/net80211/ieee80211_var.h

Modified: head/sys/net80211/ieee80211.c
==============================================================================
--- head/sys/net80211/ieee80211.c	Fri Jun  5 06:07:23 2020	(r361821)
+++ head/sys/net80211/ieee80211.c	Fri Jun  5 06:21:23 2020	(r361822)
@@ -645,6 +645,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ie
 	ieee80211_scan_vattach(vap);
 	ieee80211_regdomain_vattach(vap);
 	ieee80211_radiotap_vattach(vap);
+	ieee80211_vap_reset_erp(vap);
 	ieee80211_ratectl_set(vap, IEEE80211_RATECTL_NONE);
 
 	return 0;
@@ -2200,7 +2201,7 @@ ieee80211_setmode(struct ieee80211com *ic, enum ieee80
 		ieee80211_setbasicrates(&ic->ic_sup_rates[mode], mode);
 
 	ic->ic_curmode = mode;
-	ieee80211_reset_erp(ic);	/* reset ERP state */
+	ieee80211_reset_erp(ic);	/* reset global ERP state */
 
 	return 0;
 }

Modified: head/sys/net80211/ieee80211_node.c
==============================================================================
--- head/sys/net80211/ieee80211_node.c	Fri Jun  5 06:07:23 2020	(r361821)
+++ head/sys/net80211/ieee80211_node.c	Fri Jun  5 06:21:23 2020	(r361822)
@@ -446,7 +446,7 @@ ieee80211_reset_bss(struct ieee80211vap *vap)
 
 	ieee80211_node_table_reset(&ic->ic_sta, vap);
 	/* XXX multi-bss: wrong */
-	ieee80211_reset_erp(ic);
+	ieee80211_vap_reset_erp(vap);
 
 	ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);
 	KASSERT(ni != NULL, ("unable to setup initial BSS node"));
@@ -682,7 +682,7 @@ ieee80211_ibss_merge(struct ieee80211_node *ni)
 		"%s: new bssid %s: %s preamble, %s slot time%s\n", __func__,
 		ether_sprintf(ni->ni_bssid),
 		ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
-		ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
+		vap->iv_flags&IEEE80211_F_SHSLOT ? "short" : "long",
 		ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : ""
 	);
 	return ieee80211_sta_join1(ieee80211_ref_node(ni));
@@ -881,7 +881,7 @@ ieee80211_sta_join1(struct ieee80211_node *selbs)
 	 * the auto-select case; this should be redundant if the
 	 * mode is locked.
 	 */
-	ieee80211_reset_erp(ic);
+	ieee80211_vap_reset_erp(vap);
 	ieee80211_wme_initparams(vap);
 
 	if (vap->iv_opmode == IEEE80211_M_STA) {
@@ -2645,6 +2645,7 @@ static void
 ieee80211_node_join_11g(struct ieee80211_node *ni)
 {
 	struct ieee80211com *ic = ni->ni_ic;
+	struct ieee80211vap *vap = ni->ni_vap;
 
 	IEEE80211_LOCK_ASSERT(ic);
 
@@ -2660,14 +2661,13 @@ ieee80211_node_join_11g(struct ieee80211_node *ni)
 		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni,
 		    "station needs long slot time, count %d",
 		    ic->ic_longslotsta);
-		/* XXX vap's w/ conflicting needs won't work */
 		if (!IEEE80211_IS_CHAN_108G(ic->ic_bsschan)) {
 			/*
 			 * Don't force slot time when switched to turbo
 			 * mode as non-ERP stations won't be present; this
 			 * need only be done when on the normal G channel.
 			 */
-			ieee80211_set_shortslottime(ic, 0);
+			ieee80211_vap_set_shortslottime(vap, 0);
 		}
 	}
 	/*
@@ -2757,7 +2757,7 @@ ieee80211_node_join(struct ieee80211_node *ni, int res
 	    "station associated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s%s%s",
 	    IEEE80211_NODE_AID(ni),
 	    ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
-	    ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
+	    vap->iv_flags & IEEE80211_F_SHSLOT ? "short" : "long",
 	    ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "",
 	    ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
 	    /* XXX update for VHT string */
@@ -2810,6 +2810,7 @@ static void
 ieee80211_node_leave_11g(struct ieee80211_node *ni)
 {
 	struct ieee80211com *ic = ni->ni_ic;
+	struct ieee80211vap *vap = ni->ni_vap;
 
 	IEEE80211_LOCK_ASSERT(ic);
 
@@ -2838,7 +2839,7 @@ ieee80211_node_leave_11g(struct ieee80211_node *ni)
 				    IEEE80211_MSG_ASSOC,
 				    "%s: re-enable use of short slot time\n",
 				    __func__);
-				ieee80211_set_shortslottime(ic, 1);
+				ieee80211_vap_set_shortslottime(vap, 1);
 			}
 		}
 	}

Modified: head/sys/net80211/ieee80211_output.c
==============================================================================
--- head/sys/net80211/ieee80211_output.c	Fri Jun  5 06:07:23 2020	(r361821)
+++ head/sys/net80211/ieee80211_output.c	Fri Jun  5 06:21:23 2020	(r361822)
@@ -2522,7 +2522,7 @@ ieee80211_getcapinfo(struct ieee80211vap *vap, struct 
 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
 	    IEEE80211_IS_CHAN_2GHZ(chan))
 		capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
-	if (ic->ic_flags & IEEE80211_F_SHSLOT)
+	if (vap->iv_flags & IEEE80211_F_SHSLOT)
 		capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
 	if (IEEE80211_IS_CHAN_5GHZ(chan) && (vap->iv_flags & IEEE80211_F_DOTH))
 		capinfo |= IEEE80211_CAPINFO_SPECTRUM_MGMT;

Modified: head/sys/net80211/ieee80211_phy.h
==============================================================================
--- head/sys/net80211/ieee80211_phy.h	Fri Jun  5 06:07:23 2020	(r361821)
+++ head/sys/net80211/ieee80211_phy.h	Fri Jun  5 06:21:23 2020	(r361822)
@@ -55,8 +55,23 @@
 #define IEEE80211_DUR_SHSLOT	9	/* ERP short slottime */
 #define IEEE80211_DUR_OFDM_SLOT	9	/* OFDM slottime */
 
+/*
+ * For drivers that don't implement per-VAP slot time
+ * (ie, they rely on net80211 figuring out the union
+ * between VAPs to program a single radio) - return
+ * the current radio configured slot time.
+ */
 #define IEEE80211_GET_SLOTTIME(ic) \
 	((ic->ic_flags & IEEE80211_F_SHSLOT) ? \
+	    IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT)
+
+/*
+ * For drivers that implement per-VAP slot time; look
+ * at the per-VAP flags to determine whether this VAP
+ * is in short or long slot time.
+ */
+#define IEEE80211_VAP_GET_SLOTTIME(vap) \
+	((vap->iv_flags & IEEE80211_F_SHSLOT) ? \
 	    IEEE80211_DUR_SHSLOT : IEEE80211_DUR_SLOT)
 
 /*

Modified: head/sys/net80211/ieee80211_proto.c
==============================================================================
--- head/sys/net80211/ieee80211_proto.c	Fri Jun  5 06:07:23 2020	(r361821)
+++ head/sys/net80211/ieee80211_proto.c	Fri Jun  5 06:21:23 2020	(r361822)
@@ -244,6 +244,7 @@ static void update_promisc(void *, int);
 static void update_channel(void *, int);
 static void update_chw(void *, int);
 static void vap_update_wme(void *, int);
+static void vap_update_slot(void *, int);
 static void restart_vaps(void *, int);
 static void ieee80211_newstate_cb(void *, int);
 
@@ -340,6 +341,7 @@ ieee80211_proto_vattach(struct ieee80211vap *vap)
 	TASK_INIT(&vap->iv_nstate_task, 0, ieee80211_newstate_cb, vap);
 	TASK_INIT(&vap->iv_swbmiss_task, 0, beacon_swmiss, vap);
 	TASK_INIT(&vap->iv_wme_task, 0, vap_update_wme, vap);
+	TASK_INIT(&vap->iv_slot_task, 0, vap_update_slot, vap);
 	/*
 	 * Install default tx rate handling: no fixed rate, lowest
 	 * supported rate for mgmt and multicast frames.  Default
@@ -750,24 +752,39 @@ ieee80211_fix_rate(struct ieee80211_node *ni,
 
 /*
  * Reset 11g-related state.
+ *
+ * This is for per-VAP ERP/11g state.
+ *
+ * Eventually everything in ieee80211_reset_erp() will be
+ * per-VAP and in here.
  */
 void
-ieee80211_reset_erp(struct ieee80211com *ic)
+ieee80211_vap_reset_erp(struct ieee80211vap *vap)
 {
-	ic->ic_flags &= ~IEEE80211_F_USEPROT;
-	ic->ic_nonerpsta = 0;
-	ic->ic_longslotsta = 0;
+	struct ieee80211com *ic = vap->iv_ic;
+
 	/*
 	 * Short slot time is enabled only when operating in 11g
 	 * and not in an IBSS.  We must also honor whether or not
 	 * the driver is capable of doing it.
 	 */
-	ieee80211_set_shortslottime(ic,
+	ieee80211_vap_set_shortslottime(vap,
 		IEEE80211_IS_CHAN_A(ic->ic_curchan) ||
 		IEEE80211_IS_CHAN_HT(ic->ic_curchan) ||
 		(IEEE80211_IS_CHAN_ANYG(ic->ic_curchan) &&
-		ic->ic_opmode == IEEE80211_M_HOSTAP &&
+		vap->iv_opmode == IEEE80211_M_HOSTAP &&
 		(ic->ic_caps & IEEE80211_C_SHSLOT)));
+}
+
+/*
+ * Reset 11g-related state.
+ */
+void
+ieee80211_reset_erp(struct ieee80211com *ic)
+{
+	ic->ic_flags &= ~IEEE80211_F_USEPROT;
+	ic->ic_nonerpsta = 0;
+	ic->ic_longslotsta = 0;
 	/*
 	 * Set short preamble and ERP barker-preamble flags.
 	 */
@@ -782,18 +799,94 @@ ieee80211_reset_erp(struct ieee80211com *ic)
 }
 
 /*
+ * Deferred slot time update.
+ *
+ * For per-VAP slot time configuration, call the VAP
+ * method if the VAP requires it.  Otherwise, just call the
+ * older global method.
+ *
+ * If the per-VAP method is called then it's expected that
+ * the driver/firmware will take care of turning the per-VAP
+ * flags into slot time configuration.
+ *
+ * If the per-VAP method is not called then the global flags will be
+ * flipped into sync with the VAPs; ic_flags IEEE80211_F_SHSLOT will
+ * be set only if all of the vaps will have it set.
+ */
+static void
+vap_update_slot(void *arg, int npending)
+{
+	struct ieee80211vap *vap = arg;
+	struct ieee80211com *ic = vap->iv_ic;
+	struct ieee80211vap *iv;
+	int num_shslot = 0, num_lgslot = 0;
+
+	/*
+	 * Per-VAP path - we've already had the flags updated;
+	 * so just notify the driver and move on.
+	 */
+	if (vap->iv_updateslot != NULL) {
+		vap->iv_updateslot(vap);
+		return;
+	}
+
+	/*
+	 * Iterate over all of the VAP flags to update the
+	 * global flag.
+	 *
+	 * If all vaps have short slot enabled then flip on
+	 * short slot.  If any vap has it disabled then
+	 * we leave it globally disabled.  This should provide
+	 * correct behaviour in a multi-BSS scenario where
+	 * at least one VAP has short slot disabled for some
+	 * reason.
+	 */
+	IEEE80211_LOCK(ic);
+	TAILQ_FOREACH(iv, &ic->ic_vaps, iv_next) {
+		if (iv->iv_flags & IEEE80211_F_SHSLOT)
+			num_shslot++;
+		else
+			num_lgslot++;
+	}
+	IEEE80211_UNLOCK(ic);
+
+	/*
+	 * It looks backwards but - if the number of short slot VAPs
+	 * is zero then we're not short slot.  Else, we have one
+	 * or more short slot VAPs and we're checking to see if ANY
+	 * of them have short slot disabled.
+	 */
+	if (num_shslot == 0)
+		ic->ic_flags &= ~IEEE80211_F_SHSLOT;
+	else if (num_lgslot == 0)
+		ic->ic_flags |= IEEE80211_F_SHSLOT;
+
+	/*
+	 * Call the driver with our new global slot time flags.
+	 */
+	ic->ic_updateslot(ic);
+}
+
+/*
  * Set the short slot time state and notify the driver.
+ *
+ * This is the per-VAP slot time state.
  */
 void
-ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff)
+ieee80211_vap_set_shortslottime(struct ieee80211vap *vap, int onoff)
 {
+	struct ieee80211com *ic = vap->iv_ic;
+
+	/*
+	 * Only modify the per-VAP slot time.
+	 */
 	if (onoff)
-		ic->ic_flags |= IEEE80211_F_SHSLOT;
+		vap->iv_flags |= IEEE80211_F_SHSLOT;
 	else
-		ic->ic_flags &= ~IEEE80211_F_SHSLOT;
-	/* notify driver */
-	if (ic->ic_updateslot != NULL)
-		ic->ic_updateslot(ic);
+		vap->iv_flags &= ~IEEE80211_F_SHSLOT;
+
+	/* schedule the deferred slot flag update and update */
+	ieee80211_runtask(ic, &vap->iv_slot_task);
 }
 
 /*

Modified: head/sys/net80211/ieee80211_proto.h
==============================================================================
--- head/sys/net80211/ieee80211_proto.h	Fri Jun  5 06:07:23 2020	(r361821)
+++ head/sys/net80211/ieee80211_proto.h	Fri Jun  5 06:21:23 2020	(r361822)
@@ -154,8 +154,9 @@ uint16_t ieee80211_getcapinfo(struct ieee80211vap *,
 struct ieee80211_wme_state;
 uint8_t * ieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme);
 
+void	ieee80211_vap_reset_erp(struct ieee80211vap *);
 void	ieee80211_reset_erp(struct ieee80211com *);
-void	ieee80211_set_shortslottime(struct ieee80211com *, int onoff);
+void	ieee80211_vap_set_shortslottime(struct ieee80211vap *, int onoff);
 int	ieee80211_iserp_rateset(const struct ieee80211_rateset *);
 void	ieee80211_setbasicrates(struct ieee80211_rateset *,
 		enum ieee80211_phymode);

Modified: head/sys/net80211/ieee80211_sta.c
==============================================================================
--- head/sys/net80211/ieee80211_sta.c	Fri Jun  5 06:07:23 2020	(r361821)
+++ head/sys/net80211/ieee80211_sta.c	Fri Jun  5 06:21:23 2020	(r361822)
@@ -1435,7 +1435,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *
 				 * NB: we assume short preamble doesn't
 				 *     change dynamically
 				 */
-				ieee80211_set_shortslottime(ic,
+				ieee80211_vap_set_shortslottime(vap,
 					IEEE80211_IS_CHAN_A(ic->ic_bsschan) ||
 					(scan.capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
 				ni->ni_capinfo = (ni->ni_capinfo &~ IEEE80211_CAPINFO_SHORT_SLOTTIME)
@@ -1847,7 +1847,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *
 			ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
 			ic->ic_flags |= IEEE80211_F_USEBARKER;
 		}
-		ieee80211_set_shortslottime(ic,
+		ieee80211_vap_set_shortslottime(vap,
 			IEEE80211_IS_CHAN_A(ic->ic_curchan) ||
 			(ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
 		/*
@@ -1866,7 +1866,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *
 		    ISREASSOC(subtype) ? "re" : "",
 		    IEEE80211_NODE_AID(ni),
 		    ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
-		    ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
+		    vap->iv_flags&IEEE80211_F_SHSLOT ? "short" : "long",
 		    ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "",
 		    ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
 		    ni->ni_flags & IEEE80211_NODE_HT ?

Modified: head/sys/net80211/ieee80211_var.h
==============================================================================
--- head/sys/net80211/ieee80211_var.h	Fri Jun  5 06:07:23 2020	(r361821)
+++ head/sys/net80211/ieee80211_var.h	Fri Jun  5 06:21:23 2020	(r361822)
@@ -563,6 +563,10 @@ struct ieee80211vap {
 				    const struct wmeParams *wme_params);
 	struct task		iv_wme_task;	/* deferred VAP WME update */
 
+	/* update device state for 802.11 slot time change */
+	void			(*iv_updateslot)(struct ieee80211vap *);
+	struct task		iv_slot_task;	/* deferred slot time update */
+
 	uint64_t		iv_spare[6];
 };
 MALLOC_DECLARE(M_80211_VAP);


More information about the svn-src-head mailing list