Commit 239281f803e2efdb77d906ef296086b6917e5d71

Authored by Rostislav Lisovy
Committed by Johannes Berg
1 parent 6e0bd6c35b

mac80211: 802.11p OCB mode support

This patch adds 802.11p OCB (Outside the Context of a BSS) mode
support.

When communicating in OCB mode a mandatory wildcard BSSID
(48 '1' bits) is used.

The EDCA parameters handling function was changed to support
802.11p specific values.

The insertion of a newly discovered STAs is done in the similar way
as in the IBSS mode -- through the deferred insertion.

The OCB mode uses a periodic 'housekeeping task' for expiration of
disconnected STAs (in the similar manner as in the MESH mode).

New Kconfig option for verbose OCB debugging outputs is added.

Signed-off-by: Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

Showing 14 changed files with 417 additions and 9 deletions Side-by-side Diff

include/net/mac80211.h
... ... @@ -263,6 +263,7 @@
263 263 * @BSS_CHANGED_BANDWIDTH: The bandwidth used by this interface changed,
264 264 * note that this is only called when it changes after the channel
265 265 * context had been assigned.
  266 + * @BSS_CHANGED_OCB: OCB join status changed
266 267 */
267 268 enum ieee80211_bss_change {
268 269 BSS_CHANGED_ASSOC = 1<<0,
... ... @@ -287,6 +288,7 @@
287 288 BSS_CHANGED_P2P_PS = 1<<19,
288 289 BSS_CHANGED_BEACON_INFO = 1<<20,
289 290 BSS_CHANGED_BANDWIDTH = 1<<21,
  291 + BSS_CHANGED_OCB = 1<<22,
290 292  
291 293 /* when adding here, make sure to change ieee80211_reconfig */
292 294 };
net/mac80211/Kconfig
... ... @@ -176,6 +176,17 @@
176 176  
177 177 Do not select this option.
178 178  
  179 +config MAC80211_OCB_DEBUG
  180 + bool "Verbose OCB debugging"
  181 + depends on MAC80211_DEBUG_MENU
  182 + ---help---
  183 + Selecting this option causes mac80211 to print out
  184 + very verbose OCB debugging messages. It should not
  185 + be selected on production systems as those messages
  186 + are remotely triggerable.
  187 +
  188 + Do not select this option.
  189 +
179 190 config MAC80211_IBSS_DEBUG
180 191 bool "Verbose IBSS debugging"
181 192 depends on MAC80211_DEBUG_MENU
net/mac80211/Makefile
... ... @@ -27,7 +27,8 @@
27 27 event.o \
28 28 chan.o \
29 29 trace.o mlme.o \
30   - tdls.o
  30 + tdls.o \
  31 + ocb.o
31 32  
32 33 mac80211-$(CONFIG_MAC80211_LEDS) += led.o
33 34 mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
... ... @@ -2019,6 +2019,17 @@
2019 2019 return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev));
2020 2020 }
2021 2021  
  2022 +static int ieee80211_join_ocb(struct wiphy *wiphy, struct net_device *dev,
  2023 + struct ocb_setup *setup)
  2024 +{
  2025 + return ieee80211_ocb_join(IEEE80211_DEV_TO_SUB_IF(dev), setup);
  2026 +}
  2027 +
  2028 +static int ieee80211_leave_ocb(struct wiphy *wiphy, struct net_device *dev)
  2029 +{
  2030 + return ieee80211_ocb_leave(IEEE80211_DEV_TO_SUB_IF(dev));
  2031 +}
  2032 +
