From patchwork Mon Oct 8 12:28:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Shvedov X-Patchwork-Id: 980552 X-Patchwork-Delegate: blogic@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wimarksystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="XmEPplz1"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="QSJkvq0Z"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42TKvQ3w28z9sBk for ; Mon, 8 Oct 2018 23:49:54 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:Message-Id:Date:To :From:Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=RlPF9Ghr594Lrk8MY+1ksVvm97Wuf/mqTlp9EtOaEus=; b=XmEPplz1BRcWzd ORM7HBbH00wQyrJ28LpdMxpm9QCcWiq+o9Puw9h41vrzsdWwVrLZnpTdmxlhC8Omxo70Oz9pYeR8x CQHJ/lYdpduii6VLYu80JsLSStspLgnthiA6Skt1ItCCENFj+Pj59ir2VWjZ5ZVNYaYE5gjzIyuEi WIyGF9XxqVgvGzP+fg7JdjJ0UeskWOISvp6rd64VLX/mGt/bbfjSrTlPW3BGhY26KGvECg/5nuaJn 8tueod1eUwnXKNcIm+2c/jiC0iCGcX3KXgViwiExuKpXgJU3lfh4d9dW9Qel/su6PYfqIKKD8fQlG 1YB4b3oMwyRtrmpbGiQA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9Uyr-0002EX-B5; Mon, 08 Oct 2018 12:49:49 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9Uw2-0000uW-Ek for openwrt-devel@bombadil.infradead.org; Mon, 08 Oct 2018 12:46:54 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Content-Transfer-Encoding:MIME-Version: Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=rQZR8c7misQ95KbSmbfaT3nWODTS15byTzDNehETAtQ=; b=QSJkvq0ZB2rpAelOZUybrljMFV jhiHtGRvDJxNfvzDyEhjcgpbLBLDLc1QavpqDWNO/iQCySqMeO2FqZqKcj97l6KPxgNHIdu5YQW8R EzfzWB0ykKeFiUQRcBjfiKQ06NGSCjmX8wc4/2DJuHrzA/s/roYkevVzzGUFDFQe63alBj9zbQSFB mYxQAB0KRRs/xLIcQzNAKnXBk0NuGjdA3fjRjK+bQMW/8k0ewCv0/zEDottHNh6nESOFkXj6/RblJ JNtlxSq7zJg85PYJ7lXBWiJGqypkgzq8NaSUjmBjwWm/8NqBeeAPJ1YrnYKD41FLkjgcNlmwM49ul TTrja06w==; Received: from forward104o.mail.yandex.net ([2a02:6b8:0:1a2d::607]) by merlin.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9UeO-0004jN-Vz for openwrt-devel@lists.openwrt.org; Mon, 08 Oct 2018 12:28:42 +0000 Received: from mxback7g.mail.yandex.net (mxback7g.mail.yandex.net [IPv6:2a02:6b8:0:1472:2741:0:8b7:168]) by forward104o.mail.yandex.net (Yandex) with ESMTP id E8DE23D854BD for ; Mon, 8 Oct 2018 15:28:22 +0300 (MSK) Received: from smtp1p.mail.yandex.net (smtp1p.mail.yandex.net [2a02:6b8:0:1472:2741:0:8b6:6]) by mxback7g.mail.yandex.net (nwsmtp/Yandex) with ESMTP id hWmUluLlkb-SM5W7JMO; Mon, 08 Oct 2018 15:28:22 +0300 Received: by smtp1p.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id vvLubVtQwM-SMVikRxv; Mon, 08 Oct 2018 15:28:22 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client certificate not present) From: Yury Shvedov To: openwrt-devel@lists.openwrt.org Date: Mon, 8 Oct 2018 15:28:17 +0300 Message-Id: <20181008122821.29237-1-yshvedov@wimarksystems.com> X-Mailer: git-send-email 2.19.0 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181008_082841_313204_63A5EDCF X-CRM114-Status: GOOD ( 17.53 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.2 on merlin.infradead.org summary: Content analysis details: (-0.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2a02:6b8:0:1a2d:0:0:0:607 listed in] [list.dnswl.org] Subject: [OpenWrt-Devel] [PATCH 1/5] hostapd: add ubus hostapd_iface object X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org Ubus hostapd_iface object has get_state and get_bss methods, this patch additionally sends events with interfaces' states. This allows outer system to watch interfaces prior they enabled and handle the errors. This actually reverts the f0ac9afe695ed297caf093f02144b2adf04bca87 patch and adds functionality using hostapd_ubus_iface struct. Signed-off-by: Yury Shvedov --- .../hostapd/patches/600-ubus_support.patch | 54 +++++++- .../services/hostapd/src/src/ap/ubus.c | 127 ++++++++++++++++++ .../services/hostapd/src/src/ap/ubus.h | 13 ++ 3 files changed, 193 insertions(+), 1 deletion(-) diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch index cb2c54d57c..c63b85c079 100644 --- a/package/network/services/hostapd/patches/600-ubus_support.patch +++ b/package/network/services/hostapd/patches/600-ubus_support.patch @@ -30,7 +30,16 @@ int interface_added; /* virtual interface added for this BSS */ unsigned int started:1; unsigned int disabled:1; -@@ -544,6 +546,7 @@ hostapd_alloc_bss_data(struct hostapd_if +@@ -392,6 +394,8 @@ struct hostapd_iface { + struct hostapd_config *conf; + char phy[16]; /* Name of the PHY (radio) */ + ++ struct hostapd_ubus_iface ubus; ++ + enum hostapd_iface_state { + HAPD_IFACE_UNINITIALIZED, + HAPD_IFACE_DISABLED, +@@ -544,6 +548,7 @@ hostapd_alloc_bss_data(struct hostapd_if struct hostapd_bss_config *bss); int hostapd_setup_interface(struct hostapd_iface *iface); int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err); @@ -90,6 +99,14 @@ hostapd_interface_deinit(iface); wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit", __func__, driver, drv_priv); +@@ -3114,6 +3120,7 @@ void hostapd_set_state(struct hostapd_if + wpa_printf(MSG_INFO, "%s: interface state %s->%s", + iface->conf ? iface->conf->bss[0]->iface : "N/A", + hostapd_state_text(iface->state), hostapd_state_text(s)); ++ hostapd_ubus_event_iface_state(iface, s); + iface->state = s; + } + --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -1712,12 +1712,13 @@ ieee802_11_set_radius_info(struct hostap @@ -341,3 +358,38 @@ } +--- a/hostapd/config_file.c ++++ b/hostapd/config_file.c +@@ -2663,6 +2663,11 @@ static int hostapd_config_fill(struct ho + 0) { + bss->radius_das_require_message_authenticator = atoi(pos); + #endif /* CONFIG_NO_RADIUS */ ++#ifdef UBUS_SUPPORT ++ } else if (os_strcmp(buf, "uci_device") == 0) { ++ os_free(bss->uci_device); ++ bss->uci_device = os_strdup(pos); ++#endif /* UBUS_SUPPORT */ + } else if (os_strcmp(buf, "auth_algs") == 0) { + bss->auth_algs = atoi(pos); + if (bss->auth_algs == 0) { +--- a/src/ap/ap_config.c ++++ b/src/ap/ap_config.c +@@ -587,6 +587,7 @@ void hostapd_config_free_bss(struct host + os_free(conf->model_description); + os_free(conf->model_url); + os_free(conf->upc); ++ os_free(conf->uci_device); + { + unsigned int i; + +--- a/src/ap/ap_config.h ++++ b/src/ap/ap_config.h +@@ -470,6 +470,8 @@ struct hostapd_bss_config { + int pbc_in_m1; + char *server_id; + ++ char *uci_device; ++ + #define P2P_ENABLED BIT(0) + #define P2P_GROUP_OWNER BIT(1) + #define P2P_GROUP_FORMATION BIT(2) diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index 3375ac49f7..a393451af2 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -92,16 +92,109 @@ static void hostapd_ubus_ref_dec(void) ctx = NULL; } +static int +hostapd_iface_get_state(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct hostapd_iface *iface = container_of(obj, struct hostapd_iface, + ubus.obj); + + blob_buf_init(&b, 0); + blobmsg_add_u32(&b, "state_num", iface->state); + blobmsg_add_string(&b, "state", hostapd_state_text(iface->state)); + blobmsg_add_u32(&b, "freq", iface->freq); + if (iface->bss[0] && iface->bss[0]->conf->uci_device) + blobmsg_add_string(&b, "device", iface->bss[0]->conf->uci_device); + ubus_send_reply(ctx, req, b.head); + + return 0; +} +static int +hostapd_iface_get_bss(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct hostapd_iface *iface = container_of(obj, struct hostapd_iface, + ubus.obj); + struct hostapd_data *bss; + void *a,*h; + int i; + const char *state = hostapd_state_text(iface->state); + + blob_buf_init(&b, 0); + blobmsg_add_u32(&b, "state_num", iface->state); + blobmsg_add_string(&b, "state", state); + blobmsg_add_u32(&b, "freq", iface->freq); + if (iface->bss[0] && iface->bss[0]->conf->uci_device) + blobmsg_add_string(&b, "device", iface->bss[0]->conf->uci_device); + a = blobmsg_open_array(&b, "bss"); + for (i=0; inum_bss; ++i) { + bss = iface->bss[i]; + h = blobmsg_open_table(&b, NULL); + blobmsg_add_string(&b, "iface", bss->conf->iface); + blobmsg_add_string(&b, "state", state); + if (bss->conf->uci_device) + blobmsg_add_string(&b, "device", bss->conf->uci_device); + if (bss->ubus.obj.id) + blobmsg_add_string(&b, "uobject", bss->ubus.obj.name); + blobmsg_close_table(&b, h); + } + blobmsg_close_array(&b, a); + ubus_send_reply(ctx, req, b.head); + + return 0; +} +static const struct ubus_method iface_methods[] = { + UBUS_METHOD_NOARG("get_state", hostapd_iface_get_state), + UBUS_METHOD_NOARG("get_bss", hostapd_iface_get_bss), +}; +static struct ubus_object_type iface_object_type = + UBUS_OBJECT_TYPE("hostapd_iface", iface_methods); + void hostapd_ubus_add_iface(struct hostapd_iface *iface) { + struct ubus_object *obj = &iface->ubus.obj; + char *name, *ifname = NULL; + int ret; + if (!hostapd_ubus_init()) return; + + if (obj->id) + return; + + if (iface->bss[0] && iface->bss[0]->conf->uci_device) + ifname = iface->bss[0]->conf->uci_device; + else + ifname = iface->phy; + + if (asprintf(&name, "hostapd_iface.%s", ifname) < 0) + return; + + obj->name = name; + obj->type = &iface_object_type; + obj->methods = iface_object_type.methods; + obj->n_methods = iface_object_type.n_methods; + ret = ubus_add_object(ctx, obj); + hostapd_ubus_ref_inc(); } void hostapd_ubus_free_iface(struct hostapd_iface *iface) { + struct ubus_object *obj = &iface->ubus.obj; + char *name = (char *) obj->name; + if (!ctx) return; + + if (obj->id) { + ubus_remove_object(ctx, obj); + hostapd_ubus_ref_dec(); + } + + free(name); + obj->name = NULL; } static void @@ -1019,6 +1112,7 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd) } free(name); + obj->name = NULL; } struct ubus_event_req { @@ -1033,6 +1127,13 @@ ubus_event_cb(struct ubus_notify_request *req, int idx, int ret) ureq->resp = ret; } +static void blobmsg_add_hapd_id(struct blob_buf *buf, struct hostapd_data *hapd) +{ + if (hapd->conf->uci_device) + blobmsg_add_string(buf, "device", hapd->conf->uci_device); + blobmsg_add_macaddr(buf, "bssid", hapd->own_addr); + blobmsg_add_string(buf, "iface", hapd->conf->iface); +} int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req) { @@ -1110,6 +1211,8 @@ int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_req } } + blobmsg_add_hapd_id(&b, hapd); + if (!hapd->ubus.notify_response) { ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1); return WLAN_STATUS_SUCCESS; @@ -1138,5 +1241,29 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 * blob_buf_init(&b, 0); blobmsg_add_macaddr(&b, "address", addr); + blobmsg_add_hapd_id(&b, hapd); ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1); } + +/* Send ubus event in case new event differs. */ +void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s) +{ + struct hostapd_data *hapd = iface->bss[0]; + + if (!hostapd_ubus_init()) + return; + hostapd_ubus_add_iface(iface); + if (iface->state == s) { + return; + } + blob_buf_init(&b, 0); + if (hapd && hapd->conf->uci_device) + blobmsg_add_string(&b, "device", hapd->conf->uci_device); + if (iface->ubus.obj.id) + blobmsg_add_string(&b, "uobject", iface->ubus.obj.name); + blobmsg_add_u32(&b, "oldstate_num", iface->state); + blobmsg_add_string(&b, "oldstate", hostapd_state_text(iface->state)); + blobmsg_add_u32(&b, "state_num", s); + blobmsg_add_string(&b, "state", hostapd_state_text(s)); + ubus_send_event(ctx, "hostapd.iface_state", b.head); +} diff --git a/package/network/services/hostapd/src/src/ap/ubus.h b/package/network/services/hostapd/src/src/ap/ubus.h index 185af5a7f4..840b000180 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.h +++ b/package/network/services/hostapd/src/src/ap/ubus.h @@ -8,6 +8,8 @@ #ifndef __HOSTAPD_UBUS_H #define __HOSTAPD_UBUS_H +#include "hostapd.h" + enum hostapd_ubus_event_type { HOSTAPD_UBUS_PROBE_REQ, HOSTAPD_UBUS_AUTH_REQ, @@ -31,6 +33,10 @@ struct hostapd_data; #include #include +struct hostapd_ubus_iface { + struct ubus_object obj; +}; + struct hostapd_ubus_bss { struct ubus_object obj; struct avl_tree banned; @@ -45,8 +51,12 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd); int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req); void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac); +void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s); + #else +struct hostapd_ubus_iface {}; + struct hostapd_ubus_bss {}; static inline void hostapd_ubus_add_iface(struct hostapd_iface *iface) @@ -73,6 +83,9 @@ static inline int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct ho static inline void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac) { } +static inline void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s) +{ +} #endif #endif From patchwork Mon Oct 8 12:28:18 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Shvedov X-Patchwork-Id: 980546 X-Patchwork-Delegate: blogic@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wimarksystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="lUbSmkkw"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="Wua9iXwD"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42TKpW69jGz9s8r for ; Mon, 8 Oct 2018 23:45:39 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:References: In-Reply-To:Message-Id:Date:To:From:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=/zBO4h0E9ca4UZH8i4aNkHLyRvGo1AfHEvse6+V99FY=; b=lUbSmkkwtamC+Jh9r01BDmdQk3 5ZLdDOpYJuzVU7P5NDlhNIw1Z62VqOr0ypVlSaPkZNu1Ap91kDESF7Xn67cc8FoVY+iholol5FghC SLA/2t8HYJMUU37KNJ+7mOSHXVNleW4StZ1mTLI4xUGjaDnX7ghvYA21ZwpXZMMtOOqZxfLD6dXTW 0+le/C1yqwGKx5xJgOaigWrpbinAJgLC7qQv4qmjYM0ipN3KXAWdCjksxzlQpTTuepwVoFVvQgS4w WwSKZGYBn0rTdoci4ch9y6eO0PSG/cMN/FLXpSWsqlLT7BO0chEW8/FRUIomjfDiZ32lzOocTWR97 C5BlbhIA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9Uul-0000Jr-6b; Mon, 08 Oct 2018 12:45:35 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9Uu8-0007B5-N1 for openwrt-devel@bombadil.infradead.org; Mon, 08 Oct 2018 12:44:56 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc: Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=eDQ3/sVMhFiI8mJ6mPPwHnznpWbQ2lzVVLEyKgHUd0M=; b=Wua9iXwDE5ZGYfun3wwijrFnHd GkG4ppbTIysfLtvVVBHPCXsIBUgexqXvs8aZPvKsY7/JjGO8w5nrSah7JUEC7tbsAoqCO5XDX6mvL veLBxDMD0waCs6n9JiK+dx31VE3P2X5ezEPLCbdW8FJQmGhAVZuZXSUUhEhWWnEMO87yWX223ZRw4 ps3+11x2vb6R3YgtgREN/j/3ixILwFw82nkoG8U5nwKB4w9o3UsK1r/h3Oz8cn9XEKB9mLi+HEqvs LhzcOMSDjrhvJT09jUKph+ARuOKPjIvhfmiiXiLPtDXfNNdmrFF7/S1C8WOQSO2IlKfsLDXsrbaD9 MORBLWIA==; Received: from forward101o.mail.yandex.net ([37.140.190.181]) by casper.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9UeN-0002gP-7s for openwrt-devel@lists.openwrt.org; Mon, 08 Oct 2018 12:28:41 +0000 Received: from mxback4j.mail.yandex.net (mxback4j.mail.yandex.net [IPv6:2a02:6b8:0:1619::10d]) by forward101o.mail.yandex.net (Yandex) with ESMTP id 6943A1345435 for ; Mon, 8 Oct 2018 15:28:23 +0300 (MSK) Received: from smtp1p.mail.yandex.net (smtp1p.mail.yandex.net [2a02:6b8:0:1472:2741:0:8b6:6]) by mxback4j.mail.yandex.net (nwsmtp/Yandex) with ESMTP id RD1b97DLDV-SNLCSTu8; Mon, 08 Oct 2018 15:28:23 +0300 Received: by smtp1p.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id vvLubVtQwM-SMV8gGB5; Mon, 08 Oct 2018 15:28:22 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client certificate not present) From: Yury Shvedov To: openwrt-devel@lists.openwrt.org Date: Mon, 8 Oct 2018 15:28:18 +0300 Message-Id: <20181008122821.29237-2-yshvedov@wimarksystems.com> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20181008122821.29237-1-yshvedov@wimarksystems.com> References: <20181008122821.29237-1-yshvedov@wimarksystems.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181008_132839_418995_E6CF6DB8 X-CRM114-Status: GOOD ( 13.10 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-0.7 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [37.140.190.181 listed in list.dnswl.org] Subject: [OpenWrt-Devel] [PATCH 2/5] hostapd: add ubus switch_chan method to ifaces X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org switch_chan method now could be called directly by hostapd_iface object. Signed-off-by: Yury Shvedov --- .../services/hostapd/src/src/ap/ubus.c | 145 +++++++++++------- 1 file changed, 86 insertions(+), 59 deletions(-) diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index a393451af2..6d12126a1a 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -145,9 +145,88 @@ hostapd_iface_get_bss(struct ubus_context *ctx, struct ubus_object *obj, return 0; } + +#ifdef NEED_AP_MLME +enum { + CSA_FREQ, + CSA_BCN_COUNT, + CSA_CENTER_FREQ1, + CSA_CENTER_FREQ2, + CSA_BANDWIDTH, + CSA_SEC_CHANNEL_OFFSET, + CSA_HT, + CSA_VHT, + CSA_BLOCK_TX, + __CSA_MAX +}; + +static const struct blobmsg_policy csa_policy[__CSA_MAX] = { + [CSA_FREQ] = { "freq", BLOBMSG_TYPE_INT32 }, + [CSA_BCN_COUNT] = { "bcn_count", BLOBMSG_TYPE_INT32 }, + [CSA_CENTER_FREQ1] = { "center_freq1", BLOBMSG_TYPE_INT32 }, + [CSA_CENTER_FREQ2] = { "center_freq2", BLOBMSG_TYPE_INT32 }, + [CSA_BANDWIDTH] = { "bandwidth", BLOBMSG_TYPE_INT32 }, + [CSA_SEC_CHANNEL_OFFSET] = { "sec_channel_offset", BLOBMSG_TYPE_INT32 }, + [CSA_HT] = { "ht", BLOBMSG_TYPE_BOOL }, + [CSA_VHT] = { "vht", BLOBMSG_TYPE_BOOL }, + [CSA_BLOCK_TX] = { "block_tx", BLOBMSG_TYPE_BOOL }, +}; + +static int +hostapd_switch_chan(struct hostapd_data *hapd, struct blob_attr *msg) +{ + struct blob_attr *tb[__CSA_MAX]; + struct csa_settings css; + + blobmsg_parse(csa_policy, __CSA_MAX, tb, blob_data(msg), blob_len(msg)); + + if (!tb[CSA_FREQ]) + return UBUS_STATUS_INVALID_ARGUMENT; + + memset(&css, 0, sizeof(css)); + css.freq_params.freq = blobmsg_get_u32(tb[CSA_FREQ]); + +#define SET_CSA_SETTING(name, field, type) \ + do { \ + if (tb[name]) \ + css.field = blobmsg_get_ ## type(tb[name]); \ + } while(0) + + SET_CSA_SETTING(CSA_BCN_COUNT, cs_count, u32); + SET_CSA_SETTING(CSA_CENTER_FREQ1, freq_params.center_freq1, u32); + SET_CSA_SETTING(CSA_CENTER_FREQ2, freq_params.center_freq2, u32); + SET_CSA_SETTING(CSA_BANDWIDTH, freq_params.bandwidth, u32); + SET_CSA_SETTING(CSA_SEC_CHANNEL_OFFSET, freq_params.sec_channel_offset, u32); + SET_CSA_SETTING(CSA_HT, freq_params.ht_enabled, bool); + SET_CSA_SETTING(CSA_VHT, freq_params.vht_enabled, bool); + SET_CSA_SETTING(CSA_BLOCK_TX, block_tx, bool); + + + if (hostapd_switch_channel(hapd, &css) != 0) + return UBUS_STATUS_NOT_SUPPORTED; + return UBUS_STATUS_OK; +#undef SET_CSA_SETTING +} + +static int +hostapd_iface_switch_chan(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct hostapd_iface *iface = container_of(obj, struct hostapd_iface, + ubus.obj); + if (iface && iface->bss[0]) + return hostapd_switch_chan(iface->bss[0], msg); + return UBUS_STATUS_INVALID_ARGUMENT; +} +#endif + static const struct ubus_method iface_methods[] = { UBUS_METHOD_NOARG("get_state", hostapd_iface_get_state), UBUS_METHOD_NOARG("get_bss", hostapd_iface_get_bss), +#ifdef NEED_AP_MLME + UBUS_METHOD("switch_chan", hostapd_iface_switch_chan, csa_policy), +#endif }; static struct ubus_object_type iface_object_type = UBUS_OBJECT_TYPE("hostapd_iface", iface_methods); @@ -472,69 +551,17 @@ hostapd_bss_update_beacon(struct ubus_context *ctx, struct ubus_object *obj, return 0; } -enum { - CSA_FREQ, - CSA_BCN_COUNT, - CSA_CENTER_FREQ1, - CSA_CENTER_FREQ2, - CSA_BANDWIDTH, - CSA_SEC_CHANNEL_OFFSET, - CSA_HT, - CSA_VHT, - CSA_BLOCK_TX, - __CSA_MAX -}; - -static const struct blobmsg_policy csa_policy[__CSA_MAX] = { - [CSA_FREQ] = { "freq", BLOBMSG_TYPE_INT32 }, - [CSA_BCN_COUNT] = { "bcn_count", BLOBMSG_TYPE_INT32 }, - [CSA_CENTER_FREQ1] = { "center_freq1", BLOBMSG_TYPE_INT32 }, - [CSA_CENTER_FREQ2] = { "center_freq2", BLOBMSG_TYPE_INT32 }, - [CSA_BANDWIDTH] = { "bandwidth", BLOBMSG_TYPE_INT32 }, - [CSA_SEC_CHANNEL_OFFSET] = { "sec_channel_offset", BLOBMSG_TYPE_INT32 }, - [CSA_HT] = { "ht", BLOBMSG_TYPE_BOOL }, - [CSA_VHT] = { "vht", BLOBMSG_TYPE_BOOL }, - [CSA_BLOCK_TX] = { "block_tx", BLOBMSG_TYPE_BOOL }, -}; #ifdef NEED_AP_MLME static int -hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) +hostapd_bss_switch_chan(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) { - struct blob_attr *tb[__CSA_MAX]; struct hostapd_data *hapd = get_hapd_from_object(obj); - struct csa_settings css; - - blobmsg_parse(csa_policy, __CSA_MAX, tb, blob_data(msg), blob_len(msg)); - - if (!tb[CSA_FREQ]) - return UBUS_STATUS_INVALID_ARGUMENT; - - memset(&css, 0, sizeof(css)); - css.freq_params.freq = blobmsg_get_u32(tb[CSA_FREQ]); - -#define SET_CSA_SETTING(name, field, type) \ - do { \ - if (tb[name]) \ - css.field = blobmsg_get_ ## type(tb[name]); \ - } while(0) - - SET_CSA_SETTING(CSA_BCN_COUNT, cs_count, u32); - SET_CSA_SETTING(CSA_CENTER_FREQ1, freq_params.center_freq1, u32); - SET_CSA_SETTING(CSA_CENTER_FREQ2, freq_params.center_freq2, u32); - SET_CSA_SETTING(CSA_BANDWIDTH, freq_params.bandwidth, u32); - SET_CSA_SETTING(CSA_SEC_CHANNEL_OFFSET, freq_params.sec_channel_offset, u32); - SET_CSA_SETTING(CSA_HT, freq_params.ht_enabled, bool); - SET_CSA_SETTING(CSA_VHT, freq_params.vht_enabled, bool); - SET_CSA_SETTING(CSA_BLOCK_TX, block_tx, bool); - - - if (hostapd_switch_channel(hapd, &css) != 0) - return UBUS_STATUS_NOT_SUPPORTED; - return UBUS_STATUS_OK; -#undef SET_CSA_SETTING + if (hapd) + return hostapd_switch_chan(hapd, msg); + return UBUS_STATUS_INVALID_ARGUMENT; } #endif @@ -1050,7 +1077,7 @@ static const struct ubus_method bss_methods[] = { UBUS_METHOD_NOARG("update_beacon", hostapd_bss_update_beacon), UBUS_METHOD_NOARG("get_features", hostapd_bss_get_features), #ifdef NEED_AP_MLME - UBUS_METHOD("switch_chan", hostapd_switch_chan, csa_policy), + UBUS_METHOD("switch_chan", hostapd_bss_switch_chan, csa_policy), #endif UBUS_METHOD("set_vendor_elements", hostapd_vendor_elements, ve_policy), UBUS_METHOD("notify_response", hostapd_notify_response, notify_policy), From patchwork Mon Oct 8 12:28:19 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Shvedov X-Patchwork-Id: 980537 X-Patchwork-Delegate: blogic@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wimarksystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="U6Tai96h"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42TKTT4dwPz9s4Z for ; Mon, 8 Oct 2018 23:30:53 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:References: In-Reply-To:Message-Id:Date:To:From:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=d5ZzK4srPn9HnGhNN2TuoTtst0tbJPcYm7A1z8uIWqc=; b=U6Tai96haBOHHHAPeFnCjar1zM gSWSJ0pKrEkDAs519YRhwsafiRB3HGyE03ToUPXCmRCTRmGbhfhawQrm52tdB9d0G4w51H2nlfMQo j2pdNg7/MCRpcxr1ljBKaNaFmo0czFtRciMaWt/n8YszZRBalTLaTNaVcFUq5A2ljkw4xwhrm3RZx 5d6MT9wexI0fpS6qYPGCQEtmr4+sWRy0mRfoY83UngXjcqELA9gqBM8NvWNcWGtjB9VlitTYFuASG r/II1YrhdkO4AOIEi7TRGQviwkUVqDUboFPv2q36bVmQPiZtCW9h5xJ1MD1rZ4B9dUo0YPBcTexis C4CqdLvg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9UgR-00023z-D3; Mon, 08 Oct 2018 12:30:47 +0000 Received: from forward106p.mail.yandex.net ([2a02:6b8:0:1472:2741:0:8b7:109]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9UeP-0000QR-Oq for openwrt-devel@lists.openwrt.org; Mon, 08 Oct 2018 12:30:42 +0000 Received: from mxback16o.mail.yandex.net (mxback16o.mail.yandex.net [IPv6:2a02:6b8:0:1a2d::67]) by forward106p.mail.yandex.net (Yandex) with ESMTP id 5A4A52D83F85 for ; Mon, 8 Oct 2018 15:28:24 +0300 (MSK) Received: from smtp1p.mail.yandex.net (smtp1p.mail.yandex.net [2a02:6b8:0:1472:2741:0:8b6:6]) by mxback16o.mail.yandex.net (nwsmtp/Yandex) with ESMTP id m33oRKyaUI-SOCCxD60; Mon, 08 Oct 2018 15:28:24 +0300 Received: by smtp1p.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id vvLubVtQwM-SNVKoRBN; Mon, 08 Oct 2018 15:28:23 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client certificate not present) From: Yury Shvedov To: openwrt-devel@lists.openwrt.org Date: Mon, 8 Oct 2018 15:28:19 +0300 Message-Id: <20181008122821.29237-3-yshvedov@wimarksystems.com> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20181008122821.29237-1-yshvedov@wimarksystems.com> References: <20181008122821.29237-1-yshvedov@wimarksystems.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181008_052842_212926_821712C9 X-CRM114-Status: GOOD ( 17.37 ) X-Spam-Note: SpamAssassin invocation failed Subject: [OpenWrt-Devel] [PATCH 3/5] hostapd: Add ubus accounting X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org This implements ubus accounting events. This accounting works the same manner as the RADIUS accounting, except the interim (see below). There tree types of messages: start, stop and interim. Start sent when new client connected. There just current time, address and session_id of client in message. Stop sent when client disconnected. This message contains extra counters and terminate_cause. Interim sent by timeout, configured with ubus_accounting_interval variable. This message contains an information about all connected to bss clients. Payload example: { "clients": [ { "session_time": 9, "address": "68:3e:34:f5:61:3f", "session_id": "A6367C8F6C0662C1", "accounting": { "rx_bytes": 2336, "tx_packets": 5, "tx_bytes": 533, "rx_packets": 17 }, "terminate_cause": 1 } ], "device": "radio0", "bssid": "44:d1:fa:12:4c:74", "freq": 5260, "iface": "wlan0" } Signed-off-by: Yury Shvedov --- .../hostapd/patches/600-ubus_support.patch | 165 +++++++++++- .../services/hostapd/src/src/ap/ubus.c | 238 +++++++++++++++++- .../services/hostapd/src/src/ap/ubus.h | 14 ++ 3 files changed, 405 insertions(+), 12 deletions(-) diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch index c63b85c079..c0db5be4e9 100644 --- a/package/network/services/hostapd/patches/600-ubus_support.patch +++ b/package/network/services/hostapd/patches/600-ubus_support.patch @@ -99,7 +99,15 @@ hostapd_interface_deinit(iface); wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit", __func__, driver, drv_priv); -@@ -3114,6 +3120,7 @@ void hostapd_set_state(struct hostapd_if +@@ -3050,6 +3056,7 @@ void hostapd_new_assoc_sta(struct hostap + ap_sta_set_authorized(hapd, sta, 1); + os_get_reltime(&sta->connected_time); + accounting_sta_start(hapd, sta); ++ hostapd_ubus_event_sta_account_start(hapd,sta); + } + + /* Start IEEE 802.1X authentication process for new stations */ +@@ -3114,6 +3121,7 @@ void hostapd_set_state(struct hostapd_if wpa_printf(MSG_INFO, "%s: interface state %s->%s", iface->conf ? iface->conf->bss[0]->iface : "N/A", hostapd_state_text(iface->state), hostapd_state_text(s)); @@ -201,7 +209,15 @@ sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { -@@ -3630,6 +3657,8 @@ static void handle_deauth(struct hostapd +@@ -3584,6 +3611,7 @@ static void handle_disassoc(struct hosta + /* Stop Accounting and IEEE 802.1X sessions, but leave the STA + * authenticated. */ + accounting_sta_stop(hapd, sta); ++ hostapd_ubus_event_sta_account_stop(hapd, sta); + ieee802_1x_free_station(hapd, sta); + if (sta->ipaddr) + hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); +@@ -3630,6 +3658,8 @@ static void handle_deauth(struct hostapd " reason_code=%d", MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code)); @@ -210,7 +226,7 @@ sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying " -@@ -3949,7 +3978,7 @@ int ieee802_11_mgmt(struct hostapd_data +@@ -3949,7 +3979,7 @@ int ieee802_11_mgmt(struct hostapd_data if (stype == WLAN_FC_STYPE_PROBE_REQ) { @@ -219,7 +235,7 @@ return 1; } -@@ -3969,17 +3998,17 @@ int ieee802_11_mgmt(struct hostapd_data +@@ -3969,17 +3999,17 @@ int ieee802_11_mgmt(struct hostapd_data switch (stype) { case WLAN_FC_STYPE_AUTH: wpa_printf(MSG_DEBUG, "mgmt::auth"); @@ -240,6 +256,14 @@ ret = 1; break; case WLAN_FC_STYPE_DISASSOC: +@@ -4128,6 +4158,7 @@ static void handle_assoc_cb(struct hosta + /* Stop previous accounting session, if one is started, and allocate + * new session id for the new session. */ + accounting_sta_stop(hapd, sta); ++ hostapd_ubus_event_sta_account_stop(hapd, sta); + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -720,7 +720,7 @@ void sta_track_claim_taxonomy_info(struc @@ -309,7 +333,15 @@ if (addr == NULL) { /* -@@ -195,6 +199,12 @@ int hostapd_notif_assoc(struct hostapd_d +@@ -164,6 +168,7 @@ int hostapd_notif_assoc(struct hostapd_d + if (sta) { + ap_sta_no_session_timeout(hapd, sta); + accounting_sta_stop(hapd, sta); ++ hostapd_ubus_event_sta_account_stop(hapd, sta); + + /* + * Make sure that the previously registered inactivity timer +@@ -195,6 +200,12 @@ int hostapd_notif_assoc(struct hostapd_d goto fail; } @@ -324,7 +356,15 @@ wpabuf_free(sta->p2p_ie); --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c -@@ -415,6 +415,7 @@ void ap_handle_timer(void *eloop_ctx, vo +@@ -162,6 +162,7 @@ void ap_free_sta(struct hostapd_data *ha + int set_beacon = 0; + + accounting_sta_stop(hapd, sta); ++ hostapd_ubus_event_sta_account_stop(hapd, sta); + + /* just in case */ + ap_sta_set_authorized(hapd, sta, 0); +@@ -415,6 +416,7 @@ void ap_handle_timer(void *eloop_ctx, vo HOSTAPD_LEVEL_INFO, "deauthenticated due to " "local deauth request"); ap_free_sta(hapd, sta); @@ -332,7 +372,15 @@ return; } -@@ -562,6 +563,7 @@ skip_poll: +@@ -535,6 +537,7 @@ skip_poll: + sta->acct_terminate_cause = + RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; + accounting_sta_stop(hapd, sta); ++ hostapd_ubus_event_sta_account_stop(hapd, sta); + ieee802_1x_free_station(hapd, sta); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "disassociated due to " +@@ -562,6 +565,7 @@ skip_poll: hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID); ap_free_sta(hapd, sta); @@ -340,7 +388,23 @@ break; } } -@@ -1223,6 +1225,7 @@ void ap_sta_set_authorized(struct hostap +@@ -796,6 +800,7 @@ void ap_sta_disassociate(struct hostapd_ + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, + ap_handle_timer, hapd, sta); + accounting_sta_stop(hapd, sta); ++ hostapd_ubus_event_sta_account_stop(hapd, sta); + ieee802_1x_free_station(hapd, sta); + + sta->disassoc_reason = reason; +@@ -845,6 +850,7 @@ void ap_sta_deauthenticate(struct hostap + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, + ap_handle_timer, hapd, sta); + accounting_sta_stop(hapd, sta); ++ hostapd_ubus_event_sta_account_stop(hapd, sta); + ieee802_1x_free_station(hapd, sta); + + sta->deauth_reason = reason; +@@ -1223,6 +1229,7 @@ void ap_sta_set_authorized(struct hostap buf, ip_addr); } else { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); @@ -360,7 +424,7 @@ --- a/hostapd/config_file.c +++ b/hostapd/config_file.c -@@ -2663,6 +2663,11 @@ static int hostapd_config_fill(struct ho +@@ -2663,6 +2663,13 @@ static int hostapd_config_fill(struct ho 0) { bss->radius_das_require_message_authenticator = atoi(pos); #endif /* CONFIG_NO_RADIUS */ @@ -368,6 +432,8 @@ + } else if (os_strcmp(buf, "uci_device") == 0) { + os_free(bss->uci_device); + bss->uci_device = os_strdup(pos); ++ } else if (os_strcmp(buf, "ubus_acct_interim_interval") == 0) { ++ bss->ubus_acct_interim_interval = atoi(pos); +#endif /* UBUS_SUPPORT */ } else if (os_strcmp(buf, "auth_algs") == 0) { bss->auth_algs = atoi(pos); @@ -384,12 +450,91 @@ --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h -@@ -470,6 +470,8 @@ struct hostapd_bss_config { +@@ -470,6 +470,9 @@ struct hostapd_bss_config { int pbc_in_m1; char *server_id; + char *uci_device; ++ int ubus_acct_interim_interval; + #define P2P_ENABLED BIT(0) #define P2P_GROUP_OWNER BIT(1) #define P2P_GROUP_FORMATION BIT(2) +--- a/src/ap/accounting.c ++++ b/src/ap/accounting.c +@@ -164,7 +164,7 @@ static struct radius_msg * accounting_ms + } + + +-static int accounting_sta_update_stats(struct hostapd_data *hapd, ++int accounting_sta_update_stats(struct hostapd_data *hapd, + struct sta_info *sta, + struct hostap_sta_driver_data *data) + { +--- a/src/ap/accounting.h ++++ b/src/ap/accounting.h +@@ -10,19 +10,13 @@ + #define ACCOUNTING_H + + #ifdef CONFIG_NO_ACCOUNTING +-static inline int accounting_sta_get_id(struct hostapd_data *hapd, +- struct sta_info *sta) +-{ +- return 0; +-} +- + static inline void accounting_sta_start(struct hostapd_data *hapd, + struct sta_info *sta) + { + } + + static inline void accounting_sta_stop(struct hostapd_data *hapd, +- struct sta_info *sta) ++ struct sta_info *sta) + { + } + +@@ -35,11 +29,32 @@ static inline void accounting_deinit(str + { + } + #else /* CONFIG_NO_ACCOUNTING */ +-int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta); + void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta); + void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta); + int accounting_init(struct hostapd_data *hapd); + void accounting_deinit(struct hostapd_data *hapd); + #endif /* CONFIG_NO_ACCOUNTING */ + ++#if defined (CONFIG_NO_ACCOUNTING ) && !defined (UBUS_SUPPORT) ++static inline int accounting_sta_get_id(struct hostapd_data *hapd, ++ struct sta_info *sta) ++{ ++ return 0; ++} ++static int accounting_sta_update_stats(struct hostapd_data *hapd, ++ struct sta_info *sta, ++ struct hostap_sta_driver_data *data) ++{ ++ return 0; ++} ++ ++#else ++ ++int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta); ++int accounting_sta_update_stats(struct hostapd_data *hapd, ++ struct sta_info *sta, ++ struct hostap_sta_driver_data *data); ++ ++#endif /* CONFIG_NO_ACCOUNTING && UBUS_SUPPORT */ ++ + #endif /* ACCOUNTING_H */ +--- a/src/ap/sta_info.h ++++ b/src/ap/sta_info.h +@@ -139,6 +139,7 @@ struct sta_info { + int acct_terminate_cause; /* Acct-Terminate-Cause */ + int acct_interim_interval; /* Acct-Interim-Interval */ + unsigned int acct_interim_errors; ++ int ubus_acct_session_started; + + /* For extending 32-bit driver counters to 64-bit counters */ + u32 last_rx_bytes_hi; diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index 6d12126a1a..2ceb2de159 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -18,10 +18,14 @@ #include "ubus.h" #include "ap_drv_ops.h" #include "beacon.h" +#include "accounting.h" +#include "radius/radius.h" #include "rrm.h" #include "wnm_ap.h" #include "taxonomy.h" +#define ACCT_DEFAULT_UPDATE_INTERVAL 300 + static struct ubus_context *ctx; static struct blob_buf b; static int ctx_ref; @@ -1099,6 +1103,21 @@ static int avl_compare_macaddr(const void *k1, const void *k2, void *ptr) return memcmp(k1, k2, ETH_ALEN); } +static void hostapd_ubus_accounting_interim_update(void *eloop_ctx, void *); +static bool hostapd_ubus_accounting_init(struct hostapd_data *hapd) +{ + int interval = hapd->conf->ubus_acct_interim_interval; + if (!interval) + interval = ACCT_DEFAULT_UPDATE_INTERVAL; + eloop_register_timeout(interval, 0, hostapd_ubus_accounting_interim_update, + hapd, NULL); + return true; +} +static void hostapd_ubus_accounting_stop(struct hostapd_data *hapd) +{ + eloop_cancel_timeout(hostapd_ubus_accounting_interim_update, hapd, NULL); +} + void hostapd_ubus_add_bss(struct hostapd_data *hapd) { struct ubus_object *obj = &hapd->ubus.obj; @@ -1113,9 +1132,16 @@ void hostapd_ubus_add_bss(struct hostapd_data *hapd) if (!hostapd_ubus_init()) return; + if (obj->id) { + return; + } + if (asprintf(&name, "hostapd.%s", hapd->conf->iface) < 0) return; + if (!hostapd_ubus_accounting_init(hapd)) + return; + avl_init(&hapd->ubus.banned, avl_compare_macaddr, false, NULL); obj->name = name; obj->type = &bss_object_type; @@ -1133,6 +1159,8 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd) if (!ctx) return; + hostapd_ubus_accounting_stop(hapd); + if (obj->id) { ubus_remove_object(ctx, obj); hostapd_ubus_ref_dec(); @@ -1207,7 +1235,7 @@ int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_req ht_capabilities = (struct ieee80211_ht_capabilities*) req->elems->ht_capabilities; ht_cap = blobmsg_open_table(&b, "ht_capabilities"); blobmsg_add_u16(&b, "ht_capabilities_info", ht_capabilities->ht_capabilities_info); - ht_cap_mcs_set = blobmsg_open_table(&b, "supported_mcs_set"); + ht_cap_mcs_set = blobmsg_open_table(&b, "supported_mcs_set"); blobmsg_add_u16(&b, "a_mpdu_params", ht_capabilities->a_mpdu_params); blobmsg_add_u16(&b, "ht_extended_capabilities", ht_capabilities->ht_extended_capabilities); blobmsg_add_u32(&b, "tx_bf_capability_info", ht_capabilities->tx_bf_capability_info); @@ -1218,7 +1246,7 @@ int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_req } blobmsg_close_array(&b, mcs_set); blobmsg_close_table(&b, ht_cap_mcs_set); - blobmsg_close_table(&b, ht_cap); + blobmsg_close_table(&b, ht_cap); } if(req->elems->vht_capabilities) { @@ -1294,3 +1322,209 @@ void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s) blobmsg_add_string(&b, "state", hostapd_state_text(s)); ubus_send_event(ctx, "hostapd.iface_state", b.head); } +static void +blobmsg_add_sta_data(struct blob_buf *buf, const char *name, + struct sta_info *sta, + const struct hostap_sta_driver_data *data) +{ + u64 bytes; + void *tbl = blobmsg_open_table(buf, name); + + blobmsg_add_u32(buf, "rx_packets", data->rx_packets); + blobmsg_add_u32(buf, "tx_packets", data->tx_packets); + + if (data->bytes_64bit) + bytes = data->rx_bytes; + else + bytes = ((u64) sta->last_rx_bytes_hi << 32) | + sta->last_rx_bytes_lo; + blobmsg_add_u64(buf, "rx_bytes", bytes); + if (data->bytes_64bit) + bytes = data->tx_bytes; + else + bytes = ((u64) sta->last_tx_bytes_hi << 32) | + sta->last_tx_bytes_lo; + blobmsg_add_u64(buf, "tx_bytes", bytes); + blobmsg_add_double(buf, "rssi", data->last_ack_rssi); + blobmsg_add_double(buf, "signal", data->signal); + + blobmsg_close_table(buf, tbl); +} +static void +blobmsg_add_reltime(struct blob_buf *buf, const char *name, + const struct os_reltime *reltime) +{ + blobmsg_add_u32(buf, name, reltime->sec); +} +static void +blobmsg_add_session_id(struct blob_buf *buf, const char *name, + struct sta_info *sta) +{ + blobmsg_printf(buf, name, "%016llX", + (unsigned long long) sta->acct_session_id); +} +static void +blobmsg_add_station_accounting(struct blob_buf *buf, + const char *name, + struct sta_info *sta, + const struct hostap_sta_driver_data *data, + const struct os_reltime *session_time, + int cause) +{ + void *tbl = blobmsg_open_table(buf, name); + blobmsg_add_macaddr(buf, "address", sta->addr); + blobmsg_add_session_id(buf, "session_id", sta); + if(data) + blobmsg_add_sta_data(buf, "accounting", sta, data); + if(session_time) + blobmsg_add_reltime(buf, "session_time", session_time); + if (sta->identity) + blobmsg_add_string(buf, "identity", sta->identity); + if (cause > 0) + blobmsg_add_u32(buf, "terminate_cause", cause); + blobmsg_close_table(buf, tbl); +} +static void hostapd_ubus_event_sta_account(struct hostapd_data *hapd, + struct sta_info *sta, const char *status, + const struct hostap_sta_driver_data *data, + const struct os_reltime *session_time, + int cause) +{ + void *arr; + + if (!ctx) + return; + blob_buf_init(&b, 0); + + arr = blobmsg_open_array(&b, "clients"); + blobmsg_add_station_accounting(&b, NULL, sta, data, session_time, cause); + blobmsg_close_array(&b, arr); + blobmsg_add_u32(&b, "freq", hapd->iface->freq); + + blobmsg_add_hapd_id(&b, hapd); + ubus_notify(ctx, &hapd->ubus.obj, status, b.head, -1); +} +void hostapd_ubus_event_sta_account_start(struct hostapd_data *hapd, + struct sta_info *sta) +{ + if (sta->ubus_acct_session_started || !hapd->ubus.obj.has_subscribers) + return; +#ifdef CONFIG_NO_ACCOUNTING + os_get_reltime(&sta->acct_session_start); + sta->last_rx_bytes_hi = 0; + sta->last_rx_bytes_lo = 0; + sta->last_tx_bytes_hi = 0; + sta->last_tx_bytes_lo = 0; + hostapd_drv_sta_clear_stats(hapd, sta->addr); +#endif + sta->ubus_acct_session_started = 1; + hostapd_ubus_event_sta_account(hapd, sta, "start", NULL, NULL, 0); +} +void hostapd_ubus_event_sta_account_stop(struct hostapd_data *hapd, + struct sta_info *sta) +{ + struct hostap_sta_driver_data data, *pdata = NULL; + struct os_reltime now_r, diff; + int cause = sta->acct_terminate_cause; + + if (!sta->ubus_acct_session_started || !hapd->ubus.obj.has_subscribers) + return; + sta->ubus_acct_session_started = 0; + if (!ctx) + return; + if (eloop_terminated()) + cause = RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT; + os_get_reltime(&now_r); + os_reltime_sub(&now_r, &sta->acct_session_start, &diff); + if (accounting_sta_update_stats(hapd, sta, &data) == 0) + pdata = &data; + hostapd_ubus_event_sta_account(hapd, sta, "stop", pdata, &diff, cause); +} +struct ubus_sta_acct_counter { + struct blob_buf *buf; + int counter; + struct os_reltime now; +}; +static int hostapd_ubus_event_sta_account_interim(struct hostapd_data *hapd, + struct sta_info *sta, void *ctx) +{ + struct ubus_sta_acct_counter *counter = ctx; + struct os_reltime diff; + struct hostap_sta_driver_data data, *pdata = NULL; + + if (!sta->ubus_acct_session_started) + return 0; + os_reltime_sub(&counter->now, &sta->acct_session_start, &diff); + if (accounting_sta_update_stats(hapd, sta, &data) == 0) + pdata = &data; + blobmsg_add_station_accounting(counter->buf, NULL, sta, pdata, &diff, 0); + ++counter->counter; +} +static void hostapd_ubus_accounting_interim(struct hostapd_data *hapd, + struct sta_info *sta) +{ + struct ubus_sta_acct_counter counter = { &b, 0 }; + void *arr; + + if (!hapd->ubus.obj.has_subscribers) + return; + blob_buf_init(&b, 0); + + os_get_reltime(&counter.now); + blobmsg_add_u32(&b, "freq", hapd->iface->freq); + blobmsg_add_hapd_id(&b, hapd); + arr = blobmsg_open_array(&b, "clients"); + + if (sta != NULL) + hostapd_ubus_event_sta_account_interim(hapd, sta, &counter); + else + ap_for_each_sta(hapd, hostapd_ubus_event_sta_account_interim, &counter); + blobmsg_close_array(&b, arr); + if (counter.counter > 0) + ubus_notify(ctx, &hapd->ubus.obj, "interim", b.head, -1); +} +static void hostapd_ubus_accounting_interim_update(void *eloop_ctx, + void *timer_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + hostapd_ubus_accounting_interim(hapd, NULL); + hostapd_ubus_accounting_init(hapd); +} + +#ifdef CONFIG_NO_ACCOUNTING +int accounting_sta_update_stats(struct hostapd_data *hapd, + struct sta_info *sta, + struct hostap_sta_driver_data *data) +{ + if (hostapd_drv_read_sta_data(hapd, data, sta->addr)) + return -1; + + if (!data->bytes_64bit) { + /* Extend 32-bit counters from the driver to 64-bit counters */ + if (sta->last_rx_bytes_lo > data->rx_bytes) + sta->last_rx_bytes_hi++; + sta->last_rx_bytes_lo = data->rx_bytes; + + if (sta->last_tx_bytes_lo > data->tx_bytes) + sta->last_tx_bytes_hi++; + sta->last_tx_bytes_lo = data->tx_bytes; + } + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_DEBUG, + "updated TX/RX stats: rx_bytes=%llu [%u:%u] tx_bytes=%llu [%u:%u] bytes_64bit=%d", + data->rx_bytes, sta->last_rx_bytes_hi, + sta->last_rx_bytes_lo, + data->tx_bytes, sta->last_tx_bytes_hi, + sta->last_tx_bytes_lo, + data->bytes_64bit); + + return 0; +} +int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta) +{ + /* Copied from radius_gen_session_id */ + return os_get_random((u8 *) &sta->acct_session_id, + sizeof(sta->acct_session_id)); +} +#endif diff --git a/package/network/services/hostapd/src/src/ap/ubus.h b/package/network/services/hostapd/src/src/ap/ubus.h index 840b000180..cc4b5fcb0f 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.h +++ b/package/network/services/hostapd/src/src/ap/ubus.h @@ -27,6 +27,7 @@ struct hostapd_ubus_request { struct hostapd_iface; struct hostapd_data; +struct sta_info; #ifdef UBUS_SUPPORT @@ -53,6 +54,11 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 * void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s); +void hostapd_ubus_event_sta_account_start(struct hostapd_data *hapd, + struct sta_info *sta); +void hostapd_ubus_event_sta_account_stop(struct hostapd_data *hapd, + struct sta_info *sta); + #else struct hostapd_ubus_iface {}; @@ -86,6 +92,14 @@ static inline void hostapd_ubus_notify(struct hostapd_data *hapd, const char *ty static inline void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s) { } +static inline void hostapd_ubus_event_sta_account_start(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} +static inline void hostapd_ubus_event_sta_account_stop(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} #endif #endif From patchwork Mon Oct 8 12:28:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Shvedov X-Patchwork-Id: 980538 X-Patchwork-Delegate: blogic@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wimarksystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="qasroRoU"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42TKVC12GDz9sBk for ; Mon, 8 Oct 2018 23:31:30 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:References: In-Reply-To:Message-Id:Date:To:From:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=clB7x6ESBJwgVW8oRICPn+vOc7aM5ZtfNWFCLPkpcJA=; b=qasroRoUQoxlh8tF0cNVVhy1QR +afrmlYazQsIQh1sJ0Q2chnL0zu+6R3TeMx25E1eGQesSB0BN8vYJ3y0pZ0GPQg51dw3lpiHePUgD Dt157FoeqHlUj13q3MouOe4fIbFRHiqGKWvDBqfUihScwA9DemkrM07h5ts3PZkJC8VqYDGzt5OnS IBp1n3BBLUMjeyYqEWhcjILR/8HjN2WSiE9SMbdVZVJDzGb0EVEskS7xB/2yC6AWXhbcyD/oM8XHV zlroczYOxDolJIkgVfMklNF1n5H3T31/BPXrGwohmf8dc8nH4dSSVSHQBzog7WqhYvoePFRU2Oy9H +vOQv9rg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9Uh0-0002HE-3X; Mon, 08 Oct 2018 12:31:22 +0000 Received: from forward102j.mail.yandex.net ([2a02:6b8:0:801:2::102]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9UeQ-0000Qd-BV for openwrt-devel@lists.openwrt.org; Mon, 08 Oct 2018 12:30:42 +0000 Received: from mxback13j.mail.yandex.net (mxback13j.mail.yandex.net [IPv6:2a02:6b8:0:1619::88]) by forward102j.mail.yandex.net (Yandex) with ESMTP id CDC9F5603E51 for ; Mon, 8 Oct 2018 15:28:24 +0300 (MSK) Received: from smtp1p.mail.yandex.net (smtp1p.mail.yandex.net [2a02:6b8:0:1472:2741:0:8b6:6]) by mxback13j.mail.yandex.net (nwsmtp/Yandex) with ESMTP id KYT3FlhszU-SOo4mvMn; Mon, 08 Oct 2018 15:28:24 +0300 Received: by smtp1p.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id vvLubVtQwM-SOVKJfE3; Mon, 08 Oct 2018 15:28:24 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client certificate not present) From: Yury Shvedov To: openwrt-devel@lists.openwrt.org Date: Mon, 8 Oct 2018 15:28:20 +0300 Message-Id: <20181008122821.29237-4-yshvedov@wimarksystems.com> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20181008122821.29237-1-yshvedov@wimarksystems.com> References: <20181008122821.29237-1-yshvedov@wimarksystems.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181008_052842_760029_13B73CE1 X-CRM114-Status: GOOD ( 10.30 ) X-Spam-Note: SpamAssassin invocation failed Subject: [OpenWrt-Devel] [PATCH 4/5] hostapd: Add channel information to iface state event X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org This adds wide information about current channel of interface to hostapd.iface_state event. Additional event sent when interface completes csa operation. Signed-off-by: Yury Shvedov --- .../hostapd/patches/600-ubus_support.patch | 8 +++ .../services/hostapd/src/src/ap/ubus.c | 69 +++++++++++++++++-- .../services/hostapd/src/src/ap/ubus.h | 4 ++ 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch index c0db5be4e9..0bba0ba752 100644 --- a/package/network/services/hostapd/patches/600-ubus_support.patch +++ b/package/network/services/hostapd/patches/600-ubus_support.patch @@ -354,6 +354,14 @@ #ifdef CONFIG_P2P if (elems.p2p) { wpabuf_free(sta->p2p_ie); +@@ -816,6 +827,7 @@ void hostapd_event_ch_switch(struct host + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED + "freq=%d dfs=%d", freq, is_dfs); + } ++ hostapd_ubus_event_ch_switch(hapd->iface); + #endif /* NEED_AP_MLME */ + } + --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -162,6 +162,7 @@ void ap_free_sta(struct hostapd_data *ha diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index 2ceb2de159..abbe3fac88 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -1300,6 +1300,53 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 * ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1); } +static void blobmsg_add_iface_state(struct blob_buf *buff, + struct hostapd_iface *iface, int cur, int old) +{ + blobmsg_add_u32(buff, "oldstate_num", old); + blobmsg_add_string(buff, "oldstate", hostapd_state_text(old)); + blobmsg_add_u32(buff, "state_num", cur); + blobmsg_add_string(buff, "state", hostapd_state_text(cur)); +} +static void blobmsg_add_iface_channel(struct blob_buf *buff, + struct hostapd_iface *iface) +{ + struct hostapd_config *conf = iface->conf; + int width = 20; + void *chan; + + if (!iface->freq) { + return; + } + + chan = blobmsg_open_table(buff, "channel"); + + blobmsg_add_u32(buff, "freq", iface->freq); + blobmsg_add_u32(buff, "channel", conf->channel); + blobmsg_add_u8(buff, "ht", conf->ieee80211n); + blobmsg_add_u8(buff, "vht", conf->ieee80211ac); + blobmsg_add_u32(buff, "secondary_channel", conf->secondary_channel); + switch (conf->vht_oper_chwidth) { + case VHT_CHANWIDTH_USE_HT: + width = conf->secondary_channel ? 40 : 20; + break; + case VHT_CHANWIDTH_80MHZ: + width = 80; + break; + case VHT_CHANWIDTH_160MHZ: + width = 160; + break; + case VHT_CHANWIDTH_80P80MHZ: + width = 8080; + break; + } + blobmsg_add_u32(buff, "width", width); + blobmsg_add_u32(buff, "center_idx0", conf->vht_oper_centr_freq_seg0_idx); + blobmsg_add_u32(buff, "center_idx1", conf->vht_oper_centr_freq_seg1_idx); + blobmsg_add_u8(buff, "is_dfs", ieee80211_is_dfs(iface->freq, + iface->hw_features, iface->num_hw_features)); + blobmsg_close_table(buff, chan); +} /* Send ubus event in case new event differs. */ void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s) { @@ -1316,10 +1363,24 @@ void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s) blobmsg_add_string(&b, "device", hapd->conf->uci_device); if (iface->ubus.obj.id) blobmsg_add_string(&b, "uobject", iface->ubus.obj.name); - blobmsg_add_u32(&b, "oldstate_num", iface->state); - blobmsg_add_string(&b, "oldstate", hostapd_state_text(iface->state)); - blobmsg_add_u32(&b, "state_num", s); - blobmsg_add_string(&b, "state", hostapd_state_text(s)); + blobmsg_add_iface_state(&b, iface, s, iface->state); + blobmsg_add_iface_channel(&b, iface); + ubus_send_event(ctx, "hostapd.iface_state", b.head); +} +void hostapd_ubus_event_ch_switch(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + + if (!hostapd_ubus_init()) + return; + hostapd_ubus_add_iface(iface); + blob_buf_init(&b, 0); + if (hapd && hapd->conf->uci_device) + blobmsg_add_string(&b, "device", hapd->conf->uci_device); + if (iface->ubus.obj.id) + blobmsg_add_string(&b, "uobject", iface->ubus.obj.name); + blobmsg_add_iface_state(&b, iface, iface->state, iface->state); + blobmsg_add_iface_channel(&b, iface); ubus_send_event(ctx, "hostapd.iface_state", b.head); } static void diff --git a/package/network/services/hostapd/src/src/ap/ubus.h b/package/network/services/hostapd/src/src/ap/ubus.h index cc4b5fcb0f..6d2e1c7bcd 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.h +++ b/package/network/services/hostapd/src/src/ap/ubus.h @@ -58,6 +58,7 @@ void hostapd_ubus_event_sta_account_start(struct hostapd_data *hapd, struct sta_info *sta); void hostapd_ubus_event_sta_account_stop(struct hostapd_data *hapd, struct sta_info *sta); +void hostapd_ubus_event_ch_switch(struct hostapd_iface *iface); #else @@ -92,6 +93,9 @@ static inline void hostapd_ubus_notify(struct hostapd_data *hapd, const char *ty static inline void hostapd_ubus_event_iface_state(struct hostapd_iface *iface, int s) { } +static inline void hostapd_ubus_event_ch_switch(struct hostapd_iface *iface) +{ +} static inline void hostapd_ubus_event_sta_account_start(struct hostapd_data *hapd, struct sta_info *sta) { From patchwork Mon Oct 8 12:28:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Shvedov X-Patchwork-Id: 980545 X-Patchwork-Delegate: blogic@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=wimarksystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="PtzH0Wbm"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="SJj+FsA4"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42TKnx4mR7z9s8r for ; Mon, 8 Oct 2018 23:45:08 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:References: In-Reply-To:Message-Id:Date:To:From:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=EjzmmWsxMlVsP9wQrtC5q8fyk+kDZ4XKZS7fKlCwAlg=; b=PtzH0Wbm2HoAPAA2TD4W39F8d+ cF1Cl2sfh6jXElg2rntaSFGH0DkcxcB9/EPyvr9TSEvm5EsqinPYl/nPjwbaCDxtpNpjinsk1P9vh 44k8xExKxSO4pMJpnogTRb88zVCnkEfm3FP4qFntzBVQz14KNdO3c8XNENFSVSfinrpOhnSAAwFD9 087u/8XFpAyKsQOxCJab5OQLZP2ZEKakGh7S7eYle6qTPIMC5wHMovsIyULnpbaVq42BOzmsIWLpk GXXwgUItNx9mI3eEv5ywXnbejXDDLfaKk9j7SelhhDZKW1PjJtduuadzh+rAs+UJryhB/6BH9lTnD Qr/zLOeg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9UuB-0007Fl-CB; Mon, 08 Oct 2018 12:44:59 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9Uu8-0006yf-N0 for openwrt-devel@bombadil.infradead.org; Mon, 08 Oct 2018 12:44:56 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc: Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=fdHERcpilP2MsBbC6p/HAwMzaTeplnUMik5Hz+wnvTk=; b=SJj+FsA4q23229iGnSSgR9qAph q56iRoeTzkNT4zf8rwNV5aGu5uS302d37OrqCMbBYtae8J28y/Lpi7Di3l1XoTK9TUAOhgXB6ajkt Yz3lazG03L/fT4JHVyhg+wnV+CDIg1/TcYj/BjclgQ0K9jgqR9iivXRS7PWdCY61JkjHfsdwVp9PM /29Ma688/s/iG4uAnIpg4DDkeUk6r7GNZi2QGiidfWvdwlckLlIgCBUWa6HMDKhOEr9ifOolOwD/g WRrvS6Xfa2IQWfrPamDUofqwQH0LRZmASI3R0mdSWWM56bZsGw+7tpL8QlzXEKz4XPq2YPBcWU+7g N2+ZFtLA==; Received: from forward106o.mail.yandex.net ([37.140.190.187]) by casper.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g9UeN-0002gQ-Uz for openwrt-devel@lists.openwrt.org; Mon, 08 Oct 2018 12:28:46 +0000 Received: from mxback4j.mail.yandex.net (mxback4j.mail.yandex.net [IPv6:2a02:6b8:0:1619::10d]) by forward106o.mail.yandex.net (Yandex) with ESMTP id 874217853E3 for ; Mon, 8 Oct 2018 15:28:25 +0300 (MSK) Received: from smtp1p.mail.yandex.net (smtp1p.mail.yandex.net [2a02:6b8:0:1472:2741:0:8b6:6]) by mxback4j.mail.yandex.net (nwsmtp/Yandex) with ESMTP id 9IoFYRgwMv-SPL0dnTV; Mon, 08 Oct 2018 15:28:25 +0300 Received: by smtp1p.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id vvLubVtQwM-SOVitF9D; Mon, 08 Oct 2018 15:28:24 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client certificate not present) From: Yury Shvedov To: openwrt-devel@lists.openwrt.org Date: Mon, 8 Oct 2018 15:28:21 +0300 Message-Id: <20181008122821.29237-5-yshvedov@wimarksystems.com> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20181008122821.29237-1-yshvedov@wimarksystems.com> References: <20181008122821.29237-1-yshvedov@wimarksystems.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181008_132840_222800_8EA7F272 X-CRM114-Status: GOOD ( 24.36 ) X-Spam-Score: -0.7 (/) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-0.7 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [37.140.190.187 listed in list.dnswl.org] Subject: [OpenWrt-Devel] [PATCH 5/5] hostapd: update switch_channel methods X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org This patch implements more complex procedure of channel switching. It can accept the list of channel features witch can contain the list of channel numbers or frequencies. There two type of operation - fast and not fast. To be more, accurate, there two operations now - switch_chan and switch_chan_list. The first accepts nearly the same arguments as old, except next: * Instead of freq and chan parameters there could be one of four: freq - the same as old, channel - the same as old, freqs - the list of frequencies and channels - the list of channels. Only one of them will be used and translates to the list of channels. The priority order is the same as listed. * There no segment 0 and 1 indexes variables. They will be predicted automatically by vht_oper_cwidth. * The variable vht_oper_chwidth could be one of VHT_CHANWIDTH_ values, or 20, 40, 80, 160 and 8080 to be more user-friendly. * New variables fast and allow_acs will be described later. The switch_can_list has bcn_count, block_tx, fast and allow_acs variables with the same meanings as in switch_chan. The list variable is a list of object with switch_chan arguments. Let's call this list the features list. The fast (defined by boolean variable fast) will try only to perform the channel_switch operation via the driver. With the most drivers and channel (except the DFS) this will successfully works. The operation will roll over features and channels lists until successful driver's switch_chan. The non-fast operation will take the first feature, assemble the chanlist configuration and restarts ap. The full configuring operation occurs including acs (if allow_acs) and DFS. The result channel will be chosen from the channel list. In case when all listed channels are prohibited by DFS the hostapd will stay switched off. Signed-off-by: Yury Shvedov --- .../services/hostapd/src/src/ap/ubus.c | 510 ++++++++++++++++-- 1 file changed, 473 insertions(+), 37 deletions(-) diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index abbe3fac88..a3e2c00777 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -23,6 +23,8 @@ #include "rrm.h" #include "wnm_ap.h" #include "taxonomy.h" +#include "hw_features.h" +#include "common/hw_features_common.h" #define ACCT_DEFAULT_UPDATE_INTERVAL 300 @@ -153,63 +155,405 @@ hostapd_iface_get_bss(struct ubus_context *ctx, struct ubus_object *obj, #ifdef NEED_AP_MLME enum { CSA_FREQ, - CSA_BCN_COUNT, - CSA_CENTER_FREQ1, - CSA_CENTER_FREQ2, - CSA_BANDWIDTH, - CSA_SEC_CHANNEL_OFFSET, + CSA_CHANNEL, + CSA_FREQS, + CSA_CHANNELS, CSA_HT, CSA_VHT, + CSA_SECONDARY_CHANNEL, + CSA_VHT_OPER_CWIDTH, + CSA_BCN_COUNT, CSA_BLOCK_TX, - __CSA_MAX + CSA_FAST, + CSA_ALLOW_ACS, + __CSA_MAX, }; static const struct blobmsg_policy csa_policy[__CSA_MAX] = { [CSA_FREQ] = { "freq", BLOBMSG_TYPE_INT32 }, - [CSA_BCN_COUNT] = { "bcn_count", BLOBMSG_TYPE_INT32 }, - [CSA_CENTER_FREQ1] = { "center_freq1", BLOBMSG_TYPE_INT32 }, - [CSA_CENTER_FREQ2] = { "center_freq2", BLOBMSG_TYPE_INT32 }, - [CSA_BANDWIDTH] = { "bandwidth", BLOBMSG_TYPE_INT32 }, - [CSA_SEC_CHANNEL_OFFSET] = { "sec_channel_offset", BLOBMSG_TYPE_INT32 }, + [CSA_CHANNEL] = { "channel", BLOBMSG_TYPE_INT32 }, + [CSA_FREQS] = { "freqs", BLOBMSG_TYPE_ARRAY }, + [CSA_CHANNELS] = { "channels", BLOBMSG_TYPE_ARRAY }, [CSA_HT] = { "ht", BLOBMSG_TYPE_BOOL }, [CSA_VHT] = { "vht", BLOBMSG_TYPE_BOOL }, + [CSA_SECONDARY_CHANNEL] = { "secondary_channel", BLOBMSG_TYPE_INT32 }, + [CSA_VHT_OPER_CWIDTH] = { "vht_oper_chwidth", BLOBMSG_TYPE_INT32 }, + [CSA_BCN_COUNT] = { "bcn_count", BLOBMSG_TYPE_INT32 }, [CSA_BLOCK_TX] = { "block_tx", BLOBMSG_TYPE_BOOL }, + [CSA_FAST] = { "fast", BLOBMSG_TYPE_BOOL }, + [CSA_ALLOW_ACS] = { "allow_acs", BLOBMSG_TYPE_BOOL }, }; +static void ubus_adjust_vht_center_freq(struct hostapd_iface *iface, + int chan, int secondary_channel, int *vht_oper_chwidth, + int ht, int vht, + u8 *vht_oper_centr_freq_seg0_idx, + u8 *vht_oper_centr_freq_seg1_idx) +{ + *vht_oper_centr_freq_seg1_idx = 0; + if (!chan) + return; + if (!ht && !vht) { + *vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; + *vht_oper_centr_freq_seg0_idx = chan; + return; + } + + switch (*vht_oper_chwidth) { + case VHT_CHANWIDTH_USE_HT: + case 40: + *vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; + if (secondary_channel == 1) + *vht_oper_centr_freq_seg0_idx = chan + 2; + else if (secondary_channel == -1) + *vht_oper_centr_freq_seg0_idx = chan - 2; + else + *vht_oper_centr_freq_seg0_idx = chan; + break; + case VHT_CHANWIDTH_80MHZ: + case 80: + *vht_oper_chwidth = VHT_CHANWIDTH_80MHZ; + *vht_oper_centr_freq_seg0_idx = chan + 6; + break; + case VHT_CHANWIDTH_160MHZ: + case 160: + *vht_oper_chwidth = VHT_CHANWIDTH_160MHZ; + *vht_oper_centr_freq_seg0_idx = chan + 14; + break; + case 20: + default: + *vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; + *vht_oper_centr_freq_seg0_idx = chan; + break; + } +} +static int ubus_bandwidth_to_vht_oper_chwidth(int bandwidth, int center_freq1, + int center_freq2) +{ + if (bandwidth < 80) { + return VHT_CHANWIDTH_USE_HT; + } else if (bandwidth < 160) { + return center_freq2 ? VHT_CHANWIDTH_80P80MHZ : VHT_CHANWIDTH_80MHZ; + } else { + return VHT_CHANWIDTH_160MHZ; + } +} static int -hostapd_switch_chan(struct hostapd_data *hapd, struct blob_attr *msg) +hostapd_iface_try_channel_fallback_helper(struct hostapd_iface *iface, + struct wpa_freq_range_list *ch_list, int ht, int vht, int sec_channel, + int vht_oper_chwidth, int center_idx0, int center_idx1, int acs, + int *disabled, int do_switch) +{ + iface->conf->ieee80211n = ht; + iface->conf->ieee80211ac = vht; + iface->conf->secondary_channel = sec_channel; + //iface->freq = ch_list->range->min; + iface->conf->channel = ch_list->range->min; + iface->conf->vht_oper_centr_freq_seg0_idx = center_idx0; + iface->conf->vht_oper_centr_freq_seg1_idx = center_idx1; + iface->conf->vht_oper_chwidth = vht_oper_chwidth; + iface->conf->acs = acs; + if (acs) + iface->conf->channel = 0; + wpa_printf(MSG_DEBUG, "ubus: Fallback channel switch selected %d - %s, " + "list: %s, ht - %d, vht - %d sec_channel - %d, seg0_idx - %d, " + "seg1_idx - %d, chwidth - %d", iface->conf->channel, + acs ? "with acs" : "without acs", freq_range_list_str(ch_list), ht, + vht, sec_channel, center_idx0, center_idx1, vht_oper_chwidth); + iface->conf->acs_ch_list.range = + os_realloc_array(iface->conf->acs_ch_list.range, ch_list->num, + sizeof(struct wpa_freq_range)); + os_memcpy (iface->conf->acs_ch_list.range, ch_list->range, + ch_list->num * sizeof(struct wpa_freq_range)); + iface->conf->acs_ch_list.num = ch_list->num; + + if (!*disabled) { + if (!do_switch) { + return 0; + } + hostapd_disable_iface(iface); + *disabled = 1; + } + if (!hostapd_enable_iface(iface)) { + *disabled = 0; + return 0; + } + return -1; +} +static int +hostapd_iface_try_channel_fallback(struct hostapd_iface *iface, + struct wpa_freq_range_list *ch_list, int ht, int vht, int sec_channel, + int vht_oper_chwidth, int acs, int *disabled, int do_switch) +{ + u8 center_idx0, center_idx1; + ubus_adjust_vht_center_freq(iface, ch_list->range->min, sec_channel, + &vht_oper_chwidth, ht, vht, ¢er_idx0, ¢er_idx1); + + return hostapd_iface_try_channel_fallback_helper(iface, ch_list, ht, vht, + sec_channel, vht_oper_chwidth, center_idx0, center_idx1, acs, + disabled, do_switch); +} +static int +hostapd_iface_try_channel_fallback_fp(struct hostapd_iface *iface, + struct hostapd_freq_params *data, int acs, + struct wpa_freq_range_list *ch_list, int *disabled, int do_switch) +{ + int center_idx0 = hostapd_hw_get_channel(iface->bss[0], data->center_freq1); + int center_idx1 = hostapd_hw_get_channel(iface->bss[0], data->center_freq2); + + return hostapd_iface_try_channel_fallback_helper(iface, ch_list, + data->ht_enabled, data->vht_enabled, + data->sec_channel_offset, + ubus_bandwidth_to_vht_oper_chwidth(data->bandwidth, + center_idx0, center_idx1), center_idx0, center_idx1, + acs, disabled, do_switch); +} +static int hostapd_set_curr_freq_params(struct hostapd_iface *iface, + struct hostapd_freq_params *params, int *acs, + struct wpa_freq_range_list *ch_list) +{ + struct hostapd_config *conf = iface->conf; + memset(params, 0, sizeof(*params)); + memset(ch_list, 0, sizeof(*ch_list)); + + if (hostapd_set_freq_params(params, conf->hw_mode, + hostapd_hw_get_freq(*iface->bss, conf->channel), + conf->channel, conf->ieee80211n, + conf->ieee80211ac, + conf->secondary_channel, + conf->vht_oper_chwidth, + conf->vht_oper_centr_freq_seg0_idx, + conf->vht_oper_centr_freq_seg1_idx, + conf->vht_capab)) + { + params->channel = 0; + return -1; + } + *acs = conf->acs; + if (!*acs) + return 0; + ch_list->range = os_calloc(conf->acs_ch_list.num, sizeof(*ch_list->range)); + ch_list->num = conf->acs_ch_list.num; + os_memcpy(ch_list->range, conf->acs_ch_list.range, + conf->acs_ch_list.num * sizeof(*ch_list->range)); + return 0; +} +static int +hostapd_freq_params_compare(struct hostapd_freq_params *a, + struct hostapd_freq_params *b) +{ + /* Compiler could choose different size of enum than int. Other values are + * the same size, so there should not be any padding */ + return a->mode == b->mode && + os_memcmp(&a->freq, &b->freq, sizeof(*a) - ((void *)&a->freq - (void *)a)) == 0; +} +static int +hostapd_iface_try_channel(struct hostapd_iface *iface, struct hostapd_freq_params *old, + struct wpa_freq_range_list *ch_list, int ht, int vht, int sec_channel, + int vht_oper_chwidth, int cs_count, int block_tx, int fast, + int acs, int *disabled) { - struct blob_attr *tb[__CSA_MAX]; struct csa_settings css; + struct hostapd_freq_params *freq_params = &css.freq_params; + unsigned int i, k; + int err = 1; + int chan, freq; + u8 center_idx0, center_idx1; + + memset(&css, 0, sizeof (css)); + css.cs_count = cs_count; + css.block_tx = block_tx; + + if (*disabled) { + return hostapd_iface_try_channel_fallback(iface, ch_list, ht, vht, + sec_channel, vht_oper_chwidth, acs, disabled, 1); + } + if (hostapd_csa_in_progress(iface) || iface->cac_started) + return -1; + if (iface->state != HAPD_IFACE_ENABLED) { + return hostapd_iface_try_channel_fallback(iface, ch_list, ht, vht, + sec_channel, vht_oper_chwidth, acs, disabled, 1); + } - blobmsg_parse(csa_policy, __CSA_MAX, tb, blob_data(msg), blob_len(msg)); + for (i=0; i < ch_list->num; ++i) { + /* + * Allow selection of DFS channel in ETSI to comply with + * uniform spreading. + */ + chan = ch_list->range[i].min; + freq = hostapd_hw_get_freq(iface->bss[0], chan); + ubus_adjust_vht_center_freq(iface, chan, sec_channel, &vht_oper_chwidth, + ht, vht, ¢er_idx0, ¢er_idx1); + if (hostapd_set_freq_params(freq_params, iface->conf->hw_mode, + freq, chan, ht, vht, sec_channel, vht_oper_chwidth, + center_idx0, center_idx1, + iface->current_mode->vht_capab)) + { + wpa_printf(MSG_WARNING, "Can not build channel freq=%d, chan=%d, " + "ht=%d, vht=%d, sec_channel=%d, vht_cwidth=%d, center0=%d, " + "center1=%d", freq, chan, + ht, vht, sec_channel, vht_oper_chwidth, + center_idx0, center_idx1); + return UBUS_STATUS_INVALID_ARGUMENT; + } + if (hostapd_freq_params_compare(old, freq_params)) { + return 0; + } - if (!tb[CSA_FREQ]) - return UBUS_STATUS_INVALID_ARGUMENT; + /* Perform channel switch/CSA */ + for (k = 0; k < iface->num_bss; k++) { + err = hostapd_switch_channel(iface->bss[k], &css); + if (err) + break; + } + if (!err) { + /* Set configuration to selected channel */ + ch_list->range[i].min = ch_list->range[i].max = ch_list->range->min; + ch_list->range->min = ch_list->range->max = chan; + return hostapd_iface_try_channel_fallback(iface, ch_list, ht, vht, + sec_channel, vht_oper_chwidth, acs, disabled, 0); + } else if (!fast) { + /* In slow mode try only first channel for switch. Others - for + * ACS and DFS procedures */ + break; + } + } + if (fast) + return -1; + wpa_printf(MSG_DEBUG, "Can not perform fast switch. Use fallback method"); + return hostapd_iface_try_channel_fallback(iface, ch_list, ht, vht, + sec_channel, vht_oper_chwidth, acs, disabled, 1); +} +static int ubus_check_channel(struct hostapd_iface *iface, int n) +{ + struct hostapd_channel_data *chan = + hw_get_channel_chan(iface->current_mode, n, NULL); - memset(&css, 0, sizeof(css)); - css.freq_params.freq = blobmsg_get_u32(tb[CSA_FREQ]); + if (!chan) { + return UBUS_STATUS_INVALID_ARGUMENT; + } + if (chan->flag & HOSTAPD_CHAN_DISABLED) { + return UBUS_STATUS_NOT_SUPPORTED; + } + return 0; +} +static int blobmsg_get_ch_list(struct blob_attr *attr, struct hostapd_iface *iface, + struct wpa_freq_range_list *ch_list, int is_array, int is_channel) +{ + int val; + struct blob_attr *cur; + int rem; + int res = 0; + + memset(ch_list, 0, sizeof(*ch_list)); + if (!is_array) { + ch_list->range = os_calloc(1, sizeof(ch_list->range[0])); + val = blobmsg_get_u32(attr); + if (!is_channel) + val = hostapd_hw_get_channel(iface->bss[0], val); + ch_list->range->min = ch_list->range->max = val; + ch_list->num=1; + res = ubus_check_channel(iface, val); + } else blobmsg_for_each_attr(cur, attr, rem) { + ch_list->range = os_realloc_array(ch_list->range, ch_list->num + 1, + sizeof(ch_list->range[0])); + val = blobmsg_get_u32(cur); + ch_list->range[ch_list->num].min = ch_list->range[ch_list->num].max = + is_channel ? val : hostapd_hw_get_channel(iface->bss[0], val); + ++ch_list->num; + res = ubus_check_channel(iface, val); + if (res) + break; + } + if (!res) + return 0; -#define SET_CSA_SETTING(name, field, type) \ - do { \ - if (tb[name]) \ - css.field = blobmsg_get_ ## type(tb[name]); \ - } while(0) + os_free(ch_list->range); + ch_list->range = NULL; + ch_list->num=0; + return res; +} +static int +hostapd_do_switch_chan(struct hostapd_iface *iface, struct blob_attr *tb[], + struct hostapd_freq_params *old, int cs_count, int block_tx, int fast, + int acs, int *disabled) +{ + struct wpa_freq_range_list ch_list; + int ht = old->ht_enabled; + int vht = old->vht_enabled; + int sec_channel = old->sec_channel_offset; + int vht_oper_chwidth = ubus_bandwidth_to_vht_oper_chwidth(old->bandwidth, + old->center_freq1, old->center_freq2); + int res = 1; + + if (tb[CSA_FREQ]) { + res = blobmsg_get_ch_list(tb[CSA_FREQ], iface, &ch_list, 0, 0); + } else if (tb[CSA_CHANNEL]) { + res = blobmsg_get_ch_list(tb[CSA_CHANNEL], iface, &ch_list, 0, 1); + } else if (tb[CSA_FREQS]) { + res = blobmsg_get_ch_list(tb[CSA_FREQS], iface, &ch_list, 1, 0); + } else if (tb[CSA_CHANNELS]) { + res = blobmsg_get_ch_list(tb[CSA_CHANNELS], iface, &ch_list, 1, 1); + } + if (res) + return res; - SET_CSA_SETTING(CSA_BCN_COUNT, cs_count, u32); - SET_CSA_SETTING(CSA_CENTER_FREQ1, freq_params.center_freq1, u32); - SET_CSA_SETTING(CSA_CENTER_FREQ2, freq_params.center_freq2, u32); - SET_CSA_SETTING(CSA_BANDWIDTH, freq_params.bandwidth, u32); - SET_CSA_SETTING(CSA_SEC_CHANNEL_OFFSET, freq_params.sec_channel_offset, u32); - SET_CSA_SETTING(CSA_HT, freq_params.ht_enabled, bool); - SET_CSA_SETTING(CSA_VHT, freq_params.vht_enabled, bool); - SET_CSA_SETTING(CSA_BLOCK_TX, block_tx, bool); + if (tb[CSA_HT]) { + ht = blobmsg_get_bool(tb[CSA_HT]); + } + if (tb[CSA_VHT]) { + vht = blobmsg_get_bool(tb[CSA_VHT]); + } + if (tb[CSA_SECONDARY_CHANNEL]) { + sec_channel = blobmsg_get_u32(tb[CSA_SECONDARY_CHANNEL]); + } + if (tb[CSA_VHT_OPER_CWIDTH]) { + vht_oper_chwidth = blobmsg_get_u32(tb[CSA_VHT_OPER_CWIDTH]); + } + return hostapd_iface_try_channel(iface, old, &ch_list, ht, vht, sec_channel, + vht_oper_chwidth, cs_count, block_tx, fast, acs, disabled); +} +static int +hostapd_switch_chan(struct hostapd_iface *iface, struct blob_attr *msg) +{ + struct blob_attr *tb[__CSA_MAX]; + struct hostapd_freq_params old; + struct wpa_freq_range_list old_ch_list; + int old_acs; + int cs_count = 5, block_tx = 0, fast = 0, acs = 0; + int disabled = iface->state == HAPD_IFACE_DISABLED; + int err = UBUS_STATUS_OK; + blobmsg_parse(csa_policy, __CSA_MAX, tb, blob_data(msg), blob_len(msg)); - if (hostapd_switch_channel(hapd, &css) != 0) - return UBUS_STATUS_NOT_SUPPORTED; - return UBUS_STATUS_OK; -#undef SET_CSA_SETTING + memset(&old, 0, sizeof (old)); + hostapd_set_curr_freq_params(iface, &old, &old_acs, &old_ch_list); + + if (tb[CSA_BCN_COUNT]) + cs_count = blobmsg_get_u32(tb[CSA_BCN_COUNT]); + if (tb[CSA_BLOCK_TX]) + block_tx = blobmsg_get_bool(tb[CSA_BCN_COUNT]); + if (tb[CSA_FAST]) + fast = blobmsg_get_bool(tb[CSA_FAST]); + if (tb[CSA_ALLOW_ACS]) + acs = blobmsg_get_bool(tb[CSA_ALLOW_ACS]); + + err = hostapd_do_switch_chan(iface, tb, &old, cs_count, block_tx, fast, + acs, &disabled); + if (!err) + goto result; + if (err < 0) + err = UBUS_STATUS_NOT_SUPPORTED; + + if (!disabled) + goto result; + + hostapd_iface_try_channel_fallback_fp(iface, &old, old_acs, &old_ch_list, + &disabled, 1); + +result: + os_free(old_ch_list.range); + return err; } static int @@ -220,7 +564,86 @@ hostapd_iface_switch_chan(struct ubus_context *ctx, struct ubus_object *obj, struct hostapd_iface *iface = container_of(obj, struct hostapd_iface, ubus.obj); if (iface && iface->bss[0]) - return hostapd_switch_chan(iface->bss[0], msg); + return hostapd_switch_chan(iface, msg); + return UBUS_STATUS_INVALID_ARGUMENT; +} + +enum { + CSA_LIST, + CSA_LIST_BCN_COUNT, + CSA_LIST_BLOCK_TX, + CSA_LIST_FAST, + CSA_LIST_ALLOW_ACS, + __CSA_LIST_MAX, +}; +static const struct blobmsg_policy csa_list_policy[__CSA_LIST_MAX] = { + [CSA_LIST] = { "list", BLOBMSG_TYPE_ARRAY }, + [CSA_LIST_BCN_COUNT] = { "bcn_count", BLOBMSG_TYPE_INT32 }, + [CSA_LIST_BLOCK_TX] = { "block_tx", BLOBMSG_TYPE_BOOL }, + [CSA_LIST_FAST] = { "fast", BLOBMSG_TYPE_BOOL }, + [CSA_LIST_ALLOW_ACS] = { "allow_acs", BLOBMSG_TYPE_BOOL }, +}; + +static int +hostapd_switch_chan_list(struct hostapd_iface *iface, struct blob_attr *msg) +{ + struct blob_attr *tb_l[__CSA_LIST_MAX]; + struct blob_attr *tb[__CSA_MAX]; + struct blob_attr *cur; + struct hostapd_freq_params old; + struct wpa_freq_range_list old_ch_list; + int old_acs; + int cs_count = 5, block_tx = 0, fast = 0, acs = 0; + int disabled = iface->state == HAPD_IFACE_DISABLED; + int rem; + int err = UBUS_STATUS_OK; + + blobmsg_parse(csa_list_policy, __CSA_LIST_MAX, tb_l, + blob_data(msg), blob_len(msg)); + + if (!tb_l[CSA_LIST]) + return UBUS_STATUS_INVALID_ARGUMENT; + + hostapd_set_curr_freq_params(iface, &old, &old_acs, &old_ch_list); + + if (tb_l[CSA_LIST_BCN_COUNT]) + cs_count = blobmsg_get_u32(tb_l[CSA_LIST_BCN_COUNT]); + if (tb_l[CSA_LIST_BLOCK_TX]) + block_tx = blobmsg_get_bool(tb_l[CSA_LIST_BCN_COUNT]); + if (tb_l[CSA_LIST_FAST]) + fast = blobmsg_get_bool(tb_l[CSA_LIST_FAST]); + if (tb_l[CSA_LIST_ALLOW_ACS]) + acs = blobmsg_get_bool(tb_l[CSA_LIST_ALLOW_ACS]); + + blobmsg_for_each_attr(cur, tb_l[CSA_LIST], rem) { + blobmsg_parse(csa_policy, __CSA_MAX, tb, blobmsg_data(cur), + blobmsg_data_len(cur)); + err = hostapd_do_switch_chan(iface, tb, &old, cs_count, block_tx, fast, + acs, &disabled); + if (!err) + goto result; + } + + if (err < 0) + err = UBUS_STATUS_NOT_SUPPORTED; + if (!disabled) + goto result; + + hostapd_iface_try_channel_fallback_fp(iface, &old, old_acs, &old_ch_list, + &disabled, 1); +result: + os_free(old_ch_list.range); + return err; +} +static int +hostapd_iface_switch_chan_list(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct hostapd_iface *iface = container_of(obj, struct hostapd_iface, + ubus.obj); + if (iface && iface->bss[0]) + return hostapd_switch_chan_list(iface, msg); return UBUS_STATUS_INVALID_ARGUMENT; } #endif @@ -230,6 +653,8 @@ static const struct ubus_method iface_methods[] = { UBUS_METHOD_NOARG("get_bss", hostapd_iface_get_bss), #ifdef NEED_AP_MLME UBUS_METHOD("switch_chan", hostapd_iface_switch_chan, csa_policy), + UBUS_METHOD("switch_chan_list", hostapd_iface_switch_chan_list, + csa_list_policy), #endif }; static struct ubus_object_type iface_object_type = @@ -564,7 +989,17 @@ hostapd_bss_switch_chan(struct ubus_context *ctx, struct ubus_object *obj, { struct hostapd_data *hapd = get_hapd_from_object(obj); if (hapd) - return hostapd_switch_chan(hapd, msg); + return hostapd_switch_chan(hapd->iface, msg); + return UBUS_STATUS_INVALID_ARGUMENT; +} +static int +hostapd_bss_switch_chan_list(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct hostapd_data *hapd = get_hapd_from_object(obj); + if (hapd) + return hostapd_switch_chan_list(hapd->iface, msg); return UBUS_STATUS_INVALID_ARGUMENT; } #endif @@ -1082,6 +1517,7 @@ static const struct ubus_method bss_methods[] = { UBUS_METHOD_NOARG("get_features", hostapd_bss_get_features), #ifdef NEED_AP_MLME UBUS_METHOD("switch_chan", hostapd_bss_switch_chan, csa_policy), + UBUS_METHOD("switch_chan_list", hostapd_bss_switch_chan_list, csa_list_policy), #endif UBUS_METHOD("set_vendor_elements", hostapd_vendor_elements, ve_policy), UBUS_METHOD("notify_response", hostapd_notify_response, notify_policy),