From patchwork Wed Jun 1 05:51:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 9146071 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 7B13F60757 for ; Wed, 1 Jun 2016 05:51:30 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6D6042040D for ; Wed, 1 Jun 2016 05:51:30 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 60C5E23749; Wed, 1 Jun 2016 05:51:30 +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.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID 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 3D9E92040D for ; Wed, 1 Jun 2016 05:51:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757183AbcFAFv1 (ORCPT ); Wed, 1 Jun 2016 01:51:27 -0400 Received: from mail-lf0-f67.google.com ([209.85.215.67]:33863 "EHLO mail-lf0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751197AbcFAFv0 (ORCPT ); Wed, 1 Jun 2016 01:51:26 -0400 Received: by mail-lf0-f67.google.com with SMTP id 65so805021lfq.1 for ; Tue, 31 May 2016 22:51:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=XIkjUnWAdLOcXrqDaO23Jn3Cfhpt4iD3UoBTYj42bak=; b=BviXNLg2PS3a0V/CS+j9uXPISaq0vJcJvqtH42Jn7kiVhsiBtjgj3YLwB4LSJqkvPt IspZhkV5H/gKhyF2Qc5tzALUucA7xQ0ZwpGTNHal/3f2b++l8UQEOBGw3RkPYGQuFYeC yCxkxy21PCTSGDa7vsJRBml6zQCuIoXS/ZlpBwAydYQepyl/zy/LGvpSigvUUkhUC3no zBMcvtpEwstMy5qLJ3wRTT+G0EyKrYqjs2tR0Y4fbL0za4dz6LxerL6N0dBlqzf96Vxy 4MARJBufpIupOSEOwxTKp0okDBb8E5q2rg7K0P9362HwZJ2WrEu9svvjoYzjA+h3k3be XMnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=XIkjUnWAdLOcXrqDaO23Jn3Cfhpt4iD3UoBTYj42bak=; b=eZG4HUzR4o9H2/oesttogtn9KApSyCaK9Yu2MBRZOd3O6Iv0Lalrzez9m25jO6Wz60 qv7rrjegG/hjqF7QqrkrbWwdnXnWCJrVN8mXp/kzWhvVJkWUtAoCkiwaZ0oDuIVd2BEe Ot/Ox7etweXcWL37nEFzskMpuffChSIdLq9LD6mZcnJPVer0DUwy0VhEW7iro0dooiKS t+TTf+lcC7JdZV1IThxwX8EnEd29iHLD2JfqJoGMhqevdkJrxgXWR3mU225lo6U1Igqv Da2Gyj80UmNPhqd48qMIcJcwfDcikrT1JLfvvnu1q/iW1Fw1MvpsyhVPZ3pPiQU8hPgH u7HQ== X-Gm-Message-State: ALyK8tK9Y4sEZ4RNuK4QyQMxKt3wRf09VQNd6qu+Stq7PDrcOZ3FIrdfpkYbkfpEtuTKYw== X-Received: by 10.25.15.167 with SMTP id 39mr690209lfp.126.1464760284161; Tue, 31 May 2016 22:51:24 -0700 (PDT) Received: from linux-samsung.lan (ip-194-187-74-233.konfederacka.maverick.com.pl. [194.187.74.233]) by smtp.gmail.com with ESMTPSA id y5sm5732587lba.17.2016.05.31.22.51.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 31 May 2016 22:51:23 -0700 (PDT) From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= To: Johannes Berg Cc: linux-wireless@vger.kernel.org, =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Subject: [PATCH V3 iw] add "channels" PHY command listing frequencies with more details Date: Wed, 1 Jun 2016 07:51:14 +0200 Message-Id: <1464760274-15530-1-git-send-email-zajec5@gmail.com> X-Mailer: git-send-email 1.8.4.5 In-Reply-To: <1464712100-4489-1-git-send-email-zajec5@gmail.com> References: <1464712100-4489-1-git-send-email-zajec5@gmail.com> MIME-Version: 1.0 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 Channels (frequencies) are getting more details that users may want to know about. E.g. it's important to know which frequencies allow using 40/80/160 MHz channels to setup AP properly. We list channels in "info" command output but it's already quite big and it was agreed to introduce new command rather than expand the old one. This patch adds "channels" command printing what was already available in the "info" plus details about supported channel widths. It also removes DFS info from the "info" output. Signed-off-by: Rafał Miłecki --- V2: Make width_40, width_80 & width_160 variables static. This is needed to keep their values across separated handler calls. V3: Introduce struct channels_ctx to avoid multiple static variables in a print_channels_handler. --- info.c | 30 ------------- phy.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 30 deletions(-) diff --git a/info.c b/info.c index 32de0af..b375123 100644 --- a/info.c +++ b/info.c @@ -47,20 +47,6 @@ static char *cipher_name(__u32 c) } } -static char *dfs_state_name(enum nl80211_dfs_state state) -{ - switch (state) { - case NL80211_DFS_USABLE: - return "usable"; - case NL80211_DFS_AVAILABLE: - return "available"; - case NL80211_DFS_UNAVAILABLE: - return "unavailable"; - default: - return "unknown"; - } -} - static int ext_feature_isset(const unsigned char *ext_features, int ext_features_len, enum nl80211_ext_feature_index ftidx) { @@ -198,22 +184,6 @@ next: if (open) printf(")"); printf("\n"); - - if (!tb_freq[NL80211_FREQUENCY_ATTR_DISABLED] && tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) { - enum nl80211_dfs_state state = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]); - unsigned long time; - - printf("\t\t\t DFS state: %s", dfs_state_name(state)); - if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_TIME]) { - time = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_TIME]); - printf(" (for %lu sec)", time/1000); - } - printf("\n"); - if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]) - printf("\t\t\t DFS CAC time: %u ms\n", - nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME])); - } - } } diff --git a/phy.c b/phy.c index 13e8260..c57a71f 100644 --- a/phy.c +++ b/phy.c @@ -14,6 +14,158 @@ #include "nl80211.h" #include "iw.h" +struct channels_ctx { + int last_band; + bool width_40; + bool width_80; + bool width_160; +}; + +static char *dfs_state_name(enum nl80211_dfs_state state) +{ + switch (state) { + case NL80211_DFS_USABLE: + return "usable"; + case NL80211_DFS_AVAILABLE: + return "available"; + case NL80211_DFS_UNAVAILABLE: + return "unavailable"; + default: + return "unknown"; + } +} + +static int print_channels_handler(struct nl_msg *msg, void *arg) +{ + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct channels_ctx *ctx = arg; + struct nlattr *tb_msg[NL80211_ATTR_MAX + 1]; + struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; + struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1]; + struct nlattr *nl_band; + struct nlattr *nl_freq; + int rem_band, rem_freq; + + nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); + + if (tb_msg[NL80211_ATTR_WIPHY_BANDS]) { + nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) { + if (ctx->last_band != nl_band->nla_type) { + printf("Band %d:\n", nl_band->nla_type + 1); + ctx->width_40 = false; + ctx->width_80 = false; + ctx->width_160 = false; + ctx->last_band = nl_band->nla_type; + } + + nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band), nla_len(nl_band), NULL); + + if (tb_band[NL80211_BAND_ATTR_HT_CAPA]) { + __u16 cap = nla_get_u16(tb_band[NL80211_BAND_ATTR_HT_CAPA]); + + if (cap & BIT(1)) + ctx->width_40 = true; + } + + if (tb_band[NL80211_BAND_ATTR_VHT_CAPA]) { + __u32 capa; + + ctx->width_80 = true; + + capa = nla_get_u32(tb_band[NL80211_BAND_ATTR_VHT_CAPA]); + switch ((capa >> 2) & 3) { + case 2: + /* width_80p80 = true; */ + /* fall through */ + case 1: + ctx->width_160 = true; + break; + } + } + + if (tb_band[NL80211_BAND_ATTR_FREQS]) { + nla_for_each_nested(nl_freq, tb_band[NL80211_BAND_ATTR_FREQS], rem_freq) { + uint32_t freq; + + nla_parse(tb_freq, NL80211_FREQUENCY_ATTR_MAX, nla_data(nl_freq), nla_len(nl_freq), NULL); + + if (!tb_freq[NL80211_FREQUENCY_ATTR_FREQ]) + continue; + freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]); + printf("\t* %d MHz [%d] ", freq, ieee80211_frequency_to_channel(freq)); + + if (tb_freq[NL80211_FREQUENCY_ATTR_DISABLED]) { + printf("(disabled)\n"); + continue; + } + printf("\n"); + + if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) + printf("\t Maximum TX power: %.1f dBm\n", 0.01 * nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER])); + + /* If both flags are set assume an new kernel */ + if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR] && tb_freq[__NL80211_FREQUENCY_ATTR_NO_IBSS]) { + printf("\t No IR\n"); + } else if (tb_freq[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN]) { + printf("\t Passive scan\n"); + } else if (tb_freq[__NL80211_FREQUENCY_ATTR_NO_IBSS]){ + printf("\t No IBSS\n"); + } + + if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR]) + printf("\t Radar detection\n"); + + printf("\t Channel widths:"); + if (!tb_freq[NL80211_FREQUENCY_ATTR_NO_20MHZ]) + printf(" 20MHz"); + if (ctx->width_40 && !tb_freq[NL80211_FREQUENCY_ATTR_NO_HT40_MINUS]) + printf(" HT40-"); + if (ctx->width_40 && !tb_freq[NL80211_FREQUENCY_ATTR_NO_HT40_PLUS]) + printf(" HT40+"); + if (ctx->width_80 && !tb_freq[NL80211_FREQUENCY_ATTR_NO_80MHZ]) + printf(" VHT80"); + if (ctx->width_160 && !tb_freq[NL80211_FREQUENCY_ATTR_NO_160MHZ]) + printf(" VHT160"); + printf("\n"); + + if (!tb_freq[NL80211_FREQUENCY_ATTR_DISABLED] && tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]) { + enum nl80211_dfs_state state = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_STATE]); + unsigned long time; + + printf("\t DFS state: %s", dfs_state_name(state)); + if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_TIME]) { + time = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_TIME]); + printf(" (for %lu sec)", time / 1000); + } + printf("\n"); + if (tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME]) + printf("\t DFS CAC time: %u ms\n", + nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME])); + } + } + } + } + } + + return NL_SKIP; +} + +static int handle_channels(struct nl80211_state *state, struct nl_msg *msg, + int argc, char **argv, enum id_input id) +{ + static struct channels_ctx ctx = { + .last_band = -1, + }; + + nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP); + nlmsg_hdr(msg)->nlmsg_flags |= NLM_F_DUMP; + + register_handler(print_channels_handler, &ctx); + + return 0; +} +TOPLEVEL(channels, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_PHY, handle_channels, "Show available channels."); + static int handle_name(struct nl80211_state *state, struct nl_msg *msg, int argc, char **argv,