Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 352699
b: refs/heads/master
c: 04f3904
h: refs/heads/master
i:
  352697: 4409b41
  352695: 1fd1db5
v: v3
  • Loading branch information
Simon Wunderlich authored and Johannes Berg committed Feb 15, 2013
1 parent c270320 commit 4b170ed
Show file tree
Hide file tree
Showing 12 changed files with 571 additions and 18 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2a0e047ed62f20664005881b8e7f9328f910316a
refs/heads/master: 04f39047af2a6df64b763ea5a271db24879d0391
46 changes: 46 additions & 0 deletions trunk/include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ enum ieee80211_channel_flags {
#define IEEE80211_CHAN_NO_HT40 \
(IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)

#define IEEE80211_DFS_MIN_CAC_TIME_MS 60000
#define IEEE80211_DFS_MIN_NOP_TIME_MS (30 * 60 * 1000)

/**
* struct ieee80211_channel - channel definition
*
Expand All @@ -134,6 +137,9 @@ enum ieee80211_channel_flags {
* to enable this, this is useful only on 5 GHz band.
* @orig_mag: internal use
* @orig_mpwr: internal use
* @dfs_state: current state of this channel. Only relevant if radar is required
* on this channel.
* @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
*/
struct ieee80211_channel {
enum ieee80211_band band;
Expand All @@ -146,6 +152,8 @@ struct ieee80211_channel {
bool beacon_found;
u32 orig_flags;
int orig_mag, orig_mpwr;
enum nl80211_dfs_state dfs_state;
unsigned long dfs_state_entered;
};

/**
Expand Down Expand Up @@ -569,6 +577,7 @@ struct cfg80211_acl_data {
* @p2p_opp_ps: P2P opportunistic PS
* @acl: ACL configuration used by the drivers which has support for
* MAC address based access control
* @radar_required: set if radar detection is required
*/
struct cfg80211_ap_settings {
struct cfg80211_chan_def chandef;
Expand All @@ -586,6 +595,7 @@ struct cfg80211_ap_settings {
u8 p2p_ctwindow;
bool p2p_opp_ps;
const struct cfg80211_acl_data *acl;
bool radar_required;
};

/**
Expand Down Expand Up @@ -1909,6 +1919,8 @@ struct cfg80211_gtk_rekey_data {
* this new list replaces the existing one. Driver has to clear its ACL
* when number of MAC addresses entries is passed as 0. Drivers which
* advertise the support for MAC based ACL have to implement this callback.
*
* @start_radar_detection: Start radar detection in the driver.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
Expand Down Expand Up @@ -2132,6 +2144,10 @@ struct cfg80211_ops {

int (*set_mac_acl)(struct wiphy *wiphy, struct net_device *dev,
const struct cfg80211_acl_data *params);

int (*start_radar_detection)(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef);
};

/*
Expand Down Expand Up @@ -2715,6 +2731,8 @@ struct cfg80211_cached_keys;
* beacons, 0 when not valid
* @address: The address for this device, valid only if @netdev is %NULL
* @p2p_started: true if this is a P2P Device that has been started
* @cac_started: true if DFS channel availability check has been started
* @cac_start_time: timestamp (jiffies) when the dfs state was entered.
*/
struct wireless_dev {
struct wiphy *wiphy;
Expand Down Expand Up @@ -2766,6 +2784,9 @@ struct wireless_dev {

u32 ap_unexpected_nlportid;

bool cac_started;
unsigned long cac_start_time;

#ifdef CONFIG_CFG80211_WEXT
/* wext data */
struct {
Expand Down Expand Up @@ -3754,6 +3775,31 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
enum nl80211_cqm_rssi_threshold_event rssi_event,
gfp_t gfp);

/**
* cfg80211_radar_event - radar detection event
* @wiphy: the wiphy
* @chandef: chandef for the current channel
* @gfp: context flags
*
* This function is called when a radar is detected on the current chanenl.
*/
void cfg80211_radar_event(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef, gfp_t gfp);

/**
* cfg80211_cac_event - Channel availability check (CAC) event
* @netdev: network device
* @event: type of event
* @gfp: context flags
*
* This function is called when a Channel availability check (CAC) is finished
* or aborted. This must be called to notify the completion of a CAC process,
* also by full-MAC drivers.
*/
void cfg80211_cac_event(struct net_device *netdev,
enum nl80211_radar_event event, gfp_t gfp);


/**
* cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
* @dev: network device
Expand Down
61 changes: 61 additions & 0 deletions trunk/include/uapi/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,14 @@
* command is used in AP/P2P GO mode. Driver has to make sure to clear its
* ACL list during %NL80211_CMD_STOP_AP.
*
* @NL80211_CMD_RADAR_DETECT: Start a Channel availability check (CAC). Once
* a radar is detected or the channel availability scan (CAC) has finished
* or was aborted, or a radar was detected, usermode will be notified with
* this event. This command is also used to notify userspace about radars
* while operating on this channel.
* %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the
* event.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
Expand Down Expand Up @@ -755,6 +763,8 @@ enum nl80211_commands {

NL80211_CMD_SET_MAC_ACL,

NL80211_CMD_RADAR_DETECT,

/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
Expand Down Expand Up @@ -1342,6 +1352,9 @@ enum nl80211_commands {
* number of MAC addresses that a device can support for MAC
* ACL.
*
* @NL80211_ATTR_RADAR_EVENT: Type of radar event for notification to userspace,
* contains a value of enum nl80211_radar_event (u32).
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
Expand Down Expand Up @@ -1620,6 +1633,8 @@ enum nl80211_attrs {

NL80211_ATTR_MAC_ACL_MAX,

NL80211_ATTR_RADAR_EVENT,

/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
Expand Down Expand Up @@ -2022,6 +2037,10 @@ enum nl80211_band_attr {
* on this channel in current regulatory domain.
* @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
* (100 * dBm).
* @NL80211_FREQUENCY_ATTR_DFS_STATE: current state for DFS
* (enum nl80211_dfs_state)
* @NL80211_FREQUENCY_ATTR_DFS_TIME: time in miliseconds for how long
* this channel is in this DFS state.
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
* currently defined
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
Expand All @@ -2034,6 +2053,8 @@ enum nl80211_frequency_attr {
NL80211_FREQUENCY_ATTR_NO_IBSS,
NL80211_FREQUENCY_ATTR_RADAR,
NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
NL80211_FREQUENCY_ATTR_DFS_STATE,
NL80211_FREQUENCY_ATTR_DFS_TIME,

/* keep last */
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
Expand Down Expand Up @@ -3489,4 +3510,44 @@ enum nl80211_acl_policy {
NL80211_ACL_POLICY_DENY_UNLESS_LISTED,
};

/**
* enum nl80211_radar_event - type of radar event for DFS operation
*
* Type of event to be used with NL80211_ATTR_RADAR_EVENT to inform userspace
* about detected radars or success of the channel available check (CAC)
*
* @NL80211_RADAR_DETECTED: A radar pattern has been detected. The channel is
* now unusable.
* @NL80211_RADAR_CAC_FINISHED: Channel Availability Check has been finished,
* the channel is now available.
* @NL80211_RADAR_CAC_ABORTED: Channel Availability Check has been aborted, no
* change to the channel status.
* @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is
* over, channel becomes usable.
*/
enum nl80211_radar_event {
NL80211_RADAR_DETECTED,
NL80211_RADAR_CAC_FINISHED,
NL80211_RADAR_CAC_ABORTED,
NL80211_RADAR_NOP_FINISHED,
};

/**
* enum nl80211_dfs_state - DFS states for channels
*
* Channel states used by the DFS code.
*
* @IEEE80211_DFS_USABLE: The channel can be used, but channel availability
* check (CAC) must be performed before using it for AP or IBSS.
* @IEEE80211_DFS_UNAVAILABLE: A radar has been detected on this channel, it
* is therefore marked as not available.
* @IEEE80211_DFS_AVAILABLE: The channel has been CAC checked and is available.
*/

enum nl80211_dfs_state {
NL80211_DFS_USABLE,
NL80211_DFS_UNAVAILABLE,
NL80211_DFS_AVAILABLE,
};

#endif /* __LINUX_NL80211_H */
129 changes: 127 additions & 2 deletions trunk/net/wireless/chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,32 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
}
}

static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
{
int width;

switch (c->width) {
case NL80211_CHAN_WIDTH_20:
case NL80211_CHAN_WIDTH_20_NOHT:
width = 20;
break;
case NL80211_CHAN_WIDTH_40:
width = 40;
break;
case NL80211_CHAN_WIDTH_80P80:
case NL80211_CHAN_WIDTH_80:
width = 80;
break;
case NL80211_CHAN_WIDTH_160:
width = 160;
break;
default:
WARN_ON_ONCE(1);
return -1;
}
return width;
}

const struct cfg80211_chan_def *
cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
const struct cfg80211_chan_def *c2)
Expand Down Expand Up @@ -192,6 +218,93 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1,
}
EXPORT_SYMBOL(cfg80211_chandef_compatible);

static void cfg80211_set_chans_dfs_state(struct wiphy *wiphy, u32 center_freq,
u32 bandwidth,
enum nl80211_dfs_state dfs_state)
{
struct ieee80211_channel *c;
u32 freq;

for (freq = center_freq - bandwidth/2 + 10;
freq <= center_freq + bandwidth/2 - 10;
freq += 20) {
c = ieee80211_get_channel(wiphy, freq);
if (!c || !(c->flags & IEEE80211_CHAN_RADAR))
continue;

c->dfs_state = dfs_state;
c->dfs_state_entered = jiffies;
}
}

void cfg80211_set_dfs_state(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef,
enum nl80211_dfs_state dfs_state)
{
int width;

if (WARN_ON(!cfg80211_chandef_valid(chandef)))
return;

width = cfg80211_chandef_get_width(chandef);
if (width < 0)
return;

cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq1,
width, dfs_state);

if (!chandef->center_freq2)
return;
cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq2,
width, dfs_state);
}

static int cfg80211_get_chans_dfs_required(struct wiphy *wiphy,
u32 center_freq,
u32 bandwidth)
{
struct ieee80211_channel *c;
u32 freq;

for (freq = center_freq - bandwidth/2 + 10;
freq <= center_freq + bandwidth/2 - 10;
freq += 20) {
c = ieee80211_get_channel(wiphy, freq);
if (!c)
return -EINVAL;

if (c->flags & IEEE80211_CHAN_RADAR)
return 1;
}
return 0;
}


int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef)
{
int width;
int r;

if (WARN_ON(!cfg80211_chandef_valid(chandef)))
return -EINVAL;

width = cfg80211_chandef_get_width(chandef);
if (width < 0)
return -EINVAL;

r = cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq1,
width);
if (r)
return r;

if (!chandef->center_freq2)
return 0;

return cfg80211_get_chans_dfs_required(wiphy, chandef->center_freq2,
width);
}

static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
u32 center_freq, u32 bandwidth,
u32 prohibited_flags)
Expand All @@ -203,7 +316,16 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
freq <= center_freq + bandwidth/2 - 10;
freq += 20) {
c = ieee80211_get_channel(wiphy, freq);
if (!c || c->flags & prohibited_flags)
if (!c)
return false;

/* check for radar flags */
if ((prohibited_flags & c->flags & IEEE80211_CHAN_RADAR) &&
(c->dfs_state != NL80211_DFS_AVAILABLE))
return false;

/* check for the other flags */
if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR)
return false;
}

Expand Down Expand Up @@ -344,7 +466,10 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
if (wdev->beacon_interval) {
if (wdev->cac_started) {
*chan = wdev->channel;
*chanmode = CHAN_MODE_SHARED;
} else if (wdev->beacon_interval) {
*chan = wdev->channel;
*chanmode = CHAN_MODE_SHARED;
}
Expand Down
Loading

0 comments on commit 4b170ed

Please sign in to comment.