2022 2033 static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
2023 2034 int rate[IEEE80211_NUM_BANDS])
2024 2035 {
... ... @@ -3693,6 +3704,8 @@
3693 3704 .join_mesh = ieee80211_join_mesh,
3694 3705 .leave_mesh = ieee80211_leave_mesh,
3695 3706 #endif
  3707 + .join_ocb = ieee80211_join_ocb,
  3708 + .leave_ocb = ieee80211_leave_ocb,
3696 3709 .change_bss = ieee80211_change_bss,
3697 3710 .set_txq_params = ieee80211_set_txq_params,
3698 3711 .set_monitor_channel = ieee80211_set_monitor_channel,
... ... @@ -675,6 +675,7 @@
675 675 case NL80211_IFTYPE_ADHOC:
676 676 case NL80211_IFTYPE_WDS:
677 677 case NL80211_IFTYPE_MESH_POINT:
  678 + case NL80211_IFTYPE_OCB:
678 679 break;
679 680 default:
680 681 WARN_ON_ONCE(1);
net/mac80211/debug.h
... ... @@ -2,6 +2,12 @@
2 2 #define __MAC80211_DEBUG_H
3 3 #include <net/cfg80211.h>
4 4  
  5 +#ifdef CONFIG_MAC80211_OCB_DEBUG
  6 +#define MAC80211_OCB_DEBUG 1
  7 +#else
  8 +#define MAC80211_OCB_DEBUG 0
  9 +#endif
  10 +
5 11 #ifdef CONFIG_MAC80211_IBSS_DEBUG
6 12 #define MAC80211_IBSS_DEBUG 1
7 13 #else
... ... @@ -129,6 +135,10 @@
129 135  
130 136 #define ht_dbg_ratelimited(sdata, fmt, ...) \
131 137 _sdata_dbg(MAC80211_HT_DEBUG && net_ratelimit(), \
  138 + sdata, fmt, ##__VA_ARGS__)
  139 +
  140 +#define ocb_dbg(sdata, fmt, ...) \
  141 + _sdata_dbg(MAC80211_OCB_DEBUG, \
132 142 sdata, fmt, ##__VA_ARGS__)
133 143  
134 144 #define ibss_dbg(sdata, fmt, ...) \
net/mac80211/driver-ops.h
... ... @@ -214,7 +214,8 @@
214 214 BSS_CHANGED_BEACON_ENABLED) &&
215 215 sdata->vif.type != NL80211_IFTYPE_AP &&
216 216 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
217   - sdata->vif.type != NL80211_IFTYPE_MESH_POINT))
  217 + sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
  218 + sdata->vif.type != NL80211_IFTYPE_OCB))
218 219 return;
219 220  
220 221 if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
net/mac80211/ieee80211_i.h
... ... @@ -577,6 +577,25 @@
577 577 };
578 578  
579 579 /**
  580 + * struct ieee80211_if_ocb - OCB mode state
  581 + *
  582 + * @housekeeping_timer: timer for periodic invocation of a housekeeping task
  583 + * @wrkq_flags: OCB deferred task action
  584 + * @incomplete_lock: delayed STA insertion lock
  585 + * @incomplete_stations: list of STAs waiting for delayed insertion
  586 + * @joined: indication if the interface is connected to an OCB network
  587 + */
  588 +struct ieee80211_if_ocb {
  589 + struct timer_list housekeeping_timer;
  590 + unsigned long wrkq_flags;
  591 +
  592 + spinlock_t incomplete_lock;
  593 + struct list_head incomplete_stations;
  594 +
  595 + bool joined;
  596 +};
  597 +
  598 +/**
580 599 * struct ieee80211_mesh_sync_ops - Extensible synchronization framework interface
581 600 *
582 601 * these declarations define the interface, which enables
... ... @@ -869,6 +888,7 @@
869 888 struct ieee80211_if_managed mgd;
870 889 struct ieee80211_if_ibss ibss;
871 890 struct ieee80211_if_mesh mesh;
  891 + struct ieee80211_if_ocb ocb;
872 892 u32 mntr_flags;
873 893 } u;
874 894  
... ... @@ -1504,6 +1524,15 @@
1504 1524 struct cfg80211_csa_settings *csa_settings);
1505 1525 int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata);
1506 1526 void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata);
  1527 +
  1528 +/* OCB code */
  1529 +void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata);
  1530 +void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
  1531 + const u8 *bssid, const u8 *addr, u32 supp_rates);
  1532 +void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata);
  1533 +int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
  1534 + struct ocb_setup *setup);
  1535 +int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata);
