linux/net/mac80211/ocb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * OCB mode implementation
   4 *
   5 * Copyright: (c) 2014 Czech Technical University in Prague
   6 *            (c) 2014 Volkswagen Group Research
   7 * Author:    Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
   8 * Funded by: Volkswagen Group Research
   9 */
  10
  11#include <linux/delay.h>
  12#include <linux/if_ether.h>
  13#include <linux/skbuff.h>
  14#include <linux/if_arp.h>
  15#include <linux/etherdevice.h>
  16#include <linux/rtnetlink.h>
  17#include <net/mac80211.h>
  18#include <asm/unaligned.h>
  19
  20#include "ieee80211_i.h"
  21#include "driver-ops.h"
  22#include "rate.h"
  23
  24#define IEEE80211_OCB_HOUSEKEEPING_INTERVAL             (60 * HZ)
  25#define IEEE80211_OCB_PEER_INACTIVITY_LIMIT             (240 * HZ)
  26#define IEEE80211_OCB_MAX_STA_ENTRIES                   128
  27
  28/**
  29 * enum ocb_deferred_task_flags - mac80211 OCB deferred tasks
  30 * @OCB_WORK_HOUSEKEEPING: run the periodic OCB housekeeping tasks
  31 *
  32 * These flags are used in @wrkq_flags field of &struct ieee80211_if_ocb
  33 */
  34enum ocb_deferred_task_flags {
  35        OCB_WORK_HOUSEKEEPING,
  36};
  37
  38void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
  39                             const u8 *bssid, const u8 *addr,
  40                             u32 supp_rates)
  41{
  42        struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
  43        struct ieee80211_local *local = sdata->local;
  44        struct ieee80211_chanctx_conf *chanctx_conf;
  45        struct ieee80211_supported_band *sband;
  46        enum nl80211_bss_scan_width scan_width;
  47        struct sta_info *sta;
  48        int band;
  49
  50        /* XXX: Consider removing the least recently used entry and
  51         *      allow new one to be added.
  52         */
  53        if (local->num_sta >= IEEE80211_OCB_MAX_STA_ENTRIES) {
  54                net_info_ratelimited("%s: No room for a new OCB STA entry %pM\n",
  55                                     sdata->name, addr);
  56                return;
  57        }
  58
  59        ocb_dbg(sdata, "Adding new OCB station %pM\n", addr);
  60
  61        rcu_read_lock();
  62        chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
  63        if (WARN_ON_ONCE(!chanctx_conf)) {
  64                rcu_read_unlock();
  65                return;
  66        }
  67        band = chanctx_conf->def.chan->band;
  68        scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
  69        rcu_read_unlock();
  70
  71        sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
  72        if (!sta)
  73                return;
  74
  75        /* Add only mandatory rates for now */
  76        sband = local->hw.wiphy->bands[band];
  77        sta->sta.supp_rates[band] =
  78                ieee80211_mandatory_rates(sband, scan_width);
  79
  80        spin_lock(&ifocb->incomplete_lock);
  81        list_add(&sta->list, &ifocb->incomplete_stations);
  82        spin_unlock(&ifocb->incomplete_lock);
  83        ieee80211_queue_work(&local->hw, &sdata->work);
  84}
  85
  86static struct sta_info *ieee80211_ocb_finish_sta(struct sta_info *sta)
  87        __acquires(RCU)
  88{
  89        struct ieee80211_sub_if_data *sdata = sta->sdata;
  90        u8 addr[ETH_ALEN];
  91
  92        memcpy(addr, sta->sta.addr, ETH_ALEN);
  93
  94        ocb_dbg(sdata, "Adding new IBSS station %pM (dev=%s)\n",
  95                addr, sdata->name);
  96
  97        sta_info_move_state(sta, IEEE80211_STA_AUTH);
  98        sta_info_move_state(sta, IEEE80211_STA_ASSOC);
  99        sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
 100
 101        rate_control_rate_init(sta);
 102
 103        /* If it fails, maybe we raced another insertion? */
 104        if (sta_info_insert_rcu(sta))
 105                return sta_info_get(sdata, addr);
 106        return sta;
 107}
 108
 109static void ieee80211_ocb_housekeeping(struct ieee80211_sub_if_data *sdata)
 110{
 111        struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
 112
 113        ocb_dbg(sdata, "Running ocb housekeeping\n");
 114
 115        ieee80211_sta_expire(sdata, IEEE80211_OCB_PEER_INACTIVITY_LIMIT);
 116
 117        mod_timer(&ifocb->housekeeping_timer,
 118                  round_jiffies(jiffies + IEEE80211_OCB_HOUSEKEEPING_INTERVAL));
 119}
 120
 121void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata)
 122{
 123        struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
 124        struct sta_info *sta;
 125
 126        if (ifocb->joined != true)
 127                return;
 128
 129        sdata_lock(sdata);
 130
 131        spin_lock_bh(&ifocb->incomplete_lock);
 132        while (!list_empty(&ifocb->incomplete_stations)) {
 133                sta = list_first_entry(&ifocb->incomplete_stations,
 134                                       struct sta_info, list);
 135                list_del(&sta->list);
 136                spin_unlock_bh(&ifocb->incomplete_lock);
 137
 138                ieee80211_ocb_finish_sta(sta);
 139                rcu_read_unlock();
 140                spin_lock_bh(&ifocb->incomplete_lock);
 141        }
 142        spin_unlock_bh(&ifocb->incomplete_lock);
 143
 144        if (test_and_clear_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags))
 145                ieee80211_ocb_housekeeping(sdata);
 146
 147        sdata_unlock(sdata);
 148}
 149
 150static void ieee80211_ocb_housekeeping_timer(struct timer_list *t)
 151{
 152        struct ieee80211_sub_if_data *sdata =
 153                from_timer(sdata, t, u.ocb.housekeeping_timer);
 154        struct ieee80211_local *local = sdata->local;
 155        struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
 156
 157        set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
 158
 159        ieee80211_queue_work(&local->hw, &sdata->work);
 160}
 161
 162void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata)
 163{
 164        struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
 165
 166        timer_setup(&ifocb->housekeeping_timer,
 167                    ieee80211_ocb_housekeeping_timer, 0);
 168        INIT_LIST_HEAD(&ifocb->incomplete_stations);
 169        spin_lock_init(&ifocb->incomplete_lock);
 170}
 171
 172int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
 173                       struct ocb_setup *setup)
 174{
 175        struct ieee80211_local *local = sdata->local;
 176        struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
 177        u32 changed = BSS_CHANGED_OCB | BSS_CHANGED_BSSID;
 178        int err;
 179
 180        if (ifocb->joined == true)
 181                return -EINVAL;
 182
 183        sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
 184        sdata->smps_mode = IEEE80211_SMPS_OFF;
 185        sdata->needed_rx_chains = sdata->local->rx_chains;
 186
 187        mutex_lock(&sdata->local->mtx);
 188        err = ieee80211_vif_use_channel(sdata, &setup->chandef,
 189                                        IEEE80211_CHANCTX_SHARED);
 190        mutex_unlock(&sdata->local->mtx);
 191        if (err)
 192                return err;
 193
 194        ieee80211_bss_info_change_notify(sdata, changed);
 195
 196        ifocb->joined = true;
 197
 198        set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
 199        ieee80211_queue_work(&local->hw, &sdata->work);
 200
 201        netif_carrier_on(sdata->dev);
 202        return 0;
 203}
 204
 205int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata)
 206{
 207        struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
 208        struct ieee80211_local *local = sdata->local;
 209        struct sta_info *sta;
 210
 211        ifocb->joined = false;
 212        sta_info_flush(sdata);
 213
 214        spin_lock_bh(&ifocb->incomplete_lock);
 215        while (!list_empty(&ifocb->incomplete_stations)) {
 216                sta = list_first_entry(&ifocb->incomplete_stations,
 217                                       struct sta_info, list);
 218                list_del(&sta->list);
 219                spin_unlock_bh(&ifocb->incomplete_lock);
 220
 221                sta_info_free(local, sta);
 222                spin_lock_bh(&ifocb->incomplete_lock);
 223        }
 224        spin_unlock_bh(&ifocb->incomplete_lock);
 225
 226        netif_carrier_off(sdata->dev);
 227        clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
 228        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_OCB);
 229
 230        mutex_lock(&sdata->local->mtx);
 231        ieee80211_vif_release_channel(sdata);
 232        mutex_unlock(&sdata->local->mtx);
 233
 234        skb_queue_purge(&sdata->skb_queue);
 235
 236        del_timer_sync(&sdata->u.ocb.housekeeping_timer);
 237        /* If the timer fired while we waited for it, it will have
 238         * requeued the work. Now the work will be running again
 239         * but will not rearm the timer again because it checks
 240         * whether we are connected to the network or not -- at this
 241         * point we shouldn't be anymore.
 242         */
 243
 244        return 0;
 245}
 246