Search Linux Wireless

Re: [RFC V4 1/2] mac80211: add hw 80211 encapsulation offloading support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2019-04-10 at 09:35 +0200, John Crispin wrote:
> The driver
> needs to enable the support on a per vif basis if it finds that all
> pre-reqs are meet.

> + * @IEEE80211_HW_SUPPORTS_80211_ENCAP: Hardware/driver supports 802.11
> + *	encap for data frames.

I'm still not sure I can reconcile these ... why do you need the latter
if the driver has to enable per vif anyway?

> +int ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable);

Add documentation please. Would be better to return bool too, to be
symmetric.

> +++ b/net/mac80211/cfg.c
> @@ -2379,6 +2379,9 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
>  	if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
>  		ieee80211_check_fast_xmit_all(local);
>  
> +		if (ieee80211_is_hw_80211_encap(local))
> +			return -EINVAL;

Why not do this like TKIP and disable encap?

> +int ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable)
> +{
> +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
> +	struct ieee80211_local *local = sdata->local;
> +
> +	if (enable == sdata->hw_80211_encap)
> +		return enable;

It feels like this is missing some locking? Or at least a lock
assertion, if it's always called with a certain lock held already.

> +	if (!sdata->dev)
> +		return 0;
> +
> +	if (!ieee80211_hw_check(&local->hw, SUPPORTS_80211_ENCAP))
> +		enable = 0;
> +
> +	switch (vif->type) {
> +	case NL80211_IFTYPE_STATION:
> +		if (sdata->u.mgd.use_4addr)
> +			enable = 0;
> +		break;
> +	case NL80211_IFTYPE_AP_VLAN:
> +		if (sdata->wdev.use_4addr)
> +			enable = 0;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
> +	    (local->hw.wiphy->frag_threshold != (u32)-1))
> +		enable = 0;

Shouldn't there be some kind of TKIP check here?

> +bool ieee80211_is_hw_80211_encap(struct ieee80211_local *local)
> +{
> +	struct ieee80211_sub_if_data *sdata;
> +	bool offloaded = false;
> +
> +	mutex_lock(&local->iflist_mtx);
> +	list_for_each_entry(sdata, &local->interfaces, list) {
> +		if (sdata->hw_80211_encap) {
> +			offloaded = true;
> +			break;
> +		}
> +	}
> +	mutex_unlock(&local->iflist_mtx);

This might be better with RCU, though for proper usage you'd actually
have to call it with the mutex held, otherwise it can change while
you're iterating ...

> +	/* TKIP countermeasures wont work on encap offload mode */
> +	if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
> +		ieee80211_set_hw_80211_encap(&sdata->vif, 0);

false.

> @@ -197,6 +201,9 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
>  			  key->conf.keyidx,
>  			  sta ? sta->sta.addr : bcast_addr, ret);
>  
> +	if (sdata->hw_80211_encap)
> +		return -EINVAL;

Yeah, and this means you're also missing a "do we have a SW crypto key
right now" check above in ieee80211_set_hw_80211_encap().

> +	if (ieee80211_hw_check(hw, SUPPORTS_80211_ENCAP)) {
> +		/* mac80211 always supports monitor unless we do 802.11
> +		 * encapsulation offloading.
> +		 */
> +		hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
> +		hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
> +	}

Ok, maybe this addresses my question above about why we need both -
though it's not really clear what happens if the driver actually does
want to still enable monitor mode - which certainly we (iwlwifi) would.

> +void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
> +			      struct ieee80211_vif *vif,
> +			      struct sk_buff *skb)
> +{
> +	struct ieee80211_local *local = hw_to_local(hw);
> +	struct ieee80211_sub_if_data *sdata;
> +	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> +	struct sta_info *sta;
> +	int retry_count;
> +	int rates_idx;
> +	bool acked;
> +
> +	if (WARN_ON(!ieee80211_hw_check(hw, SUPPORTS_80211_ENCAP)))
> +		goto skip_stats_update;
> +
> +	sdata = vif_to_sdata(vif);
> +
> +	acked = !!(info->flags & IEEE80211_TX_STAT_ACK);

no need for !! with bool :-)

> +	/* check for driver support and ieee80211 encap offload */
> +	if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT) ||
> +	    sdata->hw_80211_encap)
>  		return;

That comment isn't very useful? :-)
 
> @@ -3573,6 +3576,9 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
>  		goto begin;
>  	}
>  
> +	if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
> +		goto encap_out;
> +
>  	if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags))
>  		info->flags |= IEEE80211_TX_CTL_AMPDU;

Wouldn't you still want this flag, perhaps?

Not with ath10k I guess, which offloads aggregation sessions, but still?
That's not necessarily a requirement for encap offload, is it?

> +	ieee80211_tx_stats(dev, skb->len);
> +
> +	if (sta) {
> +		sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
> +		sta->tx_stats.packets[skb_get_queue_mapping(skb)]++;
> +	}

This is something to think about, aren't we usually doing that after
encapsulation? So the counters will be off a bit now?

> +	if (WARN_ON(unlikely(!sdata->hw_80211_encap))) {

I feel I'm repeating myself - WARN_ON() includes unlikely().

johannes




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux