]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
iw: Add support for connection quality monitor configuation
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>
Fri, 26 Mar 2010 05:46:19 +0000 (07:46 +0200)
committerJohannes Berg <johannes@sipsolutions.net>
Wed, 31 Mar 2010 05:28:47 +0000 (07:28 +0200)
This patch adds the cqm option to iw allowing enabling/disabling the
rssi connection quality monitoring mode, and configuring rssi threshold and
hysteresis.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Makefile
cqm.c [new file with mode: 0644]
event.c

index c51706b983439f257a3a696709ba26859c0190da..e21900ac95f57085df2bf23926354592a50a20e6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing
 OBJS = iw.o genl.o event.o info.o phy.o \
        interface.o ibss.o station.o survey.o util.o \
        mesh.o mpath.o scan.o reg.o version.o \
-       reason.o status.o connect.o link.o offch.o ps.o
+       reason.o status.o connect.o link.o offch.o ps.o cqm.c
 OBJS += sections.o
 ALL = iw
 
diff --git a/cqm.c b/cqm.c
new file mode 100644 (file)
index 0000000..3da2b54
--- /dev/null
+++ b/cqm.c
@@ -0,0 +1,54 @@
+#include <errno.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 iw_cqm_rssi(struct nl80211_state *state, struct nl_cb *cb,
+                      struct nl_msg *msg, int argc, char **argv)
+{
+       struct nl_msg *cqm = NULL;
+       int thold = 0;
+       int hyst = 0;
+       int ret = -ENOSPC;
+
+       /* get the required args */
+       if (argc < 1 || argc > 2)
+               return 1;
+
+       if (strcmp(argv[0], "off")) {
+               thold = atoi(argv[0]);
+
+               if (thold == 0)
+                       return -EINVAL;
+
+               if (argc == 2)
+                       hyst = atoi(argv[1]);
+       }
+
+       /* connection quality monitor attributes */
+       cqm = nlmsg_alloc();
+
+       NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_THOLD, thold);
+       NLA_PUT_U32(cqm, NL80211_ATTR_CQM_RSSI_HYST, hyst);
+
+       nla_put_nested(msg, NL80211_ATTR_CQM, cqm);
+       ret = 0;
+
+ nla_put_failure:
+       nlmsg_free(cqm);
+       return ret;
+}
+
+TOPLEVEL(cqm, "",
+        0, 0, CIB_NETDEV, NULL,
+        "Configure the WLAN connection quality monitor.\n");
+
+COMMAND(cqm, rssi, "<threshold|off> [<hysteresis>]",
+       NL80211_CMD_SET_CQM, 0, CIB_NETDEV, iw_cqm_rssi,
+       "Set connection quality monitor RSSI threshold.\n");
diff --git a/event.c b/event.c
index 01a325cfb8f46d1d24b6ff6099b5f2100cb60e44..8133cb87babe8cabc2fbba1fe0908b9994ec4d75 100644 (file)
--- a/event.c
+++ b/event.c
@@ -100,6 +100,34 @@ static void print_frame(struct print_event_args *args, struct nlattr *attr)
        printf("]");
 }
 
+static void parse_cqm_event(struct nlattr *tb)
+{
+       static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
+               [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
+               [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
+               [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
+       };
+       struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
+
+       printf("connection quality monitor event: ");
+
+       if (!tb || nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, tb, cqm_policy)) {
+               printf("missing data!\n");
+               return;
+       }
+
+       if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]) {
+               enum nl80211_cqm_rssi_threshold_event rssi_event;
+               rssi_event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
+               if (rssi_event == NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)
+                       printf("RSSI went above threshold");
+               else
+                       printf("RSSI went below threshold");
+       }
+       printf("\n");
+}
+
+
 static int print_event(struct nl_msg *msg, void *arg)
 {
 #define PARSE_BEACON_CHAN(_attr, _chan) do { \
@@ -313,6 +341,9 @@ static int print_event(struct nl_msg *msg, void *arg)
                        nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]),
                        (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]));
                break;
+       case NL80211_CMD_NOTIFY_CQM:
+               parse_cqm_event(tb[NL80211_ATTR_CQM]);
+               break;
        default:
                printf("unknown event %d\n", gnlh->cmd);
                break;