1507 1536  
1508 1537 /* mesh code */
1509 1538 void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata);
net/mac80211/iface.c
... ... @@ -259,6 +259,15 @@
259 259 list_for_each_entry(nsdata, &local->interfaces, list) {
260 260 if (nsdata != sdata && ieee80211_sdata_running(nsdata)) {
261 261 /*
  262 + * Only OCB and monitor mode may coexist
  263 + */
  264 + if ((sdata->vif.type == NL80211_IFTYPE_OCB &&
  265 + nsdata->vif.type != NL80211_IFTYPE_MONITOR) ||
  266 + (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
  267 + nsdata->vif.type == NL80211_IFTYPE_OCB))
  268 + return -EBUSY;
  269 +
  270 + /*
262 271 * Allow only a single IBSS interface to be up at any
263 272 * time. This is restricted because beacon distribution
264 273 * cannot work properly if both are in the same IBSS.
... ... @@ -1283,6 +1292,9 @@
1283 1292 break;
1284 1293 ieee80211_mesh_work(sdata);
1285 1294 break;
  1295 + case NL80211_IFTYPE_OCB:
  1296 + ieee80211_ocb_work(sdata);
  1297 + break;
1286 1298 default:
1287 1299 break;
1288 1300 }
... ... @@ -1302,6 +1314,9 @@
1302 1314 static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
1303 1315 enum nl80211_iftype type)
1304 1316 {
  1317 + static const u8 bssid_wildcard[ETH_ALEN] = {0xff, 0xff, 0xff,
  1318 + 0xff, 0xff, 0xff};
  1319 +
1305 1320 /* clear type-dependent union */
1306 1321 memset(&sdata->u, 0, sizeof(sdata->u));
1307 1322  
... ... @@ -1354,7 +1369,8 @@
1354 1369 ieee80211_sta_setup_sdata(sdata);
1355 1370 break;
1356 1371 case NL80211_IFTYPE_OCB:
1357   - /* to be implemented in the future */
  1372 + sdata->vif.bss_conf.bssid = bssid_wildcard;
  1373 + ieee80211_ocb_setup_sdata(sdata);
1358 1374 break;
1359 1375 case NL80211_IFTYPE_ADHOC:
1360 1376 sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
... ... @@ -1403,6 +1419,7 @@
1403 1419 case NL80211_IFTYPE_AP:
1404 1420 case NL80211_IFTYPE_STATION:
1405 1421 case NL80211_IFTYPE_ADHOC:
  1422 + case NL80211_IFTYPE_OCB:
1406 1423 /*
1407 1424 * Could maybe also all others here?
1408 1425 * Just not sure how that interacts
... ... @@ -1418,6 +1435,7 @@
1418 1435 case NL80211_IFTYPE_AP:
1419 1436 case NL80211_IFTYPE_STATION:
1420 1437 case NL80211_IFTYPE_ADHOC:
  1438 + case NL80211_IFTYPE_OCB:
1421 1439 /*
1422 1440 * Could probably support everything
1423 1441 * but WDS here (WDS do_open can fail
  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 + */
  37 +enum ocb_deferred_task_flags {
  38 + OCB_WORK_HOUSEKEEPING,
  39 +};
  40 +
  41 +void 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 + sta->last_rx = jiffies;
  79 +
  80 + /* Add only mandatory rates for now */
  81 + sband = local->hw.wiphy->bands[band];
  82 + sta->sta.supp_rates[band] =
  83 + ieee80211_mandatory_rates(sband, scan_width);
  84 +
  85 + spin_lock(&ifocb->incomplete_lock);
  86 + list_add(&sta->list, &ifocb->incomplete_stations);
  87 + spin_unlock(&ifocb->incomplete_lock);
  88 + ieee80211_queue_work(&local->hw, &sdata->work);
  89 +}
  90 +
  91 +static struct sta_info *ieee80211_ocb_finish_sta(struct sta_info *sta)
  92 + __acquires(RCU)
  93 +{
  94 + struct ieee80211_sub_if_data *sdata = sta->sdata;
  95 + u8 addr[ETH_ALEN];
  96 +
  97 + memcpy(addr, sta->sta.addr, ETH_ALEN);
  98 +
  99 + ocb_dbg(sdata, "Adding new IBSS station %pM (dev=%s)\n",
  100 + addr, sdata->name);
  101 +
  102 + sta_info_move_state(sta, IEEE80211_STA_AUTH);
  103 + sta_info_move_state(sta, IEEE80211_STA_ASSOC);
  104 + sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
  105 +
  106 + rate_control_rate_init(sta);
  107 +
  108 + /* If it fails, maybe we raced another insertion? */
  109 + if (sta_info_insert_rcu(sta))
  110 + return sta_info_get(sdata, addr);
  111 + return sta;
  112 +}
  113 +
  114 +static void ieee80211_ocb_housekeeping(struct ieee80211_sub_if_data *sdata)
  115 +{
  116 + struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
  117 +
  118 + ocb_dbg(sdata, "Running ocb housekeeping\n");
  119 +
  120 + ieee80211_sta_expire(sdata, IEEE80211_OCB_PEER_INACTIVITY_LIMIT);
  121 +
  122 + mod_timer(&ifocb->housekeeping_timer,
  123 + round_jiffies(jiffies + IEEE80211_OCB_HOUSEKEEPING_INTERVAL));
  124 +}
  125 +
  126 +void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata)
  127 +{
  128 + struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
  129 + struct sta_info *sta;
  130 +
  131 + if (ifocb->joined != true)
  132 + return;
  133 +
  134 + sdata_lock(sdata);
  135 +
  136 + spin_lock_bh(&ifocb->incomplete_lock);
  137 + while (!list_empty(&ifocb->incomplete_stations)) {
  138 + sta = list_first_entry(&ifocb->incomplete_stations,
  139 + struct sta_info, list);
  140 + list_del(&sta->list);
  141 + spin_unlock_bh(&ifocb->incomplete_lock);
  142 +
  143 + ieee80211_ocb_finish_sta(sta);
  144 + rcu_read_unlock();
  145 + spin_lock_bh(&ifocb->incomplete_lock);
  146 + }
  147 + spin_unlock_bh(&ifocb->incomplete_lock);
  148 +
  149 + if (test_and_clear_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags))
  150 + ieee80211_ocb_housekeeping(sdata);
  151 +
  152 + sdata_unlock(sdata);
  153 +}
  154 +
  155 +static void ieee80211_ocb_housekeeping_timer(unsigned long data)
  156 +{
  157 + struct ieee80211_sub_if_data *sdata = (void *)data;
  158 + struct ieee80211_local *local = sdata->local;
  159 + struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
  160 +
  161 + set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
  162 +
  163 + ieee80211_queue_work(&local->hw, &sdata->work);
  164 +}
  165 +
  166 +void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata)
  167 +{
  168 + struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
  169 +
  170 + setup_timer(&ifocb->housekeeping_timer,
  171 + ieee80211_ocb_housekeeping_timer,
  172 + (unsigned long)sdata);
  173 + INIT_LIST_HEAD(&ifocb->incomplete_stations);
  174 + spin_lock_init(&ifocb->incomplete_lock);
  175 +}
  176 +
  177 +int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
  178 + struct ocb_setup *setup)
  179 +{
  180 + struct ieee80211_local *local = sdata->local;
  181 + struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
  182 + u32 changed = BSS_CHANGED_OCB;
  183 + int err;
  184 +
  185 + if (ifocb->joined == true)
  186 + return -EINVAL;
  187 +
  188 + sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
  189 + sdata->smps_mode = IEEE80211_SMPS_OFF;
  190 + sdata->needed_rx_chains = sdata->local->rx_chains;
  191 +
  192 + mutex_lock(&sdata->local->mtx);
  193 + err = ieee80211_vif_use_channel(sdata, &setup->chandef,
  194 + IEEE80211_CHANCTX_SHARED);
  195 + mutex_unlock(&sdata->local->mtx);
  196 + if (err)
  197 + return err;
  198 +
  199 + ieee80211_bss_info_change_notify(sdata, changed);
  200 +
  201 + ifocb->joined = true;
  202 +
  203 + set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
  204 + ieee80211_queue_work(&local->hw, &sdata->work);
  205 +
  206 + netif_carrier_on(sdata->dev);
  207 + return 0;
  208 +}
  209 +
  210 +int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata)
  211 +{
  212 + struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
  213 + struct ieee80211_local *local = sdata->local;
  214 + struct sta_info *sta;
  215 +
  216 + ifocb->joined = false;
  217 + sta_info_flush(sdata);
  218 +
  219 + spin_lock_bh(&ifocb->incomplete_lock);
  220 + while (!list_empty(&ifocb->incomplete_stations)) {
  221 + sta = list_first_entry(&ifocb->incomplete_stations,
  222 + struct sta_info, list);
  223 + list_del(&sta->list);
  224 + spin_unlock_bh(&ifocb->incomplete_lock);
  225 +
  226 + sta_info_free(local, sta);
  227 + spin_lock_bh(&ifocb->incomplete_lock);
  228 + }
  229 + spin_unlock_bh(&ifocb->incomplete_lock);
  230 +
  231 + netif_carrier_off(sdata->dev);
  232 + clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
  233 + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_OCB);
  234 +
  235 + mutex_lock(&sdata->local->mtx);
  236 + ieee80211_vif_release_channel(sdata);
  237 + mutex_unlock(&sdata->local->mtx);
  238 +
  239 + skb_queue_purge(&sdata->skb_queue);
  240 +
  241 + del_timer_sync(&sdata->u.ocb.housekeeping_timer);
  242 + /* If the timer fired while we waited for it, it will have
  243 + * requeued the work. Now the work will be running again
  244 + * but will not rearm the timer again because it checks
  245 + * whether we are connected to the network or not -- at this
  246 + * point we shouldn't be anymore.
  247 + */
  248 +
  249 + return 0;
  250 +}
