Add "set tid_config" command to support tid specific configurations. This command accepts multiple tid configurations like retry, ampdu, rtscts, noack and tx bitrate at a time. Format: iw dev <interface> set tid_config <configuration> Example: Noack configuration : iw <interface> set tid_config tid <tid_number> peer <MAC_addr> noack enable|disable Retry count : iw <interface> set tid_config tid <tid_number> peer <MAC_addr> retry_count long <retry_value> Aggregation : iw <interface> set tid_config tid <tid_number> peer <MAC_addr> ampdu enable|disable RTSCTS configuration : iw <interface> set tid_config tid <tid_number> peer <MAC_addr> rtscts enable|disable Bitrates configuration : iw <interface> set tid_config tid <tid_number> peer <MAC_addr> bitrates <[auto] [fixed] [limit]> [legacy-<2.4|5> <legacy rate in Mbps>*] [ht-mcs-<2.4|5> <MCS index>] [vht-mcs-<2.4|5> <NSS:MCSx]] Signed-off-by: Tamizh chelvam <tamizhr@xxxxxxxxxxxxxx> --- Makefile | 2 +- bitrate.c | 40 +++++++++-- iw.h | 3 + tid_config.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 267 insertions(+), 8 deletions(-) create mode 100644 tid_config.c diff --git a/Makefile b/Makefile index 33aaf6a..ecb5df8 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ OBJS = iw.o genl.o event.o info.o phy.o \ reason.o status.o connect.o link.o offch.o ps.o cqm.o \ bitrate.o wowlan.o coalesce.o roc.o p2p.o vendor.o mgmt.o \ ap.o sha256.o nan.o bloom.o \ - measurements.o ftm.o + measurements.o ftm.o tid_config.o OBJS += sections.o OBJS-$(HWSIM) += hwsim.o diff --git a/bitrate.c b/bitrate.c index 4a026a4..e287b13 100644 --- a/bitrate.c +++ b/bitrate.c @@ -76,10 +76,9 @@ static int setup_vht(struct nl80211_txrate_vht *txrate_vht, #define VHT_ARGC_MAX 100 -static int handle_bitrates(struct nl80211_state *state, - struct nl_msg *msg, - int argc, char **argv, - enum id_input id) +int set_bitrates(struct nl_msg *msg, + int argc, char **argv, + int arg_idx, enum nl80211_attrs attr) { struct nlattr *nl_rates, *nl_band; int i; @@ -110,7 +109,7 @@ static int handle_bitrates(struct nl80211_state *state, S_GI, } parser_state = S_NONE; - for (i = 0; i < argc; i++) { + for (i = arg_idx; i < argc; i++) { char *end; double tmpd; long tmpl; @@ -195,10 +194,14 @@ static int handle_bitrates(struct nl80211_state *state, case S_GI: break; default: + if (attr != NL80211_ATTR_TX_RATES) + goto next; + return 1; } } +next: if (have_vht_mcs_24) if(!setup_vht(&txrate_vht_24, vht_argc_24, vht_argv_24)) return -EINVAL; @@ -213,7 +216,7 @@ static int handle_bitrates(struct nl80211_state *state, if (sgi_24 && lgi_24) return 1; - nl_rates = nla_nest_start(msg, NL80211_ATTR_TX_RATES); + nl_rates = nla_nest_start(msg, attr); if (!nl_rates) goto nla_put_failure; @@ -253,11 +256,34 @@ static int handle_bitrates(struct nl80211_state *state, nla_nest_end(msg, nl_rates); - return 0; + return i; nla_put_failure: return -ENOBUFS; } +static int handle_bitrates(struct nl80211_state *state, + struct nl_msg *msg, + int argc, char **argv, + enum id_input id) +{ + int ret; + struct nl_msg *rate; + + rate = nlmsg_alloc(); + if (!rate) { + ret = -ENOMEM; + goto nla_put_failure; + } + + ret = set_bitrates(rate, argc, argv, 0, NL80211_ATTR_TX_RATES); + if (ret < argc) + return 1; + + return 0; +nla_put_failure: + return -ENOBUFS; +} + #define DESCR_LEGACY "[legacy-<2.4|5> <legacy rate in Mbps>*]" #define DESCR DESCR_LEGACY " [ht-mcs-<2.4|5> <MCS index>*] [vht-mcs-<2.4|5> <NSS:MCSx,MCSy... | NSS:MCSx-MCSy>*] [sgi-2.4|lgi-2.4] [sgi-5|lgi-5]" diff --git a/iw.h b/iw.h index 16ff076..274f02c 100644 --- a/iw.h +++ b/iw.h @@ -242,4 +242,7 @@ void nan_bf(uint8_t idx, uint8_t *bf, uint16_t bf_len, const uint8_t *buf, char *hex2bin(const char *hex, char *buf); +int set_bitrates(struct nl_msg *msg, int argc, char **argv, int arg_idx, + enum nl80211_attrs attr); + #endif /* __IW_H */ diff --git a/tid_config.c b/tid_config.c new file mode 100644 index 0000000..4b225c6 --- /dev/null +++ b/tid_config.c @@ -0,0 +1,230 @@ +#include <errno.h> +#include <string.h> +#include <stdbool.h> + +#include <netlink/genl/genl.h> +#include <netlink/genl/family.h> +#include <netlink/genl/ctrl.h> +#include <netlink/msg.h> +#include <netlink/attr.h> + +#include "nl80211.h" +#include "iw.h" + +static int handle_tid_config(struct nl80211_state *state, + struct nl_msg *msg, + int argc, char **argv, + enum id_input id) +{ + struct nl_msg *tid; + struct nlattr *nl_tid; + unsigned char mac_addr[ETH_ALEN]; + bool have_retry = false, have_ampdu = false; + bool have_noack = false, have_rtscts = false, have_bitrate = false; + int retry_short = -1, retry_long = -1; + bool nest_start = true; + uint8_t ampdu = 0, rtscts = 0, noack = 0; + enum nl80211_tx_rate_setting type = 0; + int tid_no = -1, i = 0; + char *end; + int ret = -ENOSPC; + + if (argc < 4) + return 1; + + tid = nlmsg_alloc(); + if (!tid) + return -ENOMEM; + + while (argc) { + if (strcmp(argv[0], "tid") == 0) { + if (argc < 2) + return 1; + + tid_no = strtoul(argv[1], &end, 16); + if (*end) + return 1; + + goto next; + } else if (strcmp(argv[0], "peer") == 0) { + if (argc < 2) + return 1; + + if (mac_addr_a2n(mac_addr, argv[1])) { + fprintf(stderr, "invalid mac address\n"); + return 2; + } + + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); + goto next; + } else if (strcmp(argv[0], "retry_count") == 0) { + have_retry = true; + argv++; + argc--; + if (argc) { + if (strcmp(argv[0], "short") == 0) { + if (argc < 2) + return 1; + + retry_short = strtoul(argv[1], &end, 0); + if (*end) + return 1; + argv += 2; + argc -= 2; + } + if (argc && strcmp(argv[0], "long") == 0) { + if (argc < 2) + return 1; + retry_long = strtoul(argv[1], &end, 0); + if (*end) + return 1; + } + } + } else if (strcmp(argv[0], "rtscts") == 0) { + have_rtscts = true; + if (argc < 2) { + argc--; + argv++; + rtscts = NL80211_TID_CONFIG_DEFAULT; + } else { + if (strcmp(argv[1], "enable") == 0) + rtscts = NL80211_TID_CONFIG_ENABLE; + else if (strcmp(argv[1], "disable") == 0) + rtscts = NL80211_TID_CONFIG_DISABLE; + else + rtscts = NL80211_TID_CONFIG_DEFAULT; + } + } else if (strcmp(argv[0], "ampdu") == 0) { + have_ampdu = true; + if (argc < 2) { + argc--; + argv++; + ampdu = NL80211_TID_CONFIG_DEFAULT; + } else { + if (strcmp(argv[1], "enable") == 0) + ampdu = NL80211_TID_CONFIG_ENABLE; + else if (strcmp(argv[1], "disable") == 0) + ampdu = NL80211_TID_CONFIG_DISABLE; + else + ampdu = NL80211_TID_CONFIG_DEFAULT; + } + } else if (strcmp(argv[0], "noack") == 0) { + have_noack = true; + if (argc < 2) { + argc--; + argv++; + noack = NL80211_TID_CONFIG_DEFAULT; + } else { + if (strcmp(argv[1], "enable") == 0) + noack = NL80211_TID_CONFIG_ENABLE; + else if (strcmp(argv[1], "disable") == 0) + noack = NL80211_TID_CONFIG_DISABLE; + else + noack = NL80211_TID_CONFIG_DEFAULT; + } + } else if (strcmp(argv[0], "bitrates") == 0) { + have_bitrate = true; + if (argc < 2) + return 1; + if (!strcmp(argv[1], "auto")) + type = NL80211_TX_RATE_AUTOMATIC; + else if (!strcmp(argv[1], "fixed")) + type = NL80211_TX_RATE_FIXED; + else if (!strcmp(argv[1], "limit")) + type = NL80211_TX_RATE_LIMITED; + else { + printf("Invalid parameter: %s\n", argv[i]); + return 2; + } + argc -= 2; + argv += 2; + } else { + return 1; + } + + if (tid_no == -1) + return 1; + if (have_retry || have_rtscts || have_bitrate || have_ampdu || + have_noack) { + nl_tid = nla_nest_start(tid, i); + if (!nl_tid) { + ret = -ENOBUFS; + goto nla_put_failure; + } + nest_start = true; + NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_TID, tid_no); + } else { + goto next; + } + + if (have_retry) { + NLA_PUT_FLAG(tid, NL80211_ATTR_TID_CONFIG_RETRY); + if (retry_short != -1) { + NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_RETRY_SHORT, + retry_short); + } + if (retry_long != -1) { + NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_RETRY_LONG, + retry_long); + } + + retry_short = retry_long = -1; + have_retry = false; + } + + if (have_rtscts) { + NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_RTSCTS_CTRL, + rtscts); + rtscts = 0; + have_rtscts = false; + } + + if (have_ampdu) { + NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_AMPDU_CTRL, + ampdu); + ampdu = 0; + have_ampdu = false; + } + + if (have_noack) { + NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_NOACK, noack); + noack = 0; + have_noack = false; + } + + if (have_bitrate) { + NLA_PUT_U8(tid, NL80211_ATTR_TID_CONFIG_TX_RATES_TYPE, type); + if (type != NL80211_TX_RATE_AUTOMATIC) { + ret = set_bitrates(tid, argc, argv, 0, + NL80211_ATTR_TID_CONFIG_TX_RATES); + if (ret < 2) + return 1; + + argc -= (ret - 2); + argv += (ret - 2); + } + have_bitrate = false; + type = 0; + } + + if (nest_start) { + nla_nest_end(tid, nl_tid); + nest_start = false; + } +next: + if (argc) { + argc -= 2; + argv += 2; + } + } + + nla_put_nested(msg, NL80211_ATTR_TID_CONFIG, tid); + + ret = 0; + +nla_put_failure: + return ret; +} +COMMAND(set, tid_config, "tid <tid> [peer <MAC address>] [<retry_count> short <limit> long <limit>] [rtscts enable|disable] [ampdu enable|disable] [noack enable|disable] bitrates <[auto] [fixed] [limited]> [peer <addr>] [legacy-<2.4|5> <legacy rate in Mbps>*] [ht-mcs-<2.4|5> <MCS index>] [vht-mcs-<2.4|5> <NSS:MCSx]", + NL80211_CMD_SET_TID_CONFIG, 0, CIB_NETDEV, handle_tid_config, + "Set the retry count for the TIDs "); -- 1.9.1