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 <[email protected]>
---
 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

Reply via email to