From patchwork Mon Nov 7 14:59:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Berg X-Patchwork-Id: 9415363 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 32A5E60585 for ; Mon, 7 Nov 2016 15:00:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 25E5028C4A for ; Mon, 7 Nov 2016 15:00:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1AA6428C4E; Mon, 7 Nov 2016 15:00:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A69AF28C4A for ; Mon, 7 Nov 2016 15:00:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932342AbcKGPAG (ORCPT ); Mon, 7 Nov 2016 10:00:06 -0500 Received: from s3.sipsolutions.net ([5.9.151.49]:36810 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932280AbcKGO74 (ORCPT ); Mon, 7 Nov 2016 09:59:56 -0500 Received: by sipsolutions.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.87) (envelope-from ) id 1c3lOs-00031L-OK; Mon, 07 Nov 2016 15:59:54 +0100 From: Benjamin Berg To: Johannes Berg Cc: linux-wireless@vger.kernel.org, sw@simonwunderlich.de, Benjamin Berg Subject: [PATCH 5/8] Add cac command to allow clearing channels Date: Mon, 7 Nov 2016 15:59:40 +0100 Message-Id: <20161107145943.16761-6-benjamin@sipsolutions.net> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161107145943.16761-1-benjamin@sipsolutions.net> References: <20161107145943.16761-1-benjamin@sipsolutions.net> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Benjamin Berg Allow the user to start a CAC for clearing DFS channels. Signed-off-by: Simon Wunderlich Signed-off-by: Benjamin Berg --- 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, " [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]", COMMAND(set, 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 [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" + "freq [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" + "freq [5|10|20|40|80|80+80|160] [ []]", + 0, 0, CIB_NETDEV, handle_cac, NULL); +COMMAND(cac, trigger, + "channel [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" + "freq [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n" + "freq [5|10|20|40|80|80+80|160] [ []]", + 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,