[OpenWrt-Devel] [PATCH] hostapd: add switch_chan and set_vendor_elements ubus methods

Zefir Kurtisi zefir.kurtisi at neratec.com
Fri Mar 6 04:32:45 EST 2015


Hi John,

the switch_chan() method is meant to initiate a CSA the same way hostapd would do
if it needs to escape the current operating channel. The common use-case for that
is operating on a DFS-channel that becomes unavailable after a presumed radar
detection.

Full DFS support is still WIP for hostapd, but once it is available, finding the
AP operating on a channel different from the configured one (if that was a DFS
channel) will become a common scenario.


The use case this patch is meant for is one layer above the stand-alone AP
operation provided by hostapd: the systems we are developing have dedicated
controllers that monitor and optimize frequency spectrum at runtime, which must be
able to switch channels of certain APs to adapt to environmental changes. In that
system, APs start operation on the configured channel and are taken over by the
controller for dynamic frequency allocation at runtime.

Generally, the proposed method is a shortcut to the already existing control
interface provided by hostapd (as is the one for setting vendor elements), i.e.
you replace
# hostapd_cli -p /var/run/hostapd-wlan0 chan_switch 1 5200
with
# ubus call hostapd.wlan0 switch_chan '{"freq":5200, "bcn_count":1}'

The benefit is, you do not need to implement a channel to the hostapd control
interface or spawn external shell to execute it. It might be useful for others who
want to implement active frequency spectrum management systems.


Cheers,
Zefir


On 03/06/2015 09:25 AM, John Crispin wrote:
> Hi Zefir,
> 
> if we switch the channel via ubus, then the channel specified inside uci
> and the one actually used are not consistent. could you tell us what
> your use case for this is ?
> 
> 	John
> 
> 
> On 10/02/2015 10:30, Zefir Kurtisi wrote:
>> Signed-off-by: Zefir Kurtisi <zefir.kurtisi at neratec.com>
>> ---
>>  src/ap/ubus.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 82 insertions(+)
>>
>> diff --git a/src/ap/ubus.c b/src/ap/ubus.c
>> index 1030d58..a8853a0 100644
>> --- a/src/ap/ubus.c
>> +++ b/src/ap/ubus.c
>> @@ -17,6 +17,12 @@
>>  
>>  static struct blob_buf b;
>>  
>> +static inline struct hostapd_data *get_hapd_from_object(struct ubus_object *obj)
>> +{
>> +	return container_of(obj, struct hostapd_data, ubus.obj);
>> +}
>> +
>> +
>>  struct ubus_banned_client {
>>  	struct avl_node avl;
>>  	u8 addr[ETH_ALEN];
>> @@ -234,12 +240,88 @@ hostapd_bss_wps_cancel(struct ubus_context *ctx, struct ubus_object *obj,
>>  	return 0;
>>  }
>>  
>> +enum {
>> +	CSA_FREQ,
>> +	CSA_BCN_COUNT,
>> +	__CSA_MAX
>> +};
>> +
>> +static const struct blobmsg_policy csa_policy[__CSA_MAX] = {
>> +	/*
>> +	 * for now, frequency and beacon count are enough, add more
>> +	 * parameters on demand
>> +	 */
>> +	[CSA_FREQ] = { "freq", BLOBMSG_TYPE_INT32 },
>> +	[CSA_BCN_COUNT] = { "bcn_count", BLOBMSG_TYPE_INT32 },
>> +};
>> +
>> +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)
>> +{
>> +	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]);
>> +	if (tb[CSA_BCN_COUNT])
>> +		css.cs_count = blobmsg_get_u32(tb[CSA_BCN_COUNT]);
>> +
>> +	if (hostapd_switch_channel(hapd, &css) != 0)
>> +		return UBUS_STATUS_NOT_SUPPORTED;
>> +	return UBUS_STATUS_OK;
>> +}
>> +
>> +enum {
>> +	VENDOR_ELEMENTS,
>> +	__VENDOR_ELEMENTS_MAX
>> +};
>> +
>> +static const struct blobmsg_policy ve_policy[__VENDOR_ELEMENTS_MAX] = {
>> +	/* vendor elements are provided as hex-string */
>> +	[VENDOR_ELEMENTS] = { "vendor_elements", BLOBMSG_TYPE_STRING },
>> +};
>> +
>> +static int
>> +hostapd_vendor_elements(struct ubus_context *ctx, struct ubus_object *obj,
>> +			struct ubus_request_data *req, const char *method,
>> +			struct blob_attr *msg)
>> +{
>> +	struct blob_attr *tb[__VENDOR_ELEMENTS_MAX];
>> +	struct hostapd_data *hapd = get_hapd_from_object(obj);
>> +
>> +	blobmsg_parse(ve_policy, __VENDOR_ELEMENTS_MAX, tb,
>> +		      blob_data(msg), blob_len(msg));
>> +
>> +	if (!tb[VENDOR_ELEMENTS])
>> +		return UBUS_STATUS_INVALID_ARGUMENT;
>> +
>> +	const char *vendor_elements = blobmsg_data(tb[VENDOR_ELEMENTS]);
>> +	if (hostapd_set_iface(hapd->iconf, hapd->conf, "vendor_elements",
>> +			      vendor_elements) != 0)
>> +		return UBUS_STATUS_NOT_SUPPORTED;
>> +
>> +	/* update beacons if vendor elements were set successfully */
>> +	if (ieee802_11_update_beacons(hapd->iface) != 0)
>> +		return UBUS_STATUS_NOT_SUPPORTED;
>> +	return UBUS_STATUS_OK;
>> +}
>> +
>>  static const struct ubus_method bss_methods[] = {
>>  	UBUS_METHOD_NOARG("get_clients", hostapd_bss_get_clients),
>>  	UBUS_METHOD("del_client", hostapd_bss_del_client, del_policy),
>>  	UBUS_METHOD_NOARG("list_bans", hostapd_bss_list_bans),
>>  	UBUS_METHOD_NOARG("wps_start", hostapd_bss_wps_start),
>>  	UBUS_METHOD_NOARG("wps_cancel", hostapd_bss_wps_cancel),
>> +	UBUS_METHOD("switch_chan", hostapd_switch_chan, csa_policy),
>> +	UBUS_METHOD("set_vendor_elements", hostapd_vendor_elements, ve_policy),
>>  };
>>  
>>  static struct ubus_object_type bss_object_type =
>>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel at lists.openwrt.org
> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
> 
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list