The removed patches were applied upstream. Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
		
			
				
	
	
		
			202 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From: Felix Fietkau <nbd@nbd.name>
 | |
| Date: Sun, 17 Mar 2019 18:11:30 +0100
 | |
| Subject: [PATCH] mac80211: optimize skb resizing
 | |
| 
 | |
| When forwarding unicast packets from ethernet to batman-adv over 802.11s
 | |
| (with forwarding disabled), the typical required headroom to transmit
 | |
| encrypted packets on mt76 is 32 (802.11) + 6 (802.11s) + 8 (CCMP) +
 | |
| 2 (padding) + 6 (LLC) + 18 (batman-adv) - 14 (old ethernet header) = 58 bytes.
 | |
| 
 | |
| On systems where NET_SKB_PAD is 64 this leads to a call to pskb_expand_head
 | |
| for every packet, since mac80211 also tries to allocate 16 bytes status
 | |
| headroom for radiotap headers.
 | |
| 
 | |
| This patch fixes these unnecessary reallocations by only requiring the extra
 | |
| status headroom in ieee80211_tx_monitor()
 | |
| If however a reallocation happens before that call, the status headroom gets
 | |
| added there as well, in order to avoid double reallocation.
 | |
| 
 | |
| The patch also cleans up the code by moving the headroom calculation to
 | |
| ieee80211_skb_resize.
 | |
| 
 | |
| Signed-off-by: Felix Fietkau <nbd@nbd.name>
 | |
| ---
 | |
| 
 | |
| --- a/net/mac80211/ieee80211_i.h
 | |
| +++ b/net/mac80211/ieee80211_i.h
 | |
| @@ -1809,6 +1809,9 @@ int ieee80211_tx_control_port(struct wip
 | |
|  			      u64 *cookie);
 | |
|  int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
 | |
|  			      const u8 *buf, size_t len);
 | |
| +int ieee80211_skb_resize(struct ieee80211_local *local,
 | |
| +			 struct ieee80211_sub_if_data *sdata,
 | |
| +			 struct sk_buff *skb, int hdrlen, int hdr_add);
 | |
|  
 | |
|  /* HT */
 | |
|  void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
 | |
| --- a/net/mac80211/status.c
 | |
| +++ b/net/mac80211/status.c
 | |
| @@ -843,6 +843,11 @@ void ieee80211_tx_monitor(struct ieee802
 | |
|  	struct net_device *prev_dev = NULL;
 | |
|  	int rtap_len;
 | |
|  
 | |
| +	if (ieee80211_skb_resize(local, NULL, skb, 0, 0)) {
 | |
| +		dev_kfree_skb(skb);
 | |
| +		return;
 | |
| +	}
 | |
| +
 | |
|  	/* send frame to monitor interfaces now */
 | |
|  	rtap_len = ieee80211_tx_radiotap_len(info, status);
 | |
|  	if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
 | |
| --- a/net/mac80211/tx.c
 | |
| +++ b/net/mac80211/tx.c
 | |
| @@ -1937,37 +1937,53 @@ static bool ieee80211_tx(struct ieee8021
 | |
|  }
 | |
|  
 | |
|  /* device xmit handlers */
 | |
| -
 | |
| -static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
 | |
| -				struct sk_buff *skb,
 | |
| -				int head_need, bool may_encrypt)
 | |
| +int ieee80211_skb_resize(struct ieee80211_local *local,
 | |
| +			 struct ieee80211_sub_if_data *sdata,
 | |
| +			 struct sk_buff *skb, int hdr_len, int hdr_extra)
 | |
|  {
 | |
| -	struct ieee80211_local *local = sdata->local;
 | |
| +	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 | |
|  	struct ieee80211_hdr *hdr;
 | |
| -	bool enc_tailroom;
 | |
| -	int tail_need = 0;
 | |
| -
 | |
| -	hdr = (struct ieee80211_hdr *) skb->data;
 | |
| -	enc_tailroom = may_encrypt &&
 | |
| -		       (sdata->crypto_tx_tailroom_needed_cnt ||
 | |
| -			ieee80211_is_mgmt(hdr->frame_control));
 | |
| -
 | |
| -	if (enc_tailroom) {
 | |
| -		tail_need = IEEE80211_ENCRYPT_TAILROOM;
 | |
| -		tail_need -= skb_tailroom(skb);
 | |
| -		tail_need = max_t(int, tail_need, 0);
 | |
| +	int head_need, head_max;
 | |
| +	int tail_need, tail_max;
 | |
| +	bool enc_tailroom = false;
 | |
| +
 | |
| +	if (sdata && !hdr_len &&
 | |
| +	    !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
 | |
| +		hdr = (struct ieee80211_hdr *) skb->data;
 | |
| +		enc_tailroom = (sdata->crypto_tx_tailroom_needed_cnt ||
 | |
| +				ieee80211_is_mgmt(hdr->frame_control));
 | |
| +		hdr_len += sdata->encrypt_headroom;
 | |
| +	}
 | |
| +
 | |
| +	head_need = head_max = hdr_len;
 | |
| +	tail_need = tail_max = 0;
 | |
| +	if (!sdata) {
 | |
| +		head_need = head_max = local->tx_headroom;
 | |
| +	} else {
 | |
| +		head_max += hdr_extra;
 | |
| +		head_max += max_t(int, local->tx_headroom,
 | |
| +				  local->hw.extra_tx_headroom);
 | |
| +		head_need += local->hw.extra_tx_headroom;
 | |
| +
 | |
| +		tail_max = IEEE80211_ENCRYPT_TAILROOM;
 | |
| +		if (enc_tailroom)
 | |
| +			tail_need = tail_max;
 | |
|  	}
 | |
|  
 | |
|  	if (skb_cloned(skb) &&
 | |
|  	    (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
 | |
|  	     !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
 | |
|  		I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
 | |
| -	else if (head_need || tail_need)
 | |
| +	else if (head_need > skb_headroom(skb) ||
 | |
| +		 tail_need > skb_tailroom(skb))
 | |
|  		I802_DEBUG_INC(local->tx_expand_skb_head);
 | |
|  	else
 | |
|  		return 0;
 | |
|  
 | |
| -	if (pskb_expand_head(skb, head_need, tail_need, GFP_ATOMIC)) {
 | |
| +	head_max = max_t(int, 0, head_max - skb_headroom(skb));
 | |
| +	tail_max = max_t(int, 0, tail_max - skb_tailroom(skb));
 | |
| +
 | |
| +	if (pskb_expand_head(skb, head_max, tail_max, GFP_ATOMIC)) {
 | |
|  		wiphy_debug(local->hw.wiphy,
 | |
|  			    "failed to reallocate TX buffer\n");
 | |
|  		return -ENOMEM;
 | |
| @@ -1983,18 +1999,8 @@ void ieee80211_xmit(struct ieee80211_sub
 | |
|  	struct ieee80211_local *local = sdata->local;
 | |
|  	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 | |
|  	struct ieee80211_hdr *hdr;
 | |
| -	int headroom;
 | |
| -	bool may_encrypt;
 | |
| -
 | |
| -	may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT);
 | |
|  
 | |
| -	headroom = local->tx_headroom;
 | |
| -	if (may_encrypt)
 | |
| -		headroom += sdata->encrypt_headroom;
 | |
| -	headroom -= skb_headroom(skb);
 | |
| -	headroom = max_t(int, 0, headroom);
 | |
| -
 | |
| -	if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) {
 | |
| +	if (ieee80211_skb_resize(local, sdata, skb, 0, 0)) {
 | |
|  		ieee80211_free_txskb(&local->hw, skb);
 | |
|  		return;
 | |
|  	}
 | |
| @@ -2809,29 +2815,13 @@ static struct sk_buff *ieee80211_build_h
 | |
|  	}
 | |
|  
 | |
|  	skb_pull(skb, skip_header_bytes);
 | |
| -	head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
 | |
| +	head_need = hdrlen + encaps_len + meshhdrlen;
 | |
|  
 | |
| -	/*
 | |
| -	 * So we need to modify the skb header and hence need a copy of
 | |
| -	 * that. The head_need variable above doesn't, so far, include
 | |
| -	 * the needed header space that we don't need right away. If we
 | |
| -	 * can, then we don't reallocate right now but only after the
 | |
| -	 * frame arrives at the master device (if it does...)
 | |
| -	 *
 | |
| -	 * If we cannot, however, then we will reallocate to include all
 | |
| -	 * the ever needed space. Also, if we need to reallocate it anyway,
 | |
| -	 * make it big enough for everything we may ever need.
 | |
| -	 */
 | |
| -
 | |
| -	if (head_need > 0 || skb_cloned(skb)) {
 | |
| -		head_need += sdata->encrypt_headroom;
 | |
| -		head_need += local->tx_headroom;
 | |
| -		head_need = max_t(int, 0, head_need);
 | |
| -		if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
 | |
| -			ieee80211_free_txskb(&local->hw, skb);
 | |
| -			skb = NULL;
 | |
| -			return ERR_PTR(-ENOMEM);
 | |
| -		}
 | |
| +	if (ieee80211_skb_resize(local, sdata, skb, head_need,
 | |
| +				 sdata->encrypt_headroom)) {
 | |
| +		ieee80211_free_txskb(&local->hw, skb);
 | |
| +		skb = NULL;
 | |
| +		return ERR_PTR(-ENOMEM);
 | |
|  	}
 | |
|  
 | |
|  	if (encaps_data)
 | |
| @@ -3446,7 +3436,6 @@ static bool ieee80211_xmit_fast(struct i
 | |
|  	struct ieee80211_local *local = sdata->local;
 | |
|  	u16 ethertype = (skb->data[12] << 8) | skb->data[13];
 | |
|  	int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
 | |
| -	int hw_headroom = sdata->local->hw.extra_tx_headroom;
 | |
|  	struct ethhdr eth;
 | |
|  	struct ieee80211_tx_info *info;
 | |
|  	struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
 | |
| @@ -3498,10 +3487,7 @@ static bool ieee80211_xmit_fast(struct i
 | |
|  	 * as the may-encrypt argument for the resize to not account for
 | |
|  	 * more room than we already have in 'extra_head'
 | |
|  	 */
 | |
| -	if (unlikely(ieee80211_skb_resize(sdata, skb,
 | |
| -					  max_t(int, extra_head + hw_headroom -
 | |
| -						     skb_headroom(skb), 0),
 | |
| -					  false))) {
 | |
| +	if (unlikely(ieee80211_skb_resize(local, sdata, skb, extra_head, 0))) {
 | |
|  		kfree_skb(skb);
 | |
|  		return true;
 | |
|  	}
 |