... ... @@ -1032,6 +1032,7 @@
1032 1032 ieee80211_is_pspoll(hdr->frame_control)) &&
1033 1033 rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
1034 1034 rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
  1035 + rx->sdata->vif.type != NL80211_IFTYPE_OCB &&
1035 1036 (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
1036 1037 /*
1037 1038 * accept port control frames from the AP even when it's not
... ... @@ -1272,6 +1273,12 @@
1272 1273 sta->last_rx_rate_vht_nss = status->vht_nss;
1273 1274 }
1274 1275 }
  1276 + } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
  1277 + u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
  1278 + NL80211_IFTYPE_OCB);
  1279 + /* OCB uses wild-card BSSID */
  1280 + if (is_broadcast_ether_addr(bssid))
  1281 + sta->last_rx = jiffies;
1275 1282 } else if (!is_multicast_ether_addr(hdr->addr1)) {
1276 1283 /*
1277 1284 * Mesh beacons will update last_rx when if they are found to
... ... @@ -2820,6 +2827,7 @@
2820 2827  
2821 2828 if (!ieee80211_vif_is_mesh(&sdata->vif) &&
2822 2829 sdata->vif.type != NL80211_IFTYPE_ADHOC &&
  2830 + sdata->vif.type != NL80211_IFTYPE_OCB &&
2823 2831 sdata->vif.type != NL80211_IFTYPE_STATION)
2824 2832 return RX_DROP_MONITOR;
2825 2833  
... ... @@ -3128,6 +3136,33 @@
3128 3136 rate_idx = status->rate_idx;
3129 3137 ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
3130 3138 BIT(rate_idx));
  3139 + }
  3140 + break;
  3141 + case NL80211_IFTYPE_OCB:
  3142 + if (!bssid)
  3143 + return false;
  3144 + if (ieee80211_is_beacon(hdr->frame_control)) {
  3145 + return false;
  3146 + } else if (!is_broadcast_ether_addr(bssid)) {
  3147 + ocb_dbg(sdata, "BSSID mismatch in OCB mode!\n");
  3148 + return false;
  3149 + } else if (!multicast &&
  3150 + !ether_addr_equal(sdata->dev->dev_addr,
  3151 + hdr->addr1)) {
  3152 + /* if we are in promisc mode we also accept
  3153 + * packets not destined for us
  3154 + */
  3155 + if (!(sdata->dev->flags & IFF_PROMISC))
  3156 + return false;
  3157 + rx->flags &= ~IEEE80211_RX_RA_MATCH;
  3158 + } else if (!rx->sta) {
  3159 + int rate_idx;
  3160 + if (status->flag & RX_FLAG_HT)
  3161 + rate_idx = 0; /* TODO: HT rates */
  3162 + else
  3163 + rate_idx = status->rate_idx;
  3164 + ieee80211_ocb_rx_no_sta(sdata, bssid, hdr->addr2,
  3165 + BIT(rate_idx));
3131 3166 }
3132 3167 break;
3133 3168 case NL80211_IFTYPE_MESH_POINT:
... ... @@ -296,6 +296,9 @@
296 296 */
297 297 return TX_DROP;
298 298  
  299 + if (tx->sdata->vif.type == NL80211_IFTYPE_OCB)
  300 + return TX_CONTINUE;
  301 +
