2013-01-18 12:05:41

by Marco Porsch

[permalink] [raw]
Subject: [PATCH 0/3] iw: mesh power save

The following commits cover all neccessary iw commands for mesh
power save. Beacon interval, DTIM period, default power mode and
awake window are accessed as part of the mesh params. The
link-specific power modes are set for peer STA.

Marco Porsch (3):
iw: add beacon interval and DTIM period parameters to mesh join
iw: add default mesh Power Mode and Awake Window to mesh config
iw: add support for link-specific mesh power modes

mesh.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
station.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 169 insertions(+), 4 deletions(-)

--
1.7.9.5



2013-01-29 11:56:09

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/3] iw: mesh power save

On Fri, 2013-01-18 at 13:05 +0100, Marco Porsch wrote:
> The following commits cover all neccessary iw commands for mesh
> power save. Beacon interval, DTIM period, default power mode and
> awake window are accessed as part of the mesh params. The
> link-specific power modes are set for peer STA.

Applied.

johannes


2013-01-18 12:05:43

by Marco Porsch

[permalink] [raw]
Subject: [PATCH 2/3] iw: add default mesh Power Mode and Awake Window to mesh config

The default mesh power mode is the power mode that will be
assigned to newly established peer links.
The awake window is the duration the local STA will stay awake
after sending its own beacon in PS mode.
Both values can be modified as part of the mesh params.

Signed-off-by: Marco Porsch <[email protected]>
Signed-off-by: Ivan Bezyazychnyy <[email protected]>
---
mesh.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/mesh.c b/mesh.c
index 958c2c0..5a09b62 100644
--- a/mesh.c
+++ b/mesh.c
@@ -109,6 +109,23 @@ static uint32_t _parse_s32(const char *str, _any *ret)
return 0;
}

+static uint32_t _parse_u32_power_mode(const char *str, _any *ret)
+{
+ unsigned long int v;
+
+ /* Parse attribute for the name of power mode */
+ if (!strcmp(str, "active"))
+ v = NL80211_MESH_POWER_ACTIVE;
+ else if (!strcmp(str, "light"))
+ v = NL80211_MESH_POWER_LIGHT_SLEEP;
+ else if (!strcmp(str, "deep"))
+ v = NL80211_MESH_POWER_DEEP_SLEEP;
+ else
+ return 0xff;
+
+ ret->u.as_32 = (uint32_t)v;
+ return 0;
+}

static void _print_u8(struct nlattr *a)
{
@@ -145,6 +162,26 @@ static void _print_u32_in_TUs(struct nlattr *a)
printf("%d TUs", nla_get_u32(a));
}

+static void _print_u32_power_mode(struct nlattr *a)
+{
+ unsigned long v = nla_get_u32(a);
+
+ switch (v) {
+ case NL80211_MESH_POWER_ACTIVE:
+ printf("active");
+ break;
+ case NL80211_MESH_POWER_LIGHT_SLEEP:
+ printf("light");
+ break;
+ case NL80211_MESH_POWER_DEEP_SLEEP:
+ printf("deep");
+ break;
+ default:
+ printf("undefined");
+ break;
+ }
+}
+
static void _print_s32_in_dBm(struct nlattr *a)
{
printf("%d dBm", (int32_t) nla_get_u32(a));
@@ -217,6 +254,10 @@ const static struct mesh_param_descr _mesh_param_descrs[] =
{"mesh_hwmp_confirmation_interval",
NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL,
_my_nla_put_u16, _parse_u16, _print_u16_in_TUs},
+ {"mesh_power_mode", NL80211_MESHCONF_POWER_MODE,
+ _my_nla_put_u32, _parse_u32_power_mode, _print_u32_power_mode},
+ {"mesh_awake_window", NL80211_MESHCONF_AWAKE_WINDOW,
+ _my_nla_put_u16, _parse_u16, _print_u16_in_TUs},
};

static void print_all_mesh_param_descr(void)
@@ -294,8 +335,15 @@ static int set_interface_meshparam(struct nl80211_state *state,
/* Parse the new value */
ret = mdescr->parse_fn(value, &any);
if (ret != 0) {
- printf("%s must be set to a number "
- "between 0 and %u\n", mdescr->name, ret);
+ if (mdescr->mesh_param_num
+ == NL80211_MESHCONF_POWER_MODE)
+ printf("%s must be set to active, light or "
+ "deep.\n", mdescr->name);
+ else
+ printf("%s must be set to a number "
+ "between 0 and %u\n",
+ mdescr->name, ret);
+
return 2;
}

--
1.7.9.5


2013-01-18 12:05:45

by Marco Porsch

[permalink] [raw]
Subject: [PATCH 3/3] iw: add support for link-specific mesh power modes

The different power modes of links towards neighbor STA can be
read using
iw <dev> station get
-or-
iw <dev> station dump

The different power modes shown are:
- mesh local PS mode
- mesh peer PS mode
- mesh non-peer PS mode
where the local PS mode is "our" mode towards the neighbor, the
peer PS mode is the neighbor's mode towards us, and the non-peer
PS mode is the neighbor's non-peer PS mode as indicated in
beacons and management frames.

The local PS mode can be modified for each neighbor using
iw <dev> station set <mac-addr> mesh_power_mode
<active|light|deep>

Signed-off-by: Marco Porsch <[email protected]>
Signed-off-by: Ivan Bezyazychnyy <[email protected]>
---
station.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)

diff --git a/station.c b/station.c
index 247f445..eb02b0c 100644
--- a/station.c
+++ b/station.c
@@ -29,6 +29,25 @@ enum plink_actions {
PLINK_ACTION_BLOCK,
};

+static void print_power_mode(struct nlattr *a)
+{
+ enum nl80211_mesh_power_mode pm = nla_get_u32(a);
+
+ switch (pm) {
+ case NL80211_MESH_POWER_ACTIVE:
+ printf("ACTIVE");
+ break;
+ case NL80211_MESH_POWER_LIGHT_SLEEP:
+ printf("LIGHT SLEEP");
+ break;
+ case NL80211_MESH_POWER_DEEP_SLEEP:
+ printf("DEEP SLEEP");
+ break;
+ default:
+ printf("UNKNOWN");
+ break;
+ }
+}

static int print_sta_handler(struct nl_msg *msg, void *arg)
{
@@ -54,6 +73,9 @@ static int print_sta_handler(struct nl_msg *msg, void *arg)
[NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
[NL80211_STA_INFO_STA_FLAGS] =
{ .minlen = sizeof(struct nl80211_sta_flag_update) },
+ [NL80211_STA_INFO_LOCAL_PM] = { .type = NLA_U32},
+ [NL80211_STA_INFO_PEER_PM] = { .type = NLA_U32},
+ [NL80211_STA_INFO_NONPEER_PM] = { .type = NLA_U32},
};

static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
@@ -177,6 +199,18 @@ static int print_sta_handler(struct nl_msg *msg, void *arg)
}
printf("\n\tmesh plink:\t%s", state_name);
}
+ if (sinfo[NL80211_STA_INFO_LOCAL_PM]) {
+ printf("\n\tmesh local PS mode:\t");
+ print_power_mode(sinfo[NL80211_STA_INFO_LOCAL_PM]);
+ }
+ if (sinfo[NL80211_STA_INFO_PEER_PM]) {
+ printf("\n\tmesh peer PS mode:\t");
+ print_power_mode(sinfo[NL80211_STA_INFO_PEER_PM]);
+ }
+ if (sinfo[NL80211_STA_INFO_NONPEER_PM]) {
+ printf("\n\tmesh non-peer PS mode:\t");
+ print_power_mode(sinfo[NL80211_STA_INFO_NONPEER_PM]);
+ }

if (sinfo[NL80211_STA_INFO_STA_FLAGS]) {
sta_flags = (struct nl80211_sta_flag_update *)
@@ -274,6 +308,7 @@ COMMAND(station, del, "<MAC address>",

static const struct cmd *station_set_plink;
static const struct cmd *station_set_vlan;
+static const struct cmd *station_set_mesh_power_mode;

static const struct cmd *select_station_cmd(int argc, char **argv)
{
@@ -283,6 +318,8 @@ static const struct cmd *select_station_cmd(int argc, char **argv)
return station_set_plink;
if (strcmp(argv[1], "vlan") == 0)
return station_set_vlan;
+ if (strcmp(argv[1], "mesh_power_mode") == 0)
+ return station_set_mesh_power_mode;
return NULL;
}

@@ -384,6 +421,58 @@ COMMAND_ALIAS(station, set, "<MAC address> vlan <ifindex>",
"Set an AP VLAN for this station.",
select_station_cmd, station_set_vlan);

+static int handle_station_set_mesh_power_mode(struct nl80211_state *state,
+ struct nl_cb *cb,
+ struct nl_msg *msg,
+ int argc, char **argv,
+ enum id_input id)
+{
+ unsigned char mesh_power_mode;
+ unsigned char mac_addr[ETH_ALEN];
+
+ if (argc < 3)
+ return 1;
+
+ if (mac_addr_a2n(mac_addr, argv[0])) {
+ fprintf(stderr, "invalid mac address\n");
+ return 2;
+ }
+ argc--;
+ argv++;
+
+ if (strcmp("mesh_power_mode", argv[0]) != 0)
+ return 1;
+ argc--;
+ argv++;
+
+ if (strcmp("active", argv[0]) == 0)
+ mesh_power_mode = NL80211_MESH_POWER_ACTIVE;
+ else if (strcmp("light", argv[0]) == 0)
+ mesh_power_mode = NL80211_MESH_POWER_LIGHT_SLEEP;
+ else if (strcmp("deep", argv[0]) == 0)
+ mesh_power_mode = NL80211_MESH_POWER_DEEP_SLEEP;
+ else {
+ fprintf(stderr, "unknown mesh power mode\n");
+ return 2;
+ }
+ argc--;
+ argv++;
+
+ if (argc)
+ return 1;
+
+ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
+ NLA_PUT_U32(msg, NL80211_ATTR_LOCAL_MESH_POWER_MODE, mesh_power_mode);
+
+ return 0;
+nla_put_failure:
+ return -ENOBUFS;
+}
+COMMAND_ALIAS(station, set, "<MAC address> mesh_power_mode "
+ "<active|light|deep>", NL80211_CMD_SET_STATION, 0, CIB_NETDEV,
+ handle_station_set_mesh_power_mode,
+ "Set link-specific mesh power mode for this station",
+ select_station_cmd, station_set_mesh_power_mode);

static int handle_station_dump(struct nl80211_state *state,
struct nl_cb *cb,
--
1.7.9.5


2013-01-18 12:05:42

by Marco Porsch

[permalink] [raw]
Subject: [PATCH 1/3] iw: add beacon interval and DTIM period parameters to mesh join

Set the beacon interval and DTIM period with the mesh join
command:
iw <dev> mesh join <meshid> beacon-interval <time in TUs>
dtim-period <value>

Signed-off-by: Marco Porsch <[email protected]>
---
mesh.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/mesh.c b/mesh.c
index 4fdad6a..958c2c0 100644
--- a/mesh.c
+++ b/mesh.c
@@ -383,6 +383,7 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb,
{
struct nlattr *container;
float rate;
+ int bintval, dtim_period;
char *end;

if (argc < 1)
@@ -405,6 +406,32 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb,
argc--;
}

+ if (argc > 1 && strcmp(argv[0], "beacon-interval") == 0) {
+ argc--;
+ argv++;
+
+ bintval = strtoul(argv[0], &end, 10);
+ if (*end != '\0')
+ return 1;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, bintval);
+ argv++;
+ argc--;
+ }
+
+ if (argc > 1 && strcmp(argv[0], "dtim-period") == 0) {
+ argc--;
+ argv++;
+
+ dtim_period = strtoul(argv[0], &end, 10);
+ if (*end != '\0')
+ return 1;
+
+ NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period);
+ argv++;
+ argc--;
+ }
+
container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP);
if (!container)
return -ENOBUFS;
@@ -431,8 +458,9 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb,
nla_put_failure:
return -ENOBUFS;
}
-COMMAND(mesh, join, "<mesh ID> [mcast-rate <rate in Mbps>] [vendor_sync on|off]"
- " [<param>=<value>]*",
+COMMAND(mesh, join, "<mesh ID> [mcast-rate <rate in Mbps>]"
+ " [beacon-interval <time in TUs>] [dtim-period <value>]"
+ " [vendor_sync on|off] [<param>=<value>]*",
NL80211_CMD_JOIN_MESH, 0, CIB_NETDEV, join_mesh,
"Join a mesh with the given mesh ID with mcast-rate and mesh parameters.");

--
1.7.9.5