123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- 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
- @@ -1762,6 +1762,9 @@ void ieee80211_clear_fast_xmit(struct st
- int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
- const u8 *buf, size_t len,
- const u8 *dest, __be16 proto, bool unencrypted);
- +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
- @@ -672,6 +672,11 @@ void ieee80211_tx_monitor(struct ieee802
- }
- }
-
- + 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);
- if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
- --- a/net/mac80211/tx.c
- +++ b/net/mac80211/tx.c
- @@ -1914,37 +1914,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;
- @@ -1960,18 +1976,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;
- }
- @@ -2741,30 +2747,14 @@ static struct sk_buff *ieee80211_build_h
-
- skb_pull(skb, skip_header_bytes);
- padsize = ieee80211_hdr_padsize(&local->hw, hdrlen);
- - head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
- + head_need = hdrlen + encaps_len + meshhdrlen;
- head_need += padsize;
-
- - /*
- - * 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)
- @@ -3377,7 +3367,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;
- @@ -3429,10 +3418,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;
- }
|