299 302 if (tx->sdata->vif.type == NL80211_IFTYPE_WDS)
300 303 return TX_CONTINUE;
301 304  
... ... @@ -2013,6 +2016,17 @@
2013 2016 goto fail_rcu;
2014 2017 band = chanctx_conf->def.chan->band;
2015 2018 break;
  2019 + case NL80211_IFTYPE_OCB:
  2020 + /* DA SA BSSID */
  2021 + memcpy(hdr.addr1, skb->data, ETH_ALEN);
  2022 + memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
  2023 + eth_broadcast_addr(hdr.addr3);
  2024 + hdrlen = 24;
  2025 + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
  2026 + if (!chanctx_conf)
  2027 + goto fail_rcu;
  2028 + band = chanctx_conf->def.chan->band;
  2029 + break;
2016 2030 case NL80211_IFTYPE_ADHOC:
2017 2031 /* DA SA BSSID */
2018 2032 memcpy(hdr.addr1, skb->data, ETH_ALEN);
... ... @@ -2057,6 +2071,7 @@
2057 2071 * EAPOL frames from the local station.
2058 2072 */
2059 2073 if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
  2074 + (sdata->vif.type != NL80211_IFTYPE_OCB) &&
2060 2075 !multicast && !authorized &&
2061 2076 (cpu_to_be16(ethertype) != sdata->control_port_protocol ||
2062 2077 !ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) {
... ... @@ -1101,6 +1101,7 @@
1101 1101 struct ieee80211_chanctx_conf *chanctx_conf;
1102 1102 int ac;
1103 1103 bool use_11b, enable_qos;
  1104 + bool is_ocb; /* Use another EDCA parameters if dot11OCBActivated=true */
1104 1105 int aCWmin, aCWmax;
1105 1106  
1106 1107 if (!local->ops->conf_tx)
... ... @@ -1125,6 +1126,8 @@
1125 1126 */
1126 1127 enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION);
1127 1128  
  1129 + is_ocb = (sdata->vif.type == NL80211_IFTYPE_OCB);
  1130 +
1128 1131 /* Set defaults according to 802.11-2007 Table 7-37 */
1129 1132 aCWmax = 1023;
1130 1133 if (use_11b)
... ... @@ -1146,7 +1149,10 @@
1146 1149 qparam.cw_max = aCWmax;
1147 1150 qparam.cw_min = aCWmin;
1148 1151 qparam.txop = 0;
1149   - qparam.aifs = 7;
  1152 + if (is_ocb)
  1153 + qparam.aifs = 9;
  1154 + else
  1155 + qparam.aifs = 7;
1150 1156 break;
1151 1157 /* never happens but let's not leave undefined */
1152 1158 default:
1153 1159  
1154 1160  
1155 1161  
... ... @@ -1154,21 +1160,32 @@
1154 1160 qparam.cw_max = aCWmax;
1155 1161 qparam.cw_min = aCWmin;
1156 1162 qparam.txop = 0;
1157   - qparam.aifs = 3;
  1163 + if (is_ocb)
  1164 + qparam.aifs = 6;
  1165 + else
  1166 + qparam.aifs = 3;
1158 1167 break;
1159 1168 case IEEE80211_AC_VI:
1160 1169 qparam.cw_max = aCWmin;
1161 1170 qparam.cw_min = (aCWmin + 1) / 2 - 1;
1162   - if (use_11b)
  1171 + if (is_ocb)
  1172 + qparam.txop = 0;
  1173 + else if (use_11b)
1163 1174 qparam.txop = 6016/32;
1164 1175 else
1165 1176 qparam.txop = 3008/32;
1166   - qparam.aifs = 2;
  1177 +
  1178 + if (is_ocb)
  1179 + qparam.aifs = 3;
  1180 + else
  1181 + qparam.aifs = 2;
1167 1182 break;
1168 1183 case IEEE80211_AC_VO:
1169 1184 qparam.cw_max = (aCWmin + 1) / 2 - 1;
1170 1185 qparam.cw_min = (aCWmin + 1) / 4 - 1;
1171   - if (use_11b)
  1186 + if (is_ocb)
  1187 + qparam.txop = 0;
  1188 + else if (use_11b)
1172 1189 qparam.txop = 3264/32;
1173 1190 else
1174 1191 qparam.txop = 1504/32;
... ... @@ -1842,7 +1859,8 @@
1842 1859 sdata_unlock(sdata);
1843 1860 break;
1844 1861 case NL80211_IFTYPE_OCB:
1845   - /* to be implemented in the future */
  1862 + changed |= BSS_CHANGED_OCB;
  1863 + ieee80211_bss_info_change_notify(sdata, changed);
1846 1864 break;
1847 1865 case NL80211_IFTYPE_ADHOC:
1848 1866 changed |= BSS_CHANGED_IBSS;
... ... @@ -148,6 +148,10 @@
148 148 case NL80211_IFTYPE_ADHOC:
149 149 ra = skb->data;
150 150 break;
  151 + case NL80211_IFTYPE_OCB:
  152 + /* all stations are required to support WME */
  153 + qos = true;
  154 + break;
151 155 default:
152 156 break;
153 157 }