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.
Unified · Split
| @@ -610,6 +610,8 @@ enum station_parameters_apply_mask { · 609 unmodified lines | ||
| 610 | 610 | * @sta_modify_mask: bitmap indicating which parameters changed |
| 611 | 611 | * (for those that don't have a natural "no change" value), |
| 612 | 612 | * see &enum station_parameters_apply_mask |
| 613 | + * @local_pm: local link-specific mesh power save mode (no change when set | |
| 614 | + * to unknown) | |
| 613 | 615 | */ |
| 614 | 616 | struct station_parameters { |
| 615 | 617 | u8 *supported_rates; |
| @@ -625,6 +627,7 @@ struct station_parameters { · 9 unmodified lines | ||
| 625 | 627 | struct ieee80211_vht_cap *vht_capa; |
| 626 | 628 | u8 uapsd_queues; |
| 627 | 629 | u8 max_sp; |
| 630 | + enum nl80211_mesh_power_mode local_pm; | |
| 628 | 631 | }; |
| 629 | 632 | |
| 630 | 633 | /** |
| @@ -655,6 +658,9 @@ struct station_parameters { · 24 unmodified lines | ||
| 655 | 658 | * @STATION_INFO_STA_FLAGS: @sta_flags filled |
| 656 | 659 | * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled |
| 657 | 660 | * @STATION_INFO_T_OFFSET: @t_offset filled |
| 661 | + * @STATION_INFO_LOCAL_PM: @local_pm filled | |
| 662 | + * @STATION_INFO_PEER_PM: @peer_pm filled | |
| 663 | + * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled | |
| 658 | 664 | */ |
| 659 | 665 | enum station_info_flags { |
| 660 | 666 | STATION_INFO_INACTIVE_TIME = 1<<0, |
| @@ -678,6 +684,9 @@ enum station_info_flags { · 17 unmodified lines | ||
| 678 | 684 | STATION_INFO_STA_FLAGS = 1<<18, |
| 679 | 685 | STATION_INFO_BEACON_LOSS_COUNT = 1<<19, |
| 680 | 686 | STATION_INFO_T_OFFSET = 1<<20, |
| 687 | + STATION_INFO_LOCAL_PM = 1<<21, | |
| 688 | + STATION_INFO_PEER_PM = 1<<22, | |
| 689 | + STATION_INFO_NONPEER_PM = 1<<23, | |
| 681 | 690 | }; |
| 682 | 691 | |
| 683 | 692 | /** |
| @@ -791,6 +800,9 @@ struct sta_bss_parameters { · 107 unmodified lines | ||
| 791 | 800 | * @sta_flags: station flags mask & values |
| 792 | 801 | * @beacon_loss_count: Number of times beacon loss event has triggered. |
| 793 | 802 | * @t_offset: Time offset of the station relative to this host. |
| 803 | + * @local_pm: local mesh STA power save mode | |
| 804 | + * @peer_pm: peer mesh STA power save mode | |
| 805 | + * @nonpeer_pm: non-peer mesh STA power save mode | |
| 794 | 806 | */ |
| 795 | 807 | struct station_info { |
| 796 | 808 | u32 filled; |
| @@ -820,6 +832,9 @@ struct station_info { · 23 unmodified lines | ||
| 820 | 832 | |
| 821 | 833 | u32 beacon_loss_count; |
| 822 | 834 | s64 t_offset; |
| 835 | + enum nl80211_mesh_power_mode local_pm; | |
| 836 | + enum nl80211_mesh_power_mode peer_pm; | |
| 837 | + enum nl80211_mesh_power_mode nonpeer_pm; | |
| 823 | 838 | |
| 824 | 839 | /* |
| 825 | 840 | * Note: Add a new enum station_info_flags value for each new field and |
| @@ -995,6 +1010,10 @@ struct bss_parameters { · 169 unmodified lines | ||
| 995 | 1010 | * @dot11MeshHWMPconfirmationInterval: The minimum interval of time (in TUs) |
| 996 | 1011 | * during which a mesh STA can send only one Action frame containing |
| 997 | 1012 | * a PREQ element for root path confirmation. |
| 1013 | + * @power_mode: The default mesh power save mode which will be the initial | |
| 1014 | + * setting for new peer links. | |
| 1015 | + * @dot11MeshAwakeWindowDuration: The duration in TUs the STA will remain awake | |
| 1016 | + * after transmitting its beacon. | |
| 998 | 1017 | */ |
| 999 | 1018 | struct mesh_config { |
| 1000 | 1019 | u16 dot11MeshRetryTimeout; |
| @@ -1022,6 +1041,8 @@ struct mesh_config { · 21 unmodified lines | ||
| 1022 | 1041 | u32 dot11MeshHWMPactivePathToRootTimeout; |
| 1023 | 1042 | u16 dot11MeshHWMProotInterval; |
| 1024 | 1043 | u16 dot11MeshHWMPconfirmationInterval; |
| 1044 | + enum nl80211_mesh_power_mode power_mode; | |
| 1045 | + u16 dot11MeshAwakeWindowDuration; | |
| 1025 | 1046 | }; |
| 1026 | 1047 | |
| 1027 | 1048 | /** |
| @@ -1310,6 +1310,9 @@ enum nl80211_commands { · 1309 unmodified lines | ||
| 1310 | 1310 | * if not given in START_AP 0 is assumed, if not given in SET_BSS |
| 1311 | 1311 | * no change is made. |
| 1312 | 1312 | * |
| 1313 | + * @NL80211_ATTR_LOCAL_MESH_POWER_MODE: local mesh STA link-specific power mode | |
| 1314 | + * defined in &enum nl80211_mesh_power_mode. | |
| 1315 | + * | |
| 1313 | 1316 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| 1314 | 1317 | * @__NL80211_ATTR_AFTER_LAST: internal use |
| 1315 | 1318 | */ |
| @@ -1580,6 +1583,8 @@ enum nl80211_attrs { · 264 unmodified lines | ||
| 1580 | 1583 | NL80211_ATTR_P2P_CTWINDOW, |
| 1581 | 1584 | NL80211_ATTR_P2P_OPPPS, |
| 1582 | 1585 | |
| 1586 | + NL80211_ATTR_LOCAL_MESH_POWER_MODE, | |
| 1587 | + | |
| 1583 | 1588 | /* add attributes here, update the policy in nl80211.c */ |
| 1584 | 1589 | |
| 1585 | 1590 | __NL80211_ATTR_AFTER_LAST, |
| @@ -1838,6 +1843,10 @@ enum nl80211_sta_bss_param { · 252 unmodified lines | ||
| 1838 | 1843 | * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. |
| 1839 | 1844 | * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) |
| 1840 | 1845 | * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64) |
| 1846 | + * @NL80211_STA_INFO_LOCAL_PM: local mesh STA link-specific power mode | |
| 1847 | + * @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode | |
| 1848 | + * @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards | |
| 1849 | + * non-peer STA | |
| 1841 | 1850 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
| 1842 | 1851 | * @NL80211_STA_INFO_MAX: highest possible station info attribute |
| 1843 | 1852 | */ |
| @@ -1862,6 +1871,9 @@ enum nl80211_sta_info { · 18 unmodified lines | ||
| 1862 | 1871 | NL80211_STA_INFO_STA_FLAGS, |
| 1863 | 1872 | NL80211_STA_INFO_BEACON_LOSS, |
| 1864 | 1873 | NL80211_STA_INFO_T_OFFSET, |
| 1874 | + NL80211_STA_INFO_LOCAL_PM, | |
| 1875 | + NL80211_STA_INFO_PEER_PM, | |
| 1876 | + NL80211_STA_INFO_NONPEER_PM, | |
| 1865 | 1877 | |
| 1866 | 1878 | /* keep last */ |
| 1867 | 1879 | __NL80211_STA_INFO_AFTER_LAST, |
| @@ -2252,6 +2264,34 @@ enum nl80211_mntr_flags { · 384 unmodified lines | ||
| 2252 | 2264 | NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 |
| 2253 | 2265 | }; |
| 2254 | 2266 | |
| 2267 | +/** | |
| 2268 | + * enum nl80211_mesh_power_mode - mesh power save modes | |
| 2269 | + * | |
| 2270 | + * @NL80211_MESH_POWER_UNKNOWN: The mesh power mode of the mesh STA is | |
| 2271 | + * not known or has not been set yet. | |
| 2272 | + * @NL80211_MESH_POWER_ACTIVE: Active mesh power mode. The mesh STA is | |
| 2273 | + * in Awake state all the time. | |
| 2274 | + * @NL80211_MESH_POWER_LIGHT_SLEEP: Light sleep mode. The mesh STA will | |
| 2275 | + * alternate between Active and Doze states, but will wake up for | |
| 2276 | + * neighbor's beacons. | |
| 2277 | + * @NL80211_MESH_POWER_DEEP_SLEEP: Deep sleep mode. The mesh STA will | |
| 2278 | + * alternate between Active and Doze states, but may not wake up | |
| 2279 | + * for neighbor's beacons. | |
| 2280 | + * | |
| 2281 | + * @__NL80211_MESH_POWER_AFTER_LAST - internal use | |
| 2282 | + * @NL80211_MESH_POWER_MAX - highest possible power save level | |
| 2283 | + */ | |
| 2284 | + | |
| 2285 | +enum nl80211_mesh_power_mode { | |
| 2286 | + NL80211_MESH_POWER_UNKNOWN, | |
| 2287 | + NL80211_MESH_POWER_ACTIVE, | |
| 2288 | + NL80211_MESH_POWER_LIGHT_SLEEP, | |
| 2289 | + NL80211_MESH_POWER_DEEP_SLEEP, | |
| 2290 | + | |
| 2291 | + __NL80211_MESH_POWER_AFTER_LAST, | |
| 2292 | + NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1 | |
| 2293 | +}; | |
| 2294 | + | |
| 2255 | 2295 | /** |
| 2256 | 2296 | * enum nl80211_meshconf_params - mesh configuration parameters |
| 2257 | 2297 | * |
| @@ -2346,6 +2386,11 @@ enum nl80211_mntr_flags { · 88 unmodified lines | ||
| 2346 | 2386 | * (in TUs) during which a mesh STA can send only one Action frame |
| 2347 | 2387 | * containing a PREQ element for root path confirmation. |
| 2348 | 2388 | * |
| 2389 | + * @NL80211_MESHCONF_POWER_MODE: Default mesh power mode for new peer links. | |
| 2390 | + * type &enum nl80211_mesh_power_mode (u32) | |
| 2391 | + * | |
| 2392 | + * @NL80211_MESHCONF_AWAKE_WINDOW: awake window duration (in TUs) | |
| 2393 | + * | |
| 2349 | 2394 | * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use |
| 2350 | 2395 | */ |
| 2351 | 2396 | enum nl80211_meshconf_params { |
| @@ -2375,6 +2420,8 @@ enum nl80211_meshconf_params { · 23 unmodified lines | ||
| 2375 | 2420 | NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, |
| 2376 | 2421 | NL80211_MESHCONF_HWMP_ROOT_INTERVAL, |
| 2377 | 2422 | NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, |
| 2423 | + NL80211_MESHCONF_POWER_MODE, | |
| 2424 | + NL80211_MESHCONF_AWAKE_WINDOW, | |
| 2378 | 2425 | |
| 2379 | 2426 | /* keep last */ |
| 2380 | 2427 | __NL80211_MESHCONF_ATTR_AFTER_LAST, |
| @@ -46,6 +46,7 @@ · 45 unmodified lines | ||
| 46 | 46 | |
| 47 | 47 | #define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units (=TUs) */ |
| 48 | 48 | #define MESH_DEFAULT_DTIM_PERIOD 2 |
| 49 | +#define MESH_DEFAULT_AWAKE_WINDOW 10 /* in 1024 us units (=TUs) */ | |
| 49 | 50 | |
| 50 | 51 | const struct mesh_config default_mesh_config = { |
| 51 | 52 | .dot11MeshRetryTimeout = MESH_RET_T, |
| @@ -72,6 +73,8 @@ const struct mesh_config default_mesh_config = { · 20 unmodified lines | ||
| 72 | 73 | .dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT, |
| 73 | 74 | .dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL, |
| 74 | 75 | .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL, |
| 76 | + .power_mode = NL80211_MESH_POWER_ACTIVE, | |
| 77 | + .dot11MeshAwakeWindowDuration = MESH_DEFAULT_AWAKE_WINDOW, | |
| 75 | 78 | }; |
| 76 | 79 | |
| 77 | 80 | const struct mesh_setup default_mesh_setup = { |
| @@ -3001,6 +3001,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, · 3000 unmodified lines | ||
| 3001 | 3001 | nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS, |
| 3002 | 3002 | sinfo->beacon_loss_count)) |
| 3003 | 3003 | goto nla_put_failure; |
| 3004 | + if ((sinfo->filled & STATION_INFO_LOCAL_PM) && | |
| 3005 | + nla_put_u32(msg, NL80211_STA_INFO_LOCAL_PM, | |
| 3006 | + sinfo->local_pm)) | |
| 3007 | + goto nla_put_failure; | |
| 3008 | + if ((sinfo->filled & STATION_INFO_PEER_PM) && | |
| 3009 | + nla_put_u32(msg, NL80211_STA_INFO_PEER_PM, | |
| 3010 | + sinfo->peer_pm)) | |
| 3011 | + goto nla_put_failure; | |
| 3012 | + if ((sinfo->filled & STATION_INFO_NONPEER_PM) && | |
| 3013 | + nla_put_u32(msg, NL80211_STA_INFO_NONPEER_PM, | |
| 3014 | + sinfo->nonpeer_pm)) | |
| 3015 | + goto nla_put_failure; | |
| 3004 | 3016 | if (sinfo->filled & STATION_INFO_BSS_PARAM) { |
| 3005 | 3017 | bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM); |
| 3006 | 3018 | if (!bss_param) |
| @@ -3206,6 +3218,17 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 199 unmodified lines | ||
| 3206 | 3218 | params.plink_state = |
| 3207 | 3219 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); |
| 3208 | 3220 | |
| 3221 | + if (info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]) { | |
| 3222 | + enum nl80211_mesh_power_mode pm = nla_get_u32( | |
| 3223 | + info->attrs[NL80211_ATTR_LOCAL_MESH_POWER_MODE]); | |
| 3224 | + | |
| 3225 | + if (pm <= NL80211_MESH_POWER_UNKNOWN || | |
| 3226 | + pm > NL80211_MESH_POWER_MAX) | |
| 3227 | + return -EINVAL; | |
| 3228 | + | |
| 3229 | + params.local_pm = pm; | |
| 3230 | + } | |
| 3231 | + | |
| 3209 | 3232 | switch (dev->ieee80211_ptr->iftype) { |
| 3210 | 3233 | case NL80211_IFTYPE_AP: |
| 3211 | 3234 | case NL80211_IFTYPE_AP_VLAN: |
| @@ -3213,6 +3236,8 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line | ||
| 3213 | 3236 | /* disallow mesh-specific things */ |
| 3214 | 3237 | if (params.plink_action) |
| 3215 | 3238 | return -EINVAL; |
| 3239 | + if (params.local_pm) | |
| 3240 | + return -EINVAL; | |
| 3216 | 3241 | |
| 3217 | 3242 | /* TDLS can't be set, ... */ |
| 3218 | 3243 | 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) · 46 unmodified lines | ||
| 3265 | 3290 | /* disallow things sta doesn't support */ |
| 3266 | 3291 | if (params.plink_action) |
| 3267 | 3292 | return -EINVAL; |
| 3293 | + if (params.local_pm) | |
| 3294 | + return -EINVAL; | |
| 3268 | 3295 | /* reject any changes other than AUTHORIZED */ |
| 3269 | 3296 | if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) |
| 3270 | 3297 | return -EINVAL; |
| @@ -3922,7 +3949,11 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, · 651 unmodified lines | ||
| 3922 | 3949 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_ROOT_INTERVAL, |
| 3923 | 3950 | cur_params.dot11MeshHWMProotInterval) || |
| 3924 | 3951 | nla_put_u16(msg, NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, |
| 3925 | − cur_params.dot11MeshHWMPconfirmationInterval)) | |
| 3952 | + cur_params.dot11MeshHWMPconfirmationInterval) || | |
| 3953 | + nla_put_u32(msg, NL80211_MESHCONF_POWER_MODE, | |
| 3954 | + cur_params.power_mode) || | |
| 3955 | + nla_put_u16(msg, NL80211_MESHCONF_AWAKE_WINDOW, | |
| 3956 | + cur_params.dot11MeshAwakeWindowDuration)) | |
| 3926 | 3957 | goto nla_put_failure; |
| 3927 | 3958 | nla_nest_end(msg, pinfoattr); |
| 3928 | 3959 | genlmsg_end(msg, hdr); |
| @@ -3961,6 +3992,8 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A · 32 unmodified lines | ||
| 3961 | 3992 | [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 }, |
| 3962 | 3993 | [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 }, |
| 3963 | 3994 | [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 }, |
| 3995 | + [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 }, | |
| 3996 | + [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 }, | |
| 3964 | 3997 | }; |
| 3965 | 3998 | |
| 3966 | 3999 | static const struct nla_policy |
| @@ -4088,6 +4121,14 @@ do { \ · 121 unmodified lines | ||
| 4088 | 4121 | 1, 65535, mask, |
| 4089 | 4122 | NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, |
| 4090 | 4123 | nla_get_u16); |
| 4124 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, power_mode, | |
| 4125 | + NL80211_MESH_POWER_ACTIVE, | |
| 4126 | + NL80211_MESH_POWER_MAX, | |
| 4127 | + mask, NL80211_MESHCONF_POWER_MODE, | |
| 4128 | + nla_get_u32); | |
| 4129 | + FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshAwakeWindowDuration, | |
| 4130 | + 0, 65535, mask, | |
| 4131 | + NL80211_MESHCONF_AWAKE_WINDOW, nla_get_u16); | |
| 4091 | 4132 | if (mask_out) |
| 4092 | 4133 | *mask_out = mask; |
| 4093 | 4134 | |