X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=mesh.c;h=8d69fca92bf5411ee5f8336b1b982149c9a34f90;hb=f0e30bd5ef6ded7b85e7513cab3e02f29883a574;hp=f678dc0a1b548b2c0ec9c7a8fd1341eafc1e291c;hpb=be97e5138844c380bee6902575954915e91153c5;p=thirdparty%2Fiw.git diff --git a/mesh.c b/mesh.c index f678dc0..8d69fca 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) { @@ -140,11 +157,36 @@ static void _print_u32_timeout(struct nlattr *a) printf("%u milliseconds", nla_get_u32(a)); } +static void _print_u32_in_seconds(struct nlattr *a) +{ + printf("%d seconds", nla_get_u32(a)); +} + 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)); @@ -199,7 +241,7 @@ const static struct mesh_param_descr _mesh_param_descrs[] = {"mesh_hwmp_rootmode", NL80211_MESHCONF_HWMP_ROOTMODE, _my_nla_put_u8, _parse_u8, _print_u8}, {"mesh_hwmp_rann_interval", NL80211_MESHCONF_HWMP_RANN_INTERVAL, - _my_nla_put_u16, _parse_u16, _print_u16}, + _my_nla_put_u16, _parse_u16, _print_u16_in_TUs}, {"mesh_gate_announcements", NL80211_MESHCONF_GATE_ANNOUNCEMENTS, _my_nla_put_u8, _parse_u8, _print_u8}, {"mesh_fwding", NL80211_MESHCONF_FORWARDING, @@ -209,6 +251,20 @@ const static struct mesh_param_descr _mesh_param_descrs[] = _my_nla_put_u32, _parse_u32, _print_u32}, {"mesh_rssi_threshold", NL80211_MESHCONF_RSSI_THRESHOLD, _my_nla_put_u32, _parse_s32, _print_s32_in_dBm}, + {"mesh_hwmp_active_path_to_root_timeout", + NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, + _my_nla_put_u32, _parse_u32, _print_u32_in_TUs}, + {"mesh_hwmp_root_interval", NL80211_MESHCONF_HWMP_ROOT_INTERVAL, + _my_nla_put_u16, _parse_u16, _print_u16_in_TUs}, + {"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}, + {"mesh_plink_timeout", NL80211_MESHCONF_PLINK_TIMEOUT, + _my_nla_put_u32, _parse_u32, _print_u32_in_seconds}, }; static void print_all_mesh_param_descr(void) @@ -224,26 +280,23 @@ static void print_all_mesh_param_descr(void) static const struct mesh_param_descr *find_mesh_param(const char *name) { int i; - const struct mesh_param_descr *mdescr = NULL; /* Find out what mesh parameter we want to change. */ for (i = 0; i < ARRAY_SIZE(_mesh_param_descrs); i++) { - if (!strcmp(_mesh_param_descrs[i].name, name)) + if (strcmp(_mesh_param_descrs[i].name, name) == 0) return _mesh_param_descrs + i; } - if (!mdescr) { - print_all_mesh_param_descr(); - return NULL; - } - return mdescr; + print_all_mesh_param_descr(); + return NULL; } /* Setter */ static int set_interface_meshparam(struct nl80211_state *state, struct nl_cb *cb, struct nl_msg *msg, - int argc, char **argv) + int argc, char **argv, + enum id_input id) { const struct mesh_param_descr *mdescr; struct nlattr *container; @@ -289,8 +342,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; } @@ -349,7 +409,8 @@ static int print_mesh_param_handler(struct nl_msg *msg, void *arg) static int get_interface_meshparam(struct nl80211_state *state, struct nl_cb *cb, struct nl_msg *msg, - int argc, char **argv) + int argc, char **argv, + enum id_input id) { const struct mesh_param_descr *mdescr = NULL; @@ -372,11 +433,38 @@ COMMAND(get, mesh_param, "[]", "Retrieve mesh parameter (run command without any to see available ones)."); static int join_mesh(struct nl80211_state *state, struct nl_cb *cb, - struct nl_msg *msg, int argc, char **argv) + struct nl_msg *msg, int argc, char **argv, + enum id_input id) { struct nlattr *container; float rate; - char *end; + unsigned char rates[NL80211_MAX_SUPP_RATES]; + int bintval, dtim_period, i, n_rates = 0; + char *end, *value = NULL, *sptr = NULL; + unsigned long freq = 0; + static const struct { + const char *name; + unsigned int width; + int freq1_diff; + int chantype; /* for older kernel */ + } *chanmode_selected = NULL, chanmode[] = { + { .name = "HT20", + .width = NL80211_CHAN_WIDTH_20, + .freq1_diff = 0, + .chantype = NL80211_CHAN_HT20 }, + { .name = "HT40+", + .width = NL80211_CHAN_WIDTH_40, + .freq1_diff = 10, + .chantype = NL80211_CHAN_HT40PLUS }, + { .name = "HT40-", + .width = NL80211_CHAN_WIDTH_40, + .freq1_diff = -10, + .chantype = NL80211_CHAN_HT40MINUS }, + { .name = "NOHT", + .width = NL80211_CHAN_WIDTH_20_NOHT, + .freq1_diff = 0, + .chantype = NL80211_CHAN_NO_HT }, + }; if (argc < 1) return 1; @@ -385,6 +473,70 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb, argc--; argv++; + /* freq */ + if (argc > 1 && strcmp(argv[0], "freq") == 0) { + argv++; + argc--; + + freq = strtoul(argv[0], &end, 10); + if (*end != '\0') + return 1; + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); + + argv++; + argc--; + } + + /* channel type */ + if (argc) { + for (i = 0; i < ARRAY_SIZE(chanmode); i++) { + if (strcasecmp(chanmode[i].name, argv[0]) == 0) { + chanmode_selected = &chanmode[i]; + break; + } + } + + if (chanmode_selected) { + NLA_PUT_U32(msg, NL80211_ATTR_CHANNEL_WIDTH, + chanmode_selected->width); + NLA_PUT_U32(msg, NL80211_ATTR_CENTER_FREQ1, + freq + chanmode_selected->freq1_diff); + if (chanmode_selected->chantype != -1) + NLA_PUT_U32(msg, + NL80211_ATTR_WIPHY_CHANNEL_TYPE, + chanmode_selected->chantype); + + argv++; + argc--; + } + } + + /* basic rates */ + if (argc > 1 && strcmp(argv[0], "basic-rates") == 0) { + argv++; + argc--; + + value = strtok_r(argv[0], ",", &sptr); + + while (value && n_rates < NL80211_MAX_SUPP_RATES) { + rate = strtod(value, &end); + rates[n_rates] = rate * 2; + + /* filter out suspicious values */ + if (*end != '\0' || !rates[n_rates] || + rate*2 != rates[n_rates]) + return 1; + + n_rates++; + value = strtok_r(NULL, ",", &sptr); + } + + NLA_PUT(msg, NL80211_ATTR_BSS_BASIC_RATES, n_rates, rates); + argv++; + argc--; + } + + /* multicast rate */ if (argc > 1 && strcmp(argv[0], "mcast-rate") == 0) { argv++; argc--; @@ -398,6 +550,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; @@ -420,17 +598,22 @@ static int join_mesh(struct nl80211_state *state, struct nl_cb *cb, if (!argc) return 0; - return set_interface_meshparam(state, cb, msg, argc, argv); + return set_interface_meshparam(state, cb, msg, argc, argv, id); nla_put_failure: return -ENOBUFS; } -COMMAND(mesh, join, " [mcast-rate ] [vendor_sync on|off]" - " [=]*", +COMMAND(mesh, join, " [[freq ]" + " [basic-rates ]], [mcast-rate ]" + " [beacon-interval