linux/net/mac80211/agg-rx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * HT handling
   4 *
   5 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
   6 * Copyright 2002-2005, Instant802 Networks, Inc.
   7 * Copyright 2005-2006, Devicescape Software, Inc.
   8 * Copyright 2006-2007  Jiri Benc <jbenc@suse.cz>
   9 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  10 * Copyright 2007-2010, Intel Corporation
  11 * Copyright(c) 2015-2017 Intel Deutschland GmbH
  12 * Copyright (C) 2018        Intel Corporation
  13 */
  14
  15/**
  16 * DOC: RX A-MPDU aggregation
  17 *
  18 * Aggregation on the RX side requires only implementing the
  19 * @ampdu_action callback that is invoked to start/stop any
  20 * block-ack sessions for RX aggregation.
  21 *
  22 * When RX aggregation is started by the peer, the driver is
  23 * notified via @ampdu_action function, with the
  24 * %IEEE80211_AMPDU_RX_START action, and may reject the request
  25 * in which case a negative response is sent to the peer, if it
  26 * accepts it a positive response is sent.
  27 *
  28 * While the session is active, the device/driver are required
  29 * to de-aggregate frames and pass them up one by one to mac80211,
  30 * which will handle the reorder buffer.
  31 *
  32 * When the aggregation session is stopped again by the peer or
  33 * ourselves, the driver's @ampdu_action function will be called
  34 * with the action %IEEE80211_AMPDU_RX_STOP. In this case, the
  35 * call must not fail.
  36 */
  37
  38#include <linux/ieee80211.h>
  39#include <linux/slab.h>
  40#include <linux/export.h>
  41#include <net/mac80211.h>
  42#include "ieee80211_i.h"
  43#include "driver-ops.h"
  44
  45static void ieee80211_free_tid_rx(struct rcu_head *h)
  46{
  47        struct tid_ampdu_rx *tid_rx =
  48                container_of(h, struct tid_ampdu_rx, rcu_head);
  49        int i;
  50
  51        for (i = 0; i < tid_rx->buf_size; i++)
  52                __skb_queue_purge(&tid_rx->reorder_buf[i]);
  53        kfree(tid_rx->reorder_buf);
  54        kfree(tid_rx->reorder_time);
  55        kfree(tid_rx);
  56}
  57
  58void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
  59                                     u16 initiator, u16 reason, bool tx)
  60{
  61        struct ieee80211_local *local = sta->local;
  62        struct tid_ampdu_rx *tid_rx;
  63        struct ieee80211_ampdu_params params = {
  64                .sta = &sta->sta,
  65                .action = IEEE80211_AMPDU_RX_STOP,
  66                .tid = tid,
  67                .amsdu = false,
  68                .timeout = 0,
  69                .ssn = 0,
  70        };
  71
  72        lockdep_assert_held(&sta->ampdu_mlme.mtx);
  73
  74        tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid],
  75                                        lockdep_is_held(&sta->ampdu_mlme.mtx));
  76
  77        if (!test_bit(tid, sta->ampdu_mlme.agg_session_valid))
  78                return;
  79
  80        RCU_INIT_POINTER(sta->ampdu_mlme.tid_rx[tid], NULL);
  81        __clear_bit(tid, sta->ampdu_mlme.agg_session_valid);
  82
  83        ht_dbg(sta->sdata,
  84               "Rx BA session stop requested for %pM tid %u %s reason: %d\n",
  85               sta->sta.addr, tid,
  86               initiator == WLAN_BACK_RECIPIENT ? "recipient" : "initiator",
  87               (int)reason);
  88
  89        if (drv_ampdu_action(local, sta->sdata, &params))
  90                sdata_info(sta->sdata,
  91                           "HW problem - can not stop rx aggregation for %pM tid %d\n",
  92                           sta->sta.addr, tid);
  93
  94        /* check if this is a self generated aggregation halt */
  95        if (initiator == WLAN_BACK_RECIPIENT && tx)
  96                ieee80211_send_delba(sta->sdata, sta->sta.addr,
  97                                     tid, WLAN_BACK_RECIPIENT, reason);
  98
  99        /*
 100         * return here in case tid_rx is not assigned - which will happen if
 101         * IEEE80211_HW_SUPPORTS_REORDERING_BUFFER is set.
 102         */
 103        if (!tid_rx)
 104                return;
 105
 106        del_timer_sync(&tid_rx->session_timer);
 107
 108        /* make sure ieee80211_sta_reorder_release() doesn't re-arm the timer */
 109        spin_lock_bh(&tid_rx->reorder_lock);
 110        tid_rx->removed = true;
 111        spin_unlock_bh(&tid_rx->reorder_lock);
 112        del_timer_sync(&tid_rx->reorder_timer);
 113
 114        call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
 115}
 116
 117void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
 118                                    u16 initiator, u16 reason, bool tx)
 119{
 120        mutex_lock(&sta->ampdu_mlme.mtx);
 121        ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx);
 122        mutex_unlock(&sta->ampdu_mlme.mtx);
 123}
 124
 125void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
 126                                  const u8 *addr)
 127{
 128        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 129        struct sta_info *sta;
 130        int i;
 131
 132        rcu_read_lock();
 133        sta = sta_info_get_bss(sdata, addr);
 134        if (!sta) {
 135                rcu_read_unlock();
 136                return;
 137        }
 138
 139        for (i = 0; i < IEEE80211_NUM_TIDS; i++)
 140                if (ba_rx_bitmap & BIT(i))
 141                        set_bit(i, sta->ampdu_mlme.tid_rx_stop_requested);
 142
 143        ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
 144        rcu_read_unlock();
 145}
 146EXPORT_SYMBOL(ieee80211_stop_rx_ba_session);
 147
 148/*
 149 * After accepting the AddBA Request we activated a timer,
 150 * resetting it after each frame that arrives from the originator.
 151 */
 152static void sta_rx_agg_session_timer_expired(struct timer_list *t)
 153{
 154        struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, session_timer);
 155        struct sta_info *sta = tid_rx->sta;
 156        u8 tid = tid_rx->tid;
 157        unsigned long timeout;
 158
 159        timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout);
 160        if (time_is_after_jiffies(timeout)) {
 161                mod_timer(&tid_rx->session_timer, timeout);
 162                return;
 163        }
 164
 165        ht_dbg(sta->sdata, "RX session timer expired on %pM tid %d\n",
 166               sta->sta.addr, tid);
 167
 168        set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
 169        ieee80211_queue_work(&sta->local->hw, &sta->ampdu_mlme.work);
 170}
 171
 172static void sta_rx_agg_reorder_timer_expired(struct timer_list *t)
 173{
 174        struct tid_ampdu_rx *tid_rx = from_timer(tid_rx, t, reorder_timer);
 175
 176        rcu_read_lock();
 177        ieee80211_release_reorder_timeout(tid_rx->sta, tid_rx->tid);
 178        rcu_read_unlock();
 179}
 180
 181static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid,
 182                                      u8 dialog_token, u16 status, u16 policy,
 183                                      u16 buf_size, u16 timeout)
 184{
 185        struct ieee80211_local *local = sdata->local;
 186        struct sk_buff *skb;
 187        struct ieee80211_mgmt *mgmt;
 188        bool amsdu = ieee80211_hw_check(&local->hw, SUPPORTS_AMSDU_IN_AMPDU);
 189        u16 capab;
 190
 191        skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
 192        if (!skb)
 193                return;
 194
 195        skb_reserve(skb, local->hw.extra_tx_headroom);
 196        mgmt = skb_put_zero(skb, 24);
 197        memcpy(mgmt->da, da, ETH_ALEN);
 198        memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
 199        if (sdata->vif.type == NL80211_IFTYPE_AP ||
 200            sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
 201            sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
 202                memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
 203        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
 204                memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
 205        else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 206                memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
 207
 208        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 209                                          IEEE80211_STYPE_ACTION);
 210
 211        skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
 212        mgmt->u.action.category = WLAN_CATEGORY_BACK;
 213        mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
 214        mgmt->u.action.u.addba_resp.dialog_token = dialog_token;
 215
 216        capab = (u16)(amsdu << 0);      /* bit 0 A-MSDU support */
 217        capab |= (u16)(policy << 1);    /* bit 1 aggregation policy */
 218        capab |= (u16)(tid << 2);       /* bit 5:2 TID number */
 219        capab |= (u16)(buf_size << 6);  /* bit 15:6 max size of aggregation */
 220
 221        mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab);
 222        mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout);
 223        mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
 224
 225        ieee80211_tx_skb(sdata, skb);
 226}
 227
 228void ___ieee80211_start_rx_ba_session(struct sta_info *sta,
 229                                      u8 dialog_token, u16 timeout,
 230                                      u16 start_seq_num, u16 ba_policy, u16 tid,
 231                                      u16 buf_size, bool tx, bool auto_seq)
 232{
 233        struct ieee80211_local *local = sta->sdata->local;
 234        struct tid_ampdu_rx *tid_agg_rx;
 235        struct ieee80211_ampdu_params params = {
 236                .sta = &sta->sta,
 237                .action = IEEE80211_AMPDU_RX_START,
 238                .tid = tid,
 239                .amsdu = false,
 240                .timeout = timeout,
 241                .ssn = start_seq_num,
 242        };
 243        int i, ret = -EOPNOTSUPP;
 244        u16 status = WLAN_STATUS_REQUEST_DECLINED;
 245        u16 max_buf_size;
 246
 247        if (tid >= IEEE80211_FIRST_TSPEC_TSID) {
 248                ht_dbg(sta->sdata,
 249                       "STA %pM requests BA session on unsupported tid %d\n",
 250                       sta->sta.addr, tid);
 251                goto end;
 252        }
 253
 254        if (!sta->sta.ht_cap.ht_supported) {
 255                ht_dbg(sta->sdata,
 256                       "STA %pM erroneously requests BA session on tid %d w/o QoS\n",
 257                       sta->sta.addr, tid);
 258                /* send a response anyway, it's an error case if we get here */
 259                goto end;
 260        }
 261
 262        if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
 263                ht_dbg(sta->sdata,
 264                       "Suspend in progress - Denying ADDBA request (%pM tid %d)\n",
 265                       sta->sta.addr, tid);
 266                goto end;
 267        }
 268
 269        if (sta->sta.he_cap.has_he)
 270                max_buf_size = IEEE80211_MAX_AMPDU_BUF;
 271        else
 272                max_buf_size = IEEE80211_MAX_AMPDU_BUF_HT;
 273
 274        /* sanity check for incoming parameters:
 275         * check if configuration can support the BA policy
 276         * and if buffer size does not exceeds max value */
 277        /* XXX: check own ht delayed BA capability?? */
 278        if (((ba_policy != 1) &&
 279             (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) ||
 280            (buf_size > max_buf_size)) {
 281                status = WLAN_STATUS_INVALID_QOS_PARAM;
 282                ht_dbg_ratelimited(sta->sdata,
 283                                   "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
 284                                   sta->sta.addr, tid, ba_policy, buf_size);
 285                goto end;
 286        }
 287        /* determine default buffer size */
 288        if (buf_size == 0)
 289                buf_size = max_buf_size;
 290
 291        /* make sure the size doesn't exceed the maximum supported by the hw */
 292        if (buf_size > sta->sta.max_rx_aggregation_subframes)
 293                buf_size = sta->sta.max_rx_aggregation_subframes;
 294        params.buf_size = buf_size;
 295
 296        ht_dbg(sta->sdata, "AddBA Req buf_size=%d for %pM\n",
 297               buf_size, sta->sta.addr);
 298
 299        /* examine state machine */
 300        lockdep_assert_held(&sta->ampdu_mlme.mtx);
 301
 302        if (test_bit(tid, sta->ampdu_mlme.agg_session_valid)) {
 303                if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
 304                        struct tid_ampdu_rx *tid_rx;
 305
 306                        ht_dbg_ratelimited(sta->sdata,
 307                                           "updated AddBA Req from %pM on tid %u\n",
 308                                           sta->sta.addr, tid);
 309                        /* We have no API to update the timeout value in the
 310                         * driver so reject the timeout update if the timeout
 311                         * changed. If if did not change, i.e., no real update,
 312                         * just reply with success.
 313                         */
 314                        rcu_read_lock();
 315                        tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
 316                        if (tid_rx && tid_rx->timeout == timeout)
 317                                status = WLAN_STATUS_SUCCESS;
 318                        else
 319                                status = WLAN_STATUS_REQUEST_DECLINED;
 320                        rcu_read_unlock();
 321                        goto end;
 322                }
 323
 324                ht_dbg_ratelimited(sta->sdata,
 325                                   "unexpected AddBA Req from %pM on tid %u\n",
 326                                   sta->sta.addr, tid);
 327
 328                /* delete existing Rx BA session on the same tid */
 329                ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
 330                                                WLAN_STATUS_UNSPECIFIED_QOS,
 331                                                false);
 332        }
 333
 334        if (ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) {
 335                ret = drv_ampdu_action(local, sta->sdata, &params);
 336                ht_dbg(sta->sdata,
 337                       "Rx A-MPDU request on %pM tid %d result %d\n",
 338                       sta->sta.addr, tid, ret);
 339                if (!ret)
 340                        status = WLAN_STATUS_SUCCESS;
 341                goto end;
 342        }
 343
 344        /* prepare A-MPDU MLME for Rx aggregation */
 345        tid_agg_rx = kzalloc(sizeof(*tid_agg_rx), GFP_KERNEL);
 346        if (!tid_agg_rx)
 347                goto end;
 348
 349        spin_lock_init(&tid_agg_rx->reorder_lock);
 350
 351        /* rx timer */
 352        timer_setup(&tid_agg_rx->session_timer,
 353                    sta_rx_agg_session_timer_expired, TIMER_DEFERRABLE);
 354
 355        /* rx reorder timer */
 356        timer_setup(&tid_agg_rx->reorder_timer,
 357                    sta_rx_agg_reorder_timer_expired, 0);
 358
 359        /* prepare reordering buffer */
 360        tid_agg_rx->reorder_buf =
 361                kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL);
 362        tid_agg_rx->reorder_time =
 363                kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
 364        if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
 365                kfree(tid_agg_rx->reorder_buf);
 366                kfree(tid_agg_rx->reorder_time);
 367                kfree(tid_agg_rx);
 368                goto end;
 369        }
 370
 371        for (i = 0; i < buf_size; i++)
 372                __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);
 373
 374        ret = drv_ampdu_action(local, sta->sdata, &params);
 375        ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
 376               sta->sta.addr, tid, ret);
 377        if (ret) {
 378                kfree(tid_agg_rx->reorder_buf);
 379                kfree(tid_agg_rx->reorder_time);
 380                kfree(tid_agg_rx);
 381                goto end;
 382        }
 383
 384        /* update data */
 385        tid_agg_rx->ssn = start_seq_num;
 386        tid_agg_rx->head_seq_num = start_seq_num;
 387        tid_agg_rx->buf_size = buf_size;
 388        tid_agg_rx->timeout = timeout;
 389        tid_agg_rx->stored_mpdu_num = 0;
 390        tid_agg_rx->auto_seq = auto_seq;
 391        tid_agg_rx->started = false;
 392        tid_agg_rx->reorder_buf_filtered = 0;
 393        tid_agg_rx->tid = tid;
 394        tid_agg_rx->sta = sta;
 395        status = WLAN_STATUS_SUCCESS;
 396
 397        /* activate it for RX */
 398        rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);
 399
 400        if (timeout) {
 401                mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout));
 402                tid_agg_rx->last_rx = jiffies;
 403        }
 404
 405end:
 406        if (status == WLAN_STATUS_SUCCESS) {
 407                __set_bit(tid, sta->ampdu_mlme.agg_session_valid);
 408                __clear_bit(tid, sta->ampdu_mlme.unexpected_agg);
 409                sta->ampdu_mlme.tid_rx_token[tid] = dialog_token;
 410        }
 411
 412        if (tx)
 413                ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
 414                                          dialog_token, status, 1, buf_size,
 415                                          timeout);
 416}
 417
 418static void __ieee80211_start_rx_ba_session(struct sta_info *sta,
 419                                            u8 dialog_token, u16 timeout,
 420                                            u16 start_seq_num, u16 ba_policy,
 421                                            u16 tid, u16 buf_size, bool tx,
 422                                            bool auto_seq)
 423{
 424        mutex_lock(&sta->ampdu_mlme.mtx);
 425        ___ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
 426                                         start_seq_num, ba_policy, tid,
 427                                         buf_size, tx, auto_seq);
 428        mutex_unlock(&sta->ampdu_mlme.mtx);
 429}
 430
 431void ieee80211_process_addba_request(struct ieee80211_local *local,
 432                                     struct sta_info *sta,
 433                                     struct ieee80211_mgmt *mgmt,
 434                                     size_t len)
 435{
 436        u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
 437        u8 dialog_token;
 438
 439        /* extract session parameters from addba request frame */
 440        dialog_token = mgmt->u.action.u.addba_req.dialog_token;
 441        timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
 442        start_seq_num =
 443                le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;
 444
 445        capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
 446        ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
 447        tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
 448        buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
 449
 450        __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
 451                                        start_seq_num, ba_policy, tid,
 452                                        buf_size, true, false);
 453}
 454
 455void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
 456                                 const u8 *addr, unsigned int tid)
 457{
 458        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 459        struct ieee80211_local *local = sdata->local;
 460        struct sta_info *sta;
 461
 462        rcu_read_lock();
 463        sta = sta_info_get_bss(sdata, addr);
 464        if (!sta)
 465                goto unlock;
 466
 467        set_bit(tid, sta->ampdu_mlme.tid_rx_manage_offl);
 468        ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
 469 unlock:
 470        rcu_read_unlock();
 471}
 472EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl);
 473
 474void ieee80211_rx_ba_timer_expired(struct ieee80211_vif *vif,
 475                                   const u8 *addr, unsigned int tid)
 476{
 477        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 478        struct ieee80211_local *local = sdata->local;
 479        struct sta_info *sta;
 480
 481        rcu_read_lock();
 482        sta = sta_info_get_bss(sdata, addr);
 483        if (!sta)
 484                goto unlock;
 485
 486        set_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired);
 487        ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
 488
 489 unlock:
 490        rcu_read_unlock();
 491}
 492EXPORT_SYMBOL(ieee80211_rx_ba_timer_expired);
 493