812b12189c4754aefb51fc2c029b9d206392963d
[librecmc/librecmc.git] /
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Sun, 9 Oct 2022 20:15:46 +0200
3 Subject: [PATCH] mac80211: add support for restricting netdev features per vif
4
5 This can be used to selectively disable feature flags for checksum offload,
6 scatter/gather or GSO by changing vif->netdev_features.
7 Removing features from vif->netdev_features does not affect the netdev
8 features themselves, but instead fixes up skbs in the tx path so that the
9 offloads are not needed in the driver.
10
11 Aside from making it easier to deal with vif type based hardware limitations,
12 this also makes it possible to optimize performance on hardware without native
13 GSO support by declaring GSO support in hw->netdev_features and removing it
14 from vif->netdev_features. This allows mac80211 to handle GSO segmentation
15 after the sta lookup, but before itxq enqueue, thus reducing the number of
16 unnecessary sta lookups, as well as some other per-packet processing.
17
18 Signed-off-by: Felix Fietkau <nbd@nbd.name>
19 ---
20
21 --- a/include/net/fq_impl.h
22 +++ b/include/net/fq_impl.h
23 @@ -200,6 +200,7 @@ static void fq_tin_enqueue(struct fq *fq
24                            fq_skb_free_t free_func)
25  {
26         struct fq_flow *flow;
27 +       struct sk_buff *next;
28         bool oom;
29  
30         lockdep_assert_held(&fq->lock);
31 @@ -214,11 +215,15 @@ static void fq_tin_enqueue(struct fq *fq
32         }
33  
34         flow->tin = tin;
35 -       flow->backlog += skb->len;
36 -       tin->backlog_bytes += skb->len;
37 -       tin->backlog_packets++;
38 -       fq->memory_usage += skb->truesize;
39 -       fq->backlog++;
40 +       skb_list_walk_safe(skb, skb, next) {
41 +               skb_mark_not_on_list(skb);
42 +               flow->backlog += skb->len;
43 +               tin->backlog_bytes += skb->len;
44 +               tin->backlog_packets++;
45 +               fq->memory_usage += skb->truesize;
46 +               fq->backlog++;
47 +               __skb_queue_tail(&flow->queue, skb);
48 +       }
49  
50         if (list_empty(&flow->flowchain)) {
51                 flow->deficit = fq->quantum;
52 @@ -226,7 +231,6 @@ static void fq_tin_enqueue(struct fq *fq
53                               &tin->new_flows);
54         }
55  
56 -       __skb_queue_tail(&flow->queue, skb);
57         oom = (fq->memory_usage > fq->memory_limit);
58         while (fq->backlog > fq->limit || oom) {
59                 flow = fq_find_fattest_flow(fq);
60 --- a/include/net/mac80211.h
61 +++ b/include/net/mac80211.h
62 @@ -1807,6 +1807,10 @@ struct ieee80211_vif_cfg {
63   * @addr: address of this interface
64   * @p2p: indicates whether this AP or STA interface is a p2p
65   *     interface, i.e. a GO or p2p-sta respectively
66 + * @netdev_features: tx netdev features supported by the hardware for this
67 + *     vif. mac80211 initializes this to hw->netdev_features, and the driver
68 + *     can mask out specific tx features. mac80211 will handle software fixup
69 + *     for masked offloads (GSO, CSUM)
70   * @driver_flags: flags/capabilities the driver has for this interface,
71   *     these need to be set (or cleared) when the interface is added
72   *     or, if supported by the driver, the interface type is changed
73 @@ -1846,6 +1850,7 @@ struct ieee80211_vif {
74  
75         struct ieee80211_txq *txq;
76  
77 +       netdev_features_t netdev_features;
78         u32 driver_flags;
79         u32 offload_flags;
80  
81 --- a/net/mac80211/iface.c
82 +++ b/net/mac80211/iface.c
83 @@ -2181,6 +2181,7 @@ int ieee80211_if_add(struct ieee80211_lo
84                 ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
85                 ndev->hw_features |= ndev->features &
86                                         MAC80211_SUPPORTED_FEATURES_TX;
87 +               sdata->vif.netdev_features = local->hw.netdev_features;
88  
89                 netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops);
90  
91 --- a/net/mac80211/tx.c
92 +++ b/net/mac80211/tx.c
93 @@ -1356,7 +1356,11 @@ static struct txq_info *ieee80211_get_tx
94  
95  static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb)
96  {
97 -       IEEE80211_SKB_CB(skb)->control.enqueue_time = codel_get_time();
98 +       struct sk_buff *next;
99 +       codel_time_t now = codel_get_time();
100 +
101 +       skb_list_walk_safe(skb, skb, next)
102 +               IEEE80211_SKB_CB(skb)->control.enqueue_time = now;
103  }
104  
105  static u32 codel_skb_len_func(const struct sk_buff *skb)
106 @@ -3579,55 +3583,79 @@ ieee80211_xmit_fast_finish(struct ieee80
107         return TX_CONTINUE;
108  }
109  
110 -static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
111 -                               struct sta_info *sta,
112 -                               struct ieee80211_fast_tx *fast_tx,
113 -                               struct sk_buff *skb)
114 +static netdev_features_t
115 +ieee80211_sdata_netdev_features(struct ieee80211_sub_if_data *sdata)
116  {
117 -       struct ieee80211_local *local = sdata->local;
118 -       u16 ethertype = (skb->data[12] << 8) | skb->data[13];
119 -       int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
120 -       int hw_headroom = sdata->local->hw.extra_tx_headroom;
121 -       struct ethhdr eth;
122 -       struct ieee80211_tx_info *info;
123 -       struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
124 -       struct ieee80211_tx_data tx;
125 -       ieee80211_tx_result r;
126 -       struct tid_ampdu_tx *tid_tx = NULL;
127 -       u8 tid = IEEE80211_NUM_TIDS;
128 +       if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
129 +               return sdata->vif.netdev_features;
130  
131 -       /* control port protocol needs a lot of special handling */
132 -       if (cpu_to_be16(ethertype) == sdata->control_port_protocol)
133 -               return false;
134 +       if (!sdata->bss)
135 +               return 0;
136  
137 -       /* only RFC 1042 SNAP */
138 -       if (ethertype < ETH_P_802_3_MIN)
139 -               return false;
140 +       sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
141 +       return sdata->vif.netdev_features;
142 +}
143  
144 -       /* don't handle TX status request here either */
145 -       if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
146 -               return false;
147 +static struct sk_buff *
148 +ieee80211_tx_skb_fixup(struct sk_buff *skb, netdev_features_t features)
149 +{
150 +       if (skb_is_gso(skb)) {
151 +               struct sk_buff *segs;
152  
153 -       if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
154 -               tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
155 -               tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
156 -               if (tid_tx) {
157 -                       if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
158 -                               return false;
159 -                       if (tid_tx->timeout)
160 -                               tid_tx->last_tx = jiffies;
161 -               }
162 +               segs = skb_gso_segment(skb, features);
163 +               if (!segs)
164 +                       return skb;
165 +               if (IS_ERR(segs))
166 +                       goto free;
167 +
168 +               consume_skb(skb);
169 +               return segs;
170         }
171  
172 -       /* after this point (skb is modified) we cannot return false */
173 +       if (skb_needs_linearize(skb, features) && __skb_linearize(skb))
174 +               goto free;
175 +
176 +       if (skb->ip_summed == CHECKSUM_PARTIAL) {
177 +               int ofs = skb_checksum_start_offset(skb);
178 +
179 +               if (skb->encapsulation)
180 +                       skb_set_inner_transport_header(skb, ofs);
181 +               else
182 +                       skb_set_transport_header(skb, ofs);
183 +
184 +               if (skb_csum_hwoffload_help(skb, features))
185 +                       goto free;
186 +       }
187 +
188 +       skb_mark_not_on_list(skb);
189 +       return skb;
190 +
191 +free:
192 +       kfree_skb(skb);
193 +       return NULL;
194 +}
195 +
196 +static void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
197 +                                 struct sta_info *sta,
198 +                                 struct ieee80211_fast_tx *fast_tx,
199 +                                 struct sk_buff *skb, u8 tid, bool ampdu)
200 +{
201 +       struct ieee80211_local *local = sdata->local;
202 +       struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
203 +       struct ieee80211_tx_info *info;
204 +       struct ieee80211_tx_data tx;
205 +       ieee80211_tx_result r;
206 +       int hw_headroom = sdata->local->hw.extra_tx_headroom;
207 +       int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
208 +       struct ethhdr eth;
209  
210         skb = skb_share_check(skb, GFP_ATOMIC);
211         if (unlikely(!skb))
212 -               return true;
213 +               return;
214  
215         if ((hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) &&
216             ieee80211_amsdu_aggregate(sdata, sta, fast_tx, skb))
217 -               return true;
218 +               return;
219  
220         /* will not be crypto-handled beyond what we do here, so use false
221          * as the may-encrypt argument for the resize to not account for
222 @@ -3636,10 +3664,8 @@ static bool ieee80211_xmit_fast(struct i
223         if (unlikely(ieee80211_skb_resize(sdata, skb,
224                                           max_t(int, extra_head + hw_headroom -
225                                                      skb_headroom(skb), 0),
226 -                                         ENCRYPT_NO))) {
227 -               kfree_skb(skb);
228 -               return true;
229 -       }
230 +                                         ENCRYPT_NO)))
231 +               goto free;
232  
233         memcpy(&eth, skb->data, ETH_HLEN - 2);
234         hdr = skb_push(skb, extra_head);
235 @@ -3653,7 +3679,7 @@ static bool ieee80211_xmit_fast(struct i
236         info->control.vif = &sdata->vif;
237         info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
238                       IEEE80211_TX_CTL_DONTFRAG |
239 -                     (tid_tx ? IEEE80211_TX_CTL_AMPDU : 0);
240 +                     (ampdu ? IEEE80211_TX_CTL_AMPDU : 0);
241         info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT |
242                               u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
243                                               IEEE80211_TX_CTRL_MLO_LINK);
244 @@ -3677,16 +3703,14 @@ static bool ieee80211_xmit_fast(struct i
245         tx.key = fast_tx->key;
246  
247         if (ieee80211_queue_skb(local, sdata, sta, skb))
248 -               return true;
249 +               return;
250  
251         tx.skb = skb;
252         r = ieee80211_xmit_fast_finish(sdata, sta, fast_tx->pn_offs,
253                                        fast_tx->key, &tx);
254         tx.skb = NULL;
255 -       if (r == TX_DROP) {
256 -               kfree_skb(skb);
257 -               return true;
258 -       }
259 +       if (r == TX_DROP)
260 +               goto free;
261  
262         if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
263                 sdata = container_of(sdata->bss,
264 @@ -3694,6 +3718,56 @@ static bool ieee80211_xmit_fast(struct i
265  
266         __skb_queue_tail(&tx.skbs, skb);
267         ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false);
268 +       return;
269 +
270 +free:
271 +       kfree_skb(skb);
272 +}
273 +
274 +static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
275 +                               struct sta_info *sta,
276 +                               struct ieee80211_fast_tx *fast_tx,
277 +                               struct sk_buff *skb)
278 +{
279 +       u16 ethertype = (skb->data[12] << 8) | skb->data[13];
280 +       struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
281 +       struct tid_ampdu_tx *tid_tx = NULL;
282 +       struct sk_buff *next;
283 +       u8 tid = IEEE80211_NUM_TIDS;
284 +
285 +       /* control port protocol needs a lot of special handling */
286 +       if (cpu_to_be16(ethertype) == sdata->control_port_protocol)
287 +               return false;
288 +
289 +       /* only RFC 1042 SNAP */
290 +       if (ethertype < ETH_P_802_3_MIN)
291 +               return false;
292 +
293 +       /* don't handle TX status request here either */
294 +       if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
295 +               return false;
296 +
297 +       if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
298 +               tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
299 +               tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
300 +               if (tid_tx) {
301 +                       if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
302 +                               return false;
303 +                       if (tid_tx->timeout)
304 +                               tid_tx->last_tx = jiffies;
305 +               }
306 +       }
307 +
308 +       /* after this point (skb is modified) we cannot return false */
309 +       skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
310 +       if (!skb)
311 +               return true;
312 +
313 +       skb_list_walk_safe(skb, skb, next) {
314 +               skb_mark_not_on_list(skb);
315 +               __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid, tid_tx);
316 +       }
317 +
318         return true;
319  }
320  
321 @@ -4201,31 +4275,14 @@ void __ieee80211_subif_start_xmit(struct
322                         goto out;
323         }
324  
325 -       if (skb_is_gso(skb)) {
326 -               struct sk_buff *segs;
327 -
328 -               segs = skb_gso_segment(skb, 0);
329 -               if (IS_ERR(segs)) {
330 -                       goto out_free;
331 -               } else if (segs) {
332 -                       consume_skb(skb);
333 -                       skb = segs;
334 -               }
335 -       } else {
336 -               /* we cannot process non-linear frames on this path */
337 -               if (skb_linearize(skb))
338 -                       goto out_free;
339 -
340 -               /* the frame could be fragmented, software-encrypted, and other
341 -                * things so we cannot really handle checksum offload with it -
342 -                * fix it up in software before we handle anything else.
343 -                */
344 -               if (skb->ip_summed == CHECKSUM_PARTIAL) {
345 -                       skb_set_transport_header(skb,
346 -                                                skb_checksum_start_offset(skb));
347 -                       if (skb_checksum_help(skb))
348 -                               goto out_free;
349 -               }
350 +       /* the frame could be fragmented, software-encrypted, and other
351 +        * things so we cannot really handle checksum or GSO offload.
352 +        * fix it up in software before we handle anything else.
353 +        */
354 +       skb = ieee80211_tx_skb_fixup(skb, 0);
355 +       if (!skb) {
356 +               len = 0;
357 +               goto out;
358         }
359  
360         skb_list_walk_safe(skb, skb, next) {
361 @@ -4443,9 +4500,11 @@ normal:
362         return NETDEV_TX_OK;
363  }
364  
365 -static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
366 -                             struct sk_buff *skb, struct sta_info *sta,
367 -                             bool txpending)
368 +
369 +
370 +static bool __ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
371 +                               struct sk_buff *skb, struct sta_info *sta,
372 +                               bool txpending)
373  {
374         struct ieee80211_local *local = sdata->local;
375         struct ieee80211_tx_control control = {};
376 @@ -4454,14 +4513,6 @@ static bool ieee80211_tx_8023(struct iee
377         unsigned long flags;
378         int q = info->hw_queue;
379  
380 -       if (sta)
381 -               sk_pacing_shift_update(skb->sk, local->hw.tx_sk_pacing_shift);
382 -
383 -       ieee80211_tpt_led_trig_tx(local, skb->len);
384 -
385 -       if (ieee80211_queue_skb(local, sdata, sta, skb))
386 -               return true;
387 -
388         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
389  
390         if (local->queue_stop_reasons[q] ||
391 @@ -4488,6 +4539,26 @@ static bool ieee80211_tx_8023(struct iee
392         return true;
393  }
394  
395 +static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
396 +                             struct sk_buff *skb, struct sta_info *sta,
397 +                             bool txpending)
398 +{
399 +       struct ieee80211_local *local = sdata->local;
400 +       struct sk_buff *next;
401 +       bool ret = true;
402 +
403 +       if (ieee80211_queue_skb(local, sdata, sta, skb))
404 +               return true;
405 +
406 +       skb_list_walk_safe(skb, skb, next) {
407 +               skb_mark_not_on_list(skb);
408 +               if (!__ieee80211_tx_8023(sdata, skb, sta, txpending))
409 +                       ret = false;
410 +       }
411 +
412 +       return ret;
413 +}
414 +
415  static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
416                                 struct net_device *dev, struct sta_info *sta,
417                                 struct ieee80211_key *key, struct sk_buff *skb)
418 @@ -4495,9 +4566,13 @@ static void ieee80211_8023_xmit(struct i
419         struct ieee80211_tx_info *info;
420         struct ieee80211_local *local = sdata->local;
421         struct tid_ampdu_tx *tid_tx;
422 +       struct sk_buff *seg, *next;
423 +       unsigned int skbs = 0, len = 0;
424 +       u16 queue;
425         u8 tid;
426  
427 -       skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
428 +       queue = ieee80211_select_queue(sdata, sta, skb);
429 +       skb_set_queue_mapping(skb, queue);
430  
431         if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) &&
432             test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
433 @@ -4507,9 +4582,6 @@ static void ieee80211_8023_xmit(struct i
434         if (unlikely(!skb))
435                 return;
436  
437 -       info = IEEE80211_SKB_CB(skb);
438 -       memset(info, 0, sizeof(*info));
439 -
440         ieee80211_aggr_check(sdata, sta, skb);
441  
442         tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
443 @@ -4523,22 +4595,20 @@ static void ieee80211_8023_xmit(struct i
444                         return;
445                 }
446  
447 -               info->flags |= IEEE80211_TX_CTL_AMPDU;
448                 if (tid_tx->timeout)
449                         tid_tx->last_tx = jiffies;
450         }
451  
452 -       if (unlikely(skb->sk &&
453 -                    skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
454 -               info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
455 -                                                            &info->flags, NULL);
456 +       skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
457 +       if (!skb)
458 +               return;
459  
460 -       info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)];
461 +       info = IEEE80211_SKB_CB(skb);
462 +       memset(info, 0, sizeof(*info));
463 +       if (tid_tx)
464 +               info->flags |= IEEE80211_TX_CTL_AMPDU;
465  
466 -       dev_sw_netstats_tx_add(dev, 1, skb->len);
467 -
468 -       sta->deflink.tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len;
469 -       sta->deflink.tx_stats.packets[skb_get_queue_mapping(skb)]++;
470 +       info->hw_queue = sdata->vif.hw_queue[queue];
471  
472         if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
473                 sdata = container_of(sdata->bss,
474 @@ -4550,6 +4620,24 @@ static void ieee80211_8023_xmit(struct i
475         if (key)
476                 info->control.hw_key = &key->conf;
477  
478 +       skb_list_walk_safe(skb, seg, next) {
479 +               skbs++;
480 +               len += seg->len;
481 +               if (seg != skb)
482 +                       memcpy(IEEE80211_SKB_CB(seg), info, sizeof(*info));
483 +       }
484 +
485 +       if (unlikely(skb->sk &&
486 +                    skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS))
487 +               info->ack_frame_id = ieee80211_store_ack_skb(local, skb,
488 +                                                            &info->flags, NULL);
489 +
490 +       dev_sw_netstats_tx_add(dev, skbs, len);
491 +       sta->deflink.tx_stats.packets[queue] += skbs;
492 +       sta->deflink.tx_stats.bytes[queue] += len;
493 +
494 +       ieee80211_tpt_led_trig_tx(local, len);
495 +
496         ieee80211_tx_8023(sdata, skb, sta, false);
497  
498         return;
499 @@ -4591,6 +4679,7 @@ netdev_tx_t ieee80211_subif_start_xmit_8
500                     key->conf.cipher == WLAN_CIPHER_SUITE_TKIP))
501                 goto skip_offload;
502  
503 +       sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
504         ieee80211_8023_xmit(sdata, dev, sta, key, skb);
505         goto out;
506