diff mbox

[6/8] Add commands to send CSA

Message ID 20161107145943.16761-7-benjamin@sipsolutions.net (mailing list archive)
State Accepted
Delegated to: Johannes Berg
Headers show

Commit Message

Benjamin Berg Nov. 7, 2016, 2:59 p.m. UTC
From: Benjamin Berg <benjamin.berg@open-mesh.com>

Add a new set of commands to send a CSA. Both the number of beacons and the
flag to block TX can be given optionally.

Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
---
 interface.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 iw.h        |  1 +
 2 files changed, 73 insertions(+)
diff mbox

Patch

diff --git a/interface.c b/interface.c
index 57dd3c3..1c9ebfb 100644
--- a/interface.c
+++ b/interface.c
@@ -644,3 +644,75 @@  nla_put_failure:
 COMMAND(set, mcast_rate, "<rate in Mbps>",
 	NL80211_CMD_SET_MCAST_RATE, 0, CIB_NETDEV, set_mcast_rate,
 	"Set the multicast bitrate.");
+
+
+static int handle_chanfreq(struct nl80211_state *state, struct nl_msg *msg,
+			   bool chan, int argc, char **argv,
+			   enum id_input id)
+{
+	struct chandef chandef;
+	int res;
+	int parsed;
+	char *end;
+
+	res = parse_freqchan(&chandef, chan, argc, argv, &parsed);
+	if (res)
+		return res;
+
+	argc -= parsed;
+	argv += parsed;
+
+	while (argc) {
+		unsigned int beacons = 10;
+
+		if (strcmp(argv[0], "beacons") == 0) {
+			if (argc < 2)
+				return 1;
+
+			beacons = strtol(argv[1], &end, 10);
+			if (*end)
+				return 1;
+
+			argc -= 2;
+			argv += 2;
+
+			NLA_PUT_U32(msg, NL80211_ATTR_CH_SWITCH_COUNT, beacons);
+		} else if (strcmp(argv[0], "block-tx") == 0) {
+			argc -= 1;
+			argv += 1;
+
+			NLA_PUT_FLAG(msg, NL80211_ATTR_CH_SWITCH_BLOCK_TX);
+		} else {
+			return 1;
+		}
+	}
+
+	return put_chandef(msg, &chandef);
+
+ nla_put_failure:
+	return -ENOBUFS;
+}
+
+static int handle_freq(struct nl80211_state *state, struct nl_msg *msg,
+		       int argc, char **argv,
+		       enum id_input id)
+{
+	return handle_chanfreq(state, msg, false, argc, argv, id);
+}
+
+static int handle_chan(struct nl80211_state *state, struct nl_msg *msg,
+		       int argc, char **argv,
+		       enum id_input id)
+{
+	return handle_chanfreq(state, msg, true, argc, argv, id);
+}
+
+SECTION(switch);
+COMMAND(switch, freq,
+	"<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [beacons <count>] [block-tx]\n"
+	"<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]] [beacons <count>] [block-tx]",
+	NL80211_CMD_CHANNEL_SWITCH, 0, CIB_NETDEV, handle_freq,
+	"Switch the operating channel by sending a channel switch announcement (CSA).");
+COMMAND(switch, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [beacons <count>] [block-tx]",
+	NL80211_CMD_CHANNEL_SWITCH, 0, CIB_NETDEV, handle_chan, NULL);
+
diff --git a/iw.h b/iw.h
index 7d56391..0857baf 100644
--- a/iw.h
+++ b/iw.h
@@ -202,6 +202,7 @@  int get_cf1(const struct chanmode *chanmode, unsigned long freq);
 	"[randomise[=<addr>/<mask>]]"
 int parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv);
 
+DECLARE_SECTION(switch);
 DECLARE_SECTION(set);
 DECLARE_SECTION(get);