linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Benjamin Berg <benjamin@sipsolutions.net>
To: Johannes Berg <johannes@sipsolutions.net>
Cc: linux-wireless@vger.kernel.org, sw@simonwunderlich.de,
	Benjamin Berg <benjamin.berg@open-mesh.com>
Subject: [PATCH 5/8] Add cac command to allow clearing channels
Date: Mon,  7 Nov 2016 15:59:40 +0100	[thread overview]
Message-ID: <20161107145943.16761-6-benjamin@sipsolutions.net> (raw)
In-Reply-To: <20161107145943.16761-1-benjamin@sipsolutions.net>

From: Benjamin Berg <benjamin.berg@open-mesh.com>

Allow the user to start a CAC for clearing DFS channels.

Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
---
 phy.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 145 insertions(+)

diff --git a/phy.c b/phy.c
index 266de4d..be31820 100644
--- a/phy.c
+++ b/phy.c
@@ -226,6 +226,151 @@ COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
 COMMAND(set, channel, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
 	NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
 
+
+struct cac_event {
+	int ret;
+	uint32_t freq;
+};
+
+static int print_cac_event(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *tb[NL80211_ATTR_MAX + 1];
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	enum nl80211_radar_event event_type;
+	struct cac_event *cac_event = arg;
+	uint32_t freq;
+
+	if (gnlh->cmd != NL80211_CMD_RADAR_DETECT)
+		return NL_SKIP;
+
+	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+		  genlmsg_attrlen(gnlh, 0), NULL);
+
+	if (!tb[NL80211_ATTR_RADAR_EVENT] || !tb[NL80211_ATTR_WIPHY_FREQ])
+		return NL_SKIP;
+
+	freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
+	event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
+	if (freq != cac_event->freq)
+		return NL_SKIP;
+
+	switch (event_type) {
+	case NL80211_RADAR_DETECTED:
+		printf("%d MHz: radar detected\n", freq);
+		break;
+	case NL80211_RADAR_CAC_FINISHED:
+		printf("%d MHz: CAC finished\n", freq);
+		break;
+	case NL80211_RADAR_CAC_ABORTED:
+		printf("%d MHz: CAC was aborted\n", freq);
+		break;
+	case NL80211_RADAR_NOP_FINISHED:
+		printf("%d MHz: NOP finished\n", freq);
+		break;
+	default:
+		printf("%d MHz: unknown radar event\n", freq);
+	}
+	cac_event->ret = 0;
+
+	return NL_SKIP;
+}
+
+static int handle_cac_trigger(struct nl80211_state *state,
+			    struct nl_msg *msg,
+			    int argc, char **argv,
+			    enum id_input id)
+{
+	struct chandef chandef;
+	int res;
+
+	if (argc < 2)
+		return 1;
+
+	if (strcmp(argv[0], "channel") == 0) {
+		res = parse_freqchan(&chandef, true, argc - 1, argv + 1, NULL);
+	} else if (strcmp(argv[0], "freq") == 0) {
+		res = parse_freqchan(&chandef, false, argc - 1, argv + 1, NULL);
+	} else {
+		return 1;
+	}
+
+	if (res)
+		return res;
+
+	return put_chandef(msg, &chandef);
+}
+
+static int no_seq_check(struct nl_msg *msg, void *arg)
+{
+	return NL_OK;
+}
+
+static int handle_cac(struct nl80211_state *state,
+		      struct nl_msg *msg,
+		      int argc, char **argv,
+		      enum id_input id)
+{
+	int err;
+	struct nl_cb *radar_cb;
+	struct chandef chandef;
+	struct cac_event cac_event;
+	char **cac_trigger_argv = NULL;
+
+	radar_cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
+	if (!radar_cb)
+		return 1;
+
+	if (argc < 3)
+		return 1;
+
+	if (strcmp(argv[2], "channel") == 0) {
+		err = parse_freqchan(&chandef, true, argc - 3, argv + 3, NULL);
+	} else if (strcmp(argv[2], "freq") == 0) {
+		err = parse_freqchan(&chandef, false, argc - 3, argv + 3, NULL);
+	} else {
+		return 1;
+	}
+
+	cac_trigger_argv = calloc(argc + 1, sizeof(char*));
+	if (!cac_trigger_argv)
+		return -ENOMEM;
+
+	cac_trigger_argv[0] = argv[0];
+	cac_trigger_argv[1] = "cac";
+	cac_trigger_argv[2] = "trigger";
+	memcpy(&cac_trigger_argv[3], &argv[2], (argc - 2) * sizeof(char*));
+
+	err = handle_cmd(state, id, argc + 1, cac_trigger_argv);
+	free(cac_trigger_argv);
+	if (err)
+		return err;
+
+	cac_event.ret = 1;
+	cac_event.freq = chandef.control_freq;
+
+	__prepare_listen_events(state);
+	nl_socket_set_cb(state->nl_sock, radar_cb);
+
+	/* need to turn off sequence number checking */
+	nl_cb_set(radar_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
+	nl_cb_set(radar_cb, NL_CB_VALID, NL_CB_CUSTOM, print_cac_event, &cac_event);
+	while (cac_event.ret > 0)
+		nl_recvmsgs(state->nl_sock, radar_cb);
+
+	return 0;
+}
+TOPLEVEL(cac, "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	      "freq <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	      "freq <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
+	 0, 0, CIB_NETDEV, handle_cac, NULL);
+COMMAND(cac, trigger,
+	"channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	"freq <frequency> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
+	"freq <frequency> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
+	NL80211_CMD_RADAR_DETECT, 0, CIB_NETDEV, handle_cac_trigger,
+	"Start or trigger a channel availability check (CAC) looking to look for\n"
+	"radars on the given channel.");
+
 static int handle_fragmentation(struct nl80211_state *state,
 				struct nl_msg *msg,
 				int argc, char **argv,
-- 
2.10.2

  parent reply	other threads:[~2016-11-07 14:59 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-07 14:59 [PATCH 0/8] iw: Add common chandef parser and new DFS related commands Benjamin Berg
2016-11-07 14:59 ` [PATCH 1/8] util: Add generic frequency/channel command line handler Benjamin Berg
2016-11-07 14:59 ` [PATCH 2/8] phy: Use common freqchan helper for setting the operating channel Benjamin Berg
2016-11-07 14:59 ` [PATCH 3/8] ibss: Use common freqchan helper for joining an ibss Benjamin Berg
2016-11-07 14:59 ` [PATCH 4/8] mesh: Use common freqchan helper for joining a mesh Benjamin Berg
2016-11-07 14:59 ` Benjamin Berg [this message]
2016-11-07 14:59 ` [PATCH 6/8] Add commands to send CSA Benjamin Berg
2016-11-07 14:59 ` [PATCH 7/8] Add flag for DFS handling in IBSS Benjamin Berg
2016-11-07 14:59 ` [PATCH 8/8] Print frequency of radar events Benjamin Berg
2016-11-17 17:21   ` Henrik Eriksson
2016-11-17 17:25     ` Benjamin Berg
2016-11-16 12:41 ` [PATCH 0/8] iw: Add common chandef parser and new DFS related commands Johannes Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161107145943.16761-6-benjamin@sipsolutions.net \
    --to=benjamin@sipsolutions.net \
    --cc=benjamin.berg@open-mesh.com \
    --cc=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    --cc=sw@simonwunderlich.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).