Skip to content

Commit

Permalink
cfg80211: 802.11p OCB mode handling
Browse files Browse the repository at this point in the history
This patch adds new iface type (NL80211_IFTYPE_OCB) representing
the OCB (Outside the Context of a BSS) mode.
When establishing a connection to the network a cfg80211_join_ocb
function is called (particular nl80211_command is added as well).
A mandatory parameters during the ocb_join operation are 'center
frequency' and 'channel width (5/10 MHz)'.

Changes done in mac80211 are minimal possible required to avoid
many warnings (warning: enumeration value 'NL80211_IFTYPE_OCB'
not handled in switch) during compilation. Full functionality
(where needed) is added in the following patch.

Signed-off-by: Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Rostislav Lisovy authored and Johannes Berg committed Nov 4, 2014
1 parent 5b3dc42 commit 6e0bd6c
Show file tree
Hide file tree
Showing 15 changed files with 238 additions and 2 deletions.
19 changes: 19 additions & 0 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,16 @@ struct mesh_setup {
u32 basic_rates;
};

/**
* struct ocb_setup - 802.11p OCB mode setup configuration
* @chandef: defines the channel to use
*
* These parameters are fixed when connecting to the network
*/
struct ocb_setup {
struct cfg80211_chan_def chandef;
};

/**
* struct ieee80211_txq_params - TX queue parameters
* @ac: AC identifier
Expand Down Expand Up @@ -2352,6 +2362,11 @@ struct cfg80211_qos_map {
* with the peer followed by immediate teardown when the addition is later
* rejected)
* @del_tx_ts: remove an existing TX TS
*
* @join_ocb: join the OCB network with the specified parameters
* (invoked with the wireless_dev mutex held)
* @leave_ocb: leave the current OCB network
* (invoked with the wireless_dev mutex held)
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
Expand Down Expand Up @@ -2433,6 +2448,10 @@ struct cfg80211_ops {
const struct mesh_setup *setup);
int (*leave_mesh)(struct wiphy *wiphy, struct net_device *dev);

int (*join_ocb)(struct wiphy *wiphy, struct net_device *dev,
struct ocb_setup *setup);
int (*leave_ocb)(struct wiphy *wiphy, struct net_device *dev);

int (*change_bss)(struct wiphy *wiphy, struct net_device *dev,
struct bss_parameters *params);

Expand Down
11 changes: 11 additions & 0 deletions include/uapi/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,11 @@
* destination %NL80211_ATTR_MAC on the interface identified by
* %NL80211_ATTR_IFINDEX.
*
* @NL80211_CMD_JOIN_OCB: Join the OCB network. The center frequency and
* bandwidth of a channel must be given.
* @NL80211_CMD_LEAVE_OCB: Leave the OCB network -- no special arguments, the
* network is determined by the network interface.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
Expand Down Expand Up @@ -922,6 +927,9 @@ enum nl80211_commands {

NL80211_CMD_GET_MPP,

NL80211_CMD_JOIN_OCB,
NL80211_CMD_LEAVE_OCB,

/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
Expand Down Expand Up @@ -2074,6 +2082,8 @@ enum nl80211_attrs {
* and therefore can't be created in the normal ways, use the
* %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE
* commands to create and destroy one
* @NL80211_IF_TYPE_OCB: Outside Context of a BSS
* This mode corresponds to the MIB variable dot11OCBActivated=true
* @NL80211_IFTYPE_MAX: highest interface type number currently defined
* @NUM_NL80211_IFTYPES: number of defined interface types
*
Expand All @@ -2093,6 +2103,7 @@ enum nl80211_iftype {
NL80211_IFTYPE_P2P_CLIENT,
NL80211_IFTYPE_P2P_GO,
NL80211_IFTYPE_P2P_DEVICE,
NL80211_IFTYPE_OCB,

/* keep last */
NUM_NL80211_IFTYPES,
Expand Down
1 change: 1 addition & 0 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
case NUM_NL80211_IFTYPES:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_OCB:
/* shouldn't happen */
WARN_ON_ONCE(1);
break;
Expand Down
2 changes: 2 additions & 0 deletions net/mac80211/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_OCB:
width = vif->bss_conf.chandef.width;
break;
case NL80211_IFTYPE_UNSPECIFIED:
Expand Down Expand Up @@ -909,6 +910,7 @@ ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data *sdata)
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_OCB:
ieee80211_queue_work(&sdata->local->hw,
&sdata->csa_finalize_work);
break;
Expand Down
5 changes: 5 additions & 0 deletions net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_OCB:
/* no special treatment */
break;
case NL80211_IFTYPE_UNSPECIFIED:
Expand Down Expand Up @@ -631,6 +632,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_OCB:
netif_carrier_off(dev);
break;
case NL80211_IFTYPE_WDS:
Expand Down Expand Up @@ -1351,6 +1353,9 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
ieee80211_sta_setup_sdata(sdata);
break;
case NL80211_IFTYPE_OCB:
/* to be implemented in the future */
break;
case NL80211_IFTYPE_ADHOC:
sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
ieee80211_ibss_setup_sdata(sdata);
Expand Down
3 changes: 3 additions & 0 deletions net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -1841,6 +1841,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
ieee80211_bss_info_change_notify(sdata, changed);
sdata_unlock(sdata);
break;
case NL80211_IFTYPE_OCB:
/* to be implemented in the future */
break;
case NL80211_IFTYPE_ADHOC:
changed |= BSS_CHANGED_IBSS;
/* fall through */
Expand Down
2 changes: 1 addition & 1 deletion net/wireless/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ obj-$(CONFIG_WEXT_SPY) += wext-spy.o
obj-$(CONFIG_WEXT_PRIV) += wext-priv.o

cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o
cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o
cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
Expand Down
8 changes: 8 additions & 0 deletions net/wireless/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,

break;
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP_VLAN:
Expand Down Expand Up @@ -892,6 +893,13 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
*radar_detect |= BIT(wdev->chandef.width);
}
return;
case NL80211_IFTYPE_OCB:
if (wdev->chandef.chan) {
*chan = wdev->chandef.chan;
*chanmode = CHAN_MODE_SHARED;
return;
}
break;
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_WDS:
Expand Down
3 changes: 3 additions & 0 deletions net/wireless/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,9 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_P2P_GO:
__cfg80211_stop_ap(rdev, dev, true);
break;
case NL80211_IFTYPE_OCB:
__cfg80211_leave_ocb(rdev, dev);
break;
case NL80211_IFTYPE_WDS:
/* must be handled by mac80211/driver, has no APIs */
break;
Expand Down
12 changes: 12 additions & 0 deletions net/wireless/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,18 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev,
struct cfg80211_chan_def *chandef);

/* OCB */
int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ocb_setup *setup);
int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ocb_setup *setup);
int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev);
int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev);

/* AP */
int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
struct net_device *dev, bool notify);
Expand Down
39 changes: 39 additions & 0 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,7 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
return -ENOLINK;
break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_WDS:
Expand Down Expand Up @@ -8275,6 +8276,28 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}

static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
struct ocb_setup setup = {};
int err;

err = nl80211_parse_chandef(rdev, info, &setup.chandef);
if (err)
return err;

return cfg80211_join_ocb(rdev, dev, &setup);
}

static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];

return cfg80211_leave_ocb(rdev, dev);
}

static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
Expand Down Expand Up @@ -10218,6 +10241,22 @@ static const struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_JOIN_OCB,
.doit = nl80211_join_ocb,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_LEAVE_OCB,
.doit = nl80211_leave_ocb,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
#ifdef CONFIG_PM
{
.cmd = NL80211_CMD_GET_WOWLAN,
Expand Down
88 changes: 88 additions & 0 deletions net/wireless/ocb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* OCB mode implementation
*
* Copyright: (c) 2014 Czech Technical University in Prague
* (c) 2014 Volkswagen Group Research
* Author: Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
* Funded by: Volkswagen Group Research
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include <linux/ieee80211.h>
#include <net/cfg80211.h>
#include "nl80211.h"
#include "core.h"
#include "rdev-ops.h"

int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ocb_setup *setup)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;

ASSERT_WDEV_LOCK(wdev);

if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
return -EOPNOTSUPP;

if (WARN_ON(!setup->chandef.chan))
return -EINVAL;

err = rdev_join_ocb(rdev, dev, setup);
if (!err)
wdev->chandef = setup->chandef;

return err;
}

int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ocb_setup *setup)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;

wdev_lock(wdev);
err = __cfg80211_join_ocb(rdev, dev, setup);
wdev_unlock(wdev);

return err;
}

int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;

ASSERT_WDEV_LOCK(wdev);

if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
return -EOPNOTSUPP;

if (!rdev->ops->leave_ocb)
return -EOPNOTSUPP;

err = rdev_leave_ocb(rdev, dev);
if (!err)
memset(&wdev->chandef, 0, sizeof(wdev->chandef));

return err;
}

int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;

wdev_lock(wdev);
err = __cfg80211_leave_ocb(rdev, dev);
wdev_unlock(wdev);

return err;
}
21 changes: 21 additions & 0 deletions net/wireless/rdev-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,27 @@ static inline int rdev_leave_mesh(struct cfg80211_registered_device *rdev,
return ret;
}

static inline int rdev_join_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ocb_setup *setup)
{
int ret;
trace_rdev_join_ocb(&rdev->wiphy, dev, setup);
ret = rdev->ops->join_ocb(&rdev->wiphy, dev, setup);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}

static inline int rdev_leave_ocb(struct cfg80211_registered_device *rdev,
struct net_device *dev)
{
int ret;
trace_rdev_leave_ocb(&rdev->wiphy, dev);
ret = rdev->ops->leave_ocb(&rdev->wiphy, dev);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}

static inline int rdev_change_bss(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct bss_parameters *params)
Expand Down
Loading

0 comments on commit 6e0bd6c

Please sign in to comment.