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