Commit 3b1c5a53 authored by Marco Porsch's avatar Marco Porsch Committed by Johannes Berg

{cfg,nl}80211: mesh power mode primitives and userspace access

Add the nl80211_mesh_power_mode enumeration which holds possible
values for the mesh power mode. These modes are unknown, active,
light sleep and deep sleep.

Add power_mode entry to the mesh config structure to hold the
user-configured default mesh power mode. This value will be used
for new peer links.

Add the dot11MeshAwakeWindowDuration value to the mesh config.
The awake window is a duration in TU describing how long the STA
will stay awake after transmitting its beacon in PS mode.

Add access routines to:
 - get/set local link-specific power mode (STA)
 - get remote STA's link-specific power mode (STA)
 - get remote STA's non-peer power mode (STA)
 - get/set default mesh power mode (mesh config)
 - get/set mesh awake window duration (mesh config)

All config changes may be done at mesh runtime and take effect
immediately.
Signed-off-by: default avatarMarco Porsch <marco@cozybit.com>
Signed-off-by: default avatarIvan Bezyazychnyy <ivan.bezyazychnyy@gmail.com>
Signed-off-by: default avatarMike Krinkin <krinkin.m.u@gmail.com>
[fix commit message line length, error handling in set station]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9bdbf04d
...@@ -610,6 +610,8 @@ enum station_parameters_apply_mask { ...@@ -610,6 +610,8 @@ enum station_parameters_apply_mask {
* @sta_modify_mask: bitmap indicating which parameters changed * @sta_modify_mask: bitmap indicating which parameters changed
* (for those that don't have a natural "no change" value), * (for those that don't have a natural "no change" value),
* see &enum station_parameters_apply_mask * see &enum station_parameters_apply_mask
* @local_pm: local link-specific mesh power save mode (no change when set
* to unknown)
*/ */
struct station_parameters { struct station_parameters {
u8 *supported_rates; u8 *supported_rates;
...@@ -625,6 +627,7 @@ struct station_parameters { ...@@ -625,6 +627,7 @@ struct station_parameters {
struct ieee80211_vht_cap *vht_capa; struct ieee80211_vht_cap *vht_capa;
u8 uapsd_queues; u8 uapsd_queues;
u8 max_sp; u8 max_sp;
enum nl80211_mesh_power_mode local_pm;
}; };
/** /**
...@@ -655,6 +658,9 @@ struct station_parameters { ...@@ -655,6 +658,9 @@ struct station_parameters {
* @STATION_INFO_STA_FLAGS: @sta_flags filled * @STATION_INFO_STA_FLAGS: @sta_flags filled
* @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled
* @STATION_INFO_T_OFFSET: @t_offset filled * @STATION_INFO_T_OFFSET: @t_offset filled
* @STATION_INFO_LOCAL_PM: @local_pm filled
* @STATION_INFO_PEER_PM: @peer_pm filled
* @STATION_INFO_NONPEER_PM: @nonpeer_pm filled
*/ */
enum station_info_flags { enum station_info_flags {
STATION_INFO_INACTIVE_TIME = 1<<0, STATION_INFO_INACTIVE_TIME = 1<<0,
...@@ -678,6 +684,9 @@ enum station_info_flags { ...@@ -678,6 +684,9 @@ enum station_info_flags {
STATION_INFO_STA_FLAGS = 1<<18, STATION_INFO_STA_FLAGS = 1<<18,
STATION_INFO_BEACON_LOSS_COUNT = 1<<19, STATION_INFO_BEACON_LOSS_COUNT = 1<<19,
STATION_INFO_T_OFFSET = 1<<20, STATION_INFO_T_OFFSET = 1<<20,
STATION_INFO_LOCAL_PM = 1<<21,
STATION_INFO_PEER_PM = 1<<22,
STATION_INFO_NONPEER_PM = 1<<23,
}; };
/** /**
...@@ -791,6 +800,9 @@ struct sta_bss_parameters { ...@@ -791,6 +800,9 @@ struct sta_bss_parameters {
* @sta_flags: station flags mask & values * @sta_flags: station flags mask & values
* @beacon_loss_count: Number of times beacon loss event has triggered. * @beacon_loss_count: Number of times beacon loss event has triggered.
* @t_offset: Time offset of the station relative to this host. * @t_offset: Time offset of the station relative to this host.
* @local_pm: local mesh STA power save mode
* @peer_pm: peer mesh STA power save mode
* @nonpeer_pm: non-peer mesh STA power save mode
*/ */
struct station_info { struct station_info {
u32 filled; u32 filled;
...@@ -820,6 +832,9 @@ struct station_info { ...@@ -820,6 +832,9 @@ struct station_info {
u32 beacon_loss_count; u32 beacon_loss_count;
s64 t_offset; s64 t_offset;
enum nl80211_mesh_power_mode local_pm;
enum nl80211_mesh_power_mode peer_pm;
enum nl80211_mesh_power_mode nonpeer_pm;
/* /*
* Note: Add a new enum station_info_flags value for each new field and * Note: Add a new enum station_info_flags value for each new field and
...@@ -995,6 +1010,10 @@ struct bss_parameters { ...@@ -995,6 +1010,10 @@ struct bss_parameters {
* @dot11MeshHWMPconfirmationInterval: The minimum interval of time (in TUs) * @dot11MeshHWMPconfirmationInterval: The minimum interval of time (in TUs)
* during which a mesh STA can send only one Action frame containing * during which a mesh STA can send only one Action frame containing
* a PREQ element for root path confirmation. * a PREQ element for root path confirmation.
* @power_mode: The default mesh power save mode which will be the initial
* setting for new peer links.
* @dot11MeshAwakeWindowDuration: The duration in TUs the STA will remain awake
* after transmitting its beacon.
*/ */
struct mesh_config { struct mesh_config {
u16 dot11MeshRetryTimeout; u16 dot11MeshRetryTimeout;
...@@ -1022,6 +1041,8 @@ struct mesh_config { ...@@ -1022,6 +1041,8 @@ struct mesh_config {
u32 dot11MeshHWMPactivePathToRootTimeout; u32 dot11MeshHWMPactivePathToRootTimeout;
u16 dot11MeshHWMProotInterval; u16 dot11MeshHWMProotInterval;
u16 dot11MeshHWMPconfirmationInterval; u16 dot11MeshHWMPconfirmationInterval;
enum nl80211_mesh_power_mode power_mode;
u16 dot11MeshAwakeWindowDuration;
}; };
/** /**
......
...@@ -1310,6 +1310,9 @@ enum nl80211_commands { ...@@ -1310,6 +1310,9 @@ enum nl80211_commands {
* if not given in START_AP 0 is assumed, if not given in SET_BSS * if not given in START_AP 0 is assumed, if not given in SET_BSS
* no change is made. * no change is made.
* *
* @NL80211_ATTR_LOCAL_MESH_POWER_MODE: local mesh STA link-specific power mode
* defined in &enum nl80211_mesh_power_mode.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined * @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use * @__NL80211_ATTR_AFTER_LAST: internal use
*/ */
...@@ -1580,6 +1583,8 @@ enum nl80211_attrs { ...@@ -1580,6 +1583,8 @@ enum nl80211_attrs {
NL80211_ATTR_P2P_CTWINDOW, NL80211_ATTR_P2P_CTWINDOW,
NL80211_ATTR_P2P_OPPPS, NL80211_ATTR_P2P_OPPPS,
NL80211_ATTR_LOCAL_MESH_POWER_MODE,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST, __NL80211_ATTR_AFTER_LAST,
...@@ -1838,6 +1843,10 @@ enum nl80211_sta_bss_param { ...@@ -1838,6 +1843,10 @@ enum nl80211_sta_bss_param {
* @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
* @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32)
* @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64) * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64)
* @NL80211_STA_INFO_LOCAL_PM: local mesh STA link-specific power mode
* @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode
* @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards
* non-peer STA
* @__NL80211_STA_INFO_AFTER_LAST: internal * @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute * @NL80211_STA_INFO_MAX: highest possible station info attribute
*/ */
...@@ -1862,6 +1871,9 @@ enum nl80211_sta_info { ...@@ -1862,6 +1871,9 @@ enum nl80211_sta_info {
NL80211_STA_INFO_STA_FLAGS, NL80211_STA_INFO_STA_FLAGS,
NL80211_STA_INFO_BEACON_LOSS, NL80211_STA_INFO_BEACON_LOSS,
NL80211_STA_INFO_T_OFFSET, NL80211_STA_INFO_T_OFFSET,
NL80211_STA_INFO_LOCAL_PM,
NL80211_STA_INFO_PEER_PM,
NL80211_STA_INFO_NONPEER_PM,
/* keep last */ /* keep last */
__NL80211_STA_INFO_AFTER_LAST, __NL80211_STA_INFO_AFTER_LAST,
...@@ -2252,6 +2264,34 @@ enum nl80211_mntr_flags { ...@@ -2252,6 +2264,34 @@ enum nl80211_mntr_flags {
NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1
}; };
/**
* enum nl80211_mesh_power_mode - mesh power save modes
*
* @NL80211_MESH_POWER_UNKNOWN: The mesh power mode of the mesh STA is
* not known or has not been set yet.
* @NL80211_MESH_POWER_ACTIVE: Active mesh power mode. The mesh STA is
* in Awake state all the time.
* @NL80211_MESH_POWER_LIGHT_SLEEP: Light sleep mode. The mesh STA will
* alternate between Active and Doze states, but will wake up for
* neighbor's beacons.
* @NL80211_MESH_POWER_DEEP_SLEEP: Deep sleep mode. The mesh STA will
* alternate between Active and Doze states, but may not wake up
* for neighbor's beacons.
*
* @__NL80211_MESH_POWER_AFTER_LAST - internal use
* @NL80211_MESH_POWER_MAX - highest possible power save level
*/
enum nl80211_mesh_power_mode {
NL80211_MESH_POWER_UNKNOWN,
NL80211_MESH_POWER_ACTIVE,
NL80211_MESH_POWER_LIGHT_SLEEP,
NL80211_MESH_POWER_DEEP_SLEEP,
__NL80211_MESH_POWER_AFTER_LAST,
NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1
};
/** /**
* enum nl80211_meshconf_params - mesh configuration parameters * enum nl80211_meshconf_params - mesh configuration parameters
* *
...@@ -2346,6 +2386,11 @@ enum nl80211_mntr_flags { ...@@ -2346,6 +2386,11 @@ enum nl80211_mntr_flags {
* (in TUs) during which a mesh STA can send only one Action frame * (in TUs) during which a mesh STA can send only one Action frame
* containing a PREQ element for root path confirmation. * containing a PREQ element for root path confirmation.
* *
* @NL80211_MESHCONF_POWER_MODE: Default mesh power mode for new peer links.
* type &enum nl80211_mesh_power_mode (u32)
*
* @NL80211_MESHCONF_AWAKE_WINDOW: awake window duration (in TUs)
*
* @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use
*/ */
enum nl80211_meshconf_params { enum nl80211_meshconf_params {
...@@ -2375,6 +2420,8 @@ enum nl80211_meshconf_params { ...@@ -2375,6 +2420,8 @@ enum nl80211_meshconf_params {
NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT,
NL80211_MESHCONF_HWMP_ROOT_INTERVAL, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
NL80211_MESHCONF_POWER_MODE,
NL80211_MESHCONF_AWAKE_WINDOW,
/* keep last */ /* keep last */
__NL80211_MESHCONF_ATTR_AFTER_LAST, __NL80211_MESHCONF_ATTR_AFTER_LAST,
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units (=TUs) */ #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units (=TUs) */
#define MESH_DEFAULT_DTIM_PERIOD 2 #define MESH_DEFAULT_DTIM_PERIOD 2
#define MESH_DEFAULT_AWAKE_WINDOW 10 /* in 1024 us units (=TUs) */
const struct mesh_config default_mesh_config = { const struct mesh_config default_mesh_config = {
.dot11MeshRetryTimeout = MESH_RET_T, .dot11MeshRetryTimeout = MESH_RET_T,
...@@ -72,6 +73,8 @@ const struct mesh_config default_mesh_config = { ...@@ -72,6 +73,8 @@ const struct mesh_config default_mesh_config = {
.dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT, .dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT,
.dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL, .dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL,
.dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL, .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL,
.power_mode = NL80211_MESH_POWER_ACTIVE,
.dot11MeshAwakeWindowDuration = MESH_DEFAULT_AWAKE_WINDOW,
}; };
const struct mesh_setup default_mesh_setup = { const struct mesh_setup default_mesh_setup = {
......
...@@ -3001,6 +3001,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -3001,6 +3001,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS,
sinfo->beacon_loss_count)) sinfo->beacon_loss_count))
goto nla_put_failure; goto nla_put_failure;
if ((sinfo->filled & STATION_INFO_LOCAL_PM) &&
nla_put_u32(msg, NL80211_STA_INFO_LOCAL_PM,
sinfo->local_pm))
goto nla_put_failure;
if ((sinfo->filled & STATION_INFO_PEER_PM) &&
nla_put_u32(msg, NL80211_STA_INFO_PEER_PM,
sinfo->peer_pm))
goto nla_put_failure;
if ((sinfo->filled & STATION_INFO_NONPEER_PM) &&
nla_put_u32(msg, NL80211_STA_INFO_NONPEER_PM,
sinfo->nonpeer_pm))
goto nla_put_failure;
if (sinfo->filled & STATION_INFO_BSS_PARAM) { if (sinfo->filled & STATION_INFO_BSS_PARAM) {
bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM);
if (!bss_param) if (!bss_param)
...@@ -3206,6 +3218,17 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) ...@@ -3206,6 +3218,17 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
params.plink_state = params.plink_state =
nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) {
enum nl80211_mesh_power_mode pm = nla_get_u32(
info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]);
if (pm <= NL80211_MESH_POWER_UNKNOWN ||
pm > NL80211_MESH_POWER_MAX)
return -EINVAL;
params.local_pm = pm;
}
switch (dev->ieee80211_ptr->iftype) { switch (dev->ieee80211_ptr->iftype) {
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_AP_VLAN:
...@@ -3213,6 +3236,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) ...@@ -3213,6 +3236,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
/* disallow mesh-specific things */ /* disallow mesh-specific things */
if (params.plink_action) if (params.plink_action)
return -EINVAL; return -EINVAL;
if (params.local_pm)
return -EINVAL;
/* TDLS can't be set, ... */ /* TDLS can't be set, ... */
if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
...@@ -3265,6 +3290,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) ...@@ -3265,6 +3290,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
/* disallow things sta doesn't support */ /* disallow things sta doesn't support */
if (params.plink_action) if (params.plink_action)
return -EINVAL; return -EINVAL;
if (params.local_pm)
return -EINVAL;
/* reject any changes other than AUTHORIZED */ /* reject any changes other than AUTHORIZED */
if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
return -EINVAL; return -EINVAL;
...@@ -3922,7 +3949,11 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, ...@@ -3922,7 +3949,11 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL,
cur_params.dot11MeshHWMProotInterval) || cur_params.dot11MeshHWMProotInterval) ||
nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
cur_params.dot11MeshHWMPconfirmationInterval)) cur_params.dot11MeshHWMPconfirmationInterval) ||
nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE,
cur_params.power_mode) ||
nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW,
cur_params.dot11MeshAwakeWindowDuration))
goto nla_put_failure; goto nla_put_failure;
nla_nest_end(msg, pinfoattr); nla_nest_end(msg, pinfoattr);
genlmsg_end(msg, hdr); genlmsg_end(msg, hdr);
...@@ -3961,6 +3992,8 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A ...@@ -3961,6 +3992,8 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
[NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 }, [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
[NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 },
[NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 },
[NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 },
[NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
}; };
static const struct nla_policy static const struct nla_policy
...@@ -4088,6 +4121,14 @@ do { \ ...@@ -4088,6 +4121,14 @@ do { \
1, 65535, mask, 1, 65535, mask,
NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
nla_get_u16); nla_get_u16);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode,
NL80211_MESH_POWER_ACTIVE,
NL80211_MESH_POWER_MAX,
mask, NL80211_MESHCONF_POWER_MODE,
nla_get_u32);
FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration,
0, 65535, mask,
NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16);
if (mask_out) if (mask_out)
*mask_out = mask; *mask_out = mask;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment