Add nl80211 driver operation functions: hostapd_enable_tx – to enable tx on DFS channel after channel availability check. hostapd_channel_switch – to handle channel switch request. hostapd_start_radar_detection – to enable radar detection on DFS channel. Signed-hostap: Victor Goldenshtein <victorg@xxxxxx> --- src/ap/ap_config.h | 3 ++ src/ap/ap_drv_ops.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/ap/ap_drv_ops.h | 5 +++ src/ap/hostapd.h | 6 +++ src/drivers/driver.h | 48 +++++++++++++++++++++++++ 5 files changed, 157 insertions(+), 0 deletions(-) diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index bfb2d8a..c21a7a8 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -454,6 +454,9 @@ struct hostapd_config { int ieee80211d; + /* DFS */ + int channel_switch_count; + struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES]; /* diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 64c9c20..d1d9e8b 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -621,3 +621,98 @@ int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, hapd->own_addr, hapd->own_addr, data, len, 0); } + +int hostapd_enable_tx(struct hostapd_data *hapd, int freq, int flags) +{ + struct os_time now; + + if (!hapd->driver || !hapd->driver->enable_tx) + return 0; + + if ((flags & HOSTAPD_CHAN_RADAR) && + !(hapd->iface->dfs_state & DFS_ENABLED)) { + wpa_printf(MSG_ERROR, "Can't enable tx, " + "DFS functionality is not enabled"); + return -1; + } + + os_get_time(&now); + + if ((flags & HOSTAPD_CHAN_RADAR) && + now.sec - hapd->iface->dfs_start_cac_ts < DFS_MIN_CAC_TIME_SEC) { + wpa_printf(MSG_ERROR, "Can't enable tx, " + "DFS min CAC time hasn't passed"); + return -1; + } + + hapd->iface->dfs_start_cac_ts = 0; + + return hapd->driver->enable_tx(hapd->drv_priv, freq); +} + + +int hostapd_channel_switch(struct hostapd_data *hapd, int freq, int flags, + u8 tx_block, u8 post_switch_block_tx) +{ + struct hostapd_channel_switch params; + + if (!hapd->driver || !hapd->driver->hapd_channel_switch) + return 0; + + if ((flags & HOSTAPD_CHAN_RADAR) && + !(hapd->iface->dfs_state & DFS_ENABLED)) { + wpa_printf(MSG_ERROR, "Can't switch to radar channel, " + "DFS functionality is not enabled"); + return -1; + } + + if (hapd->iface->conf->secondary_channel) { + wpa_printf(MSG_ERROR, "Channel switch is not supported " + "with HT40"); + return -1; + } + + params.freq = freq; + params.tx_block = tx_block; + params.post_switch_block_tx = post_switch_block_tx; + params.ch_switch_count = hapd->iface->conf->channel_switch_count; + + return hapd->driver->hapd_channel_switch(hapd->drv_priv, ¶ms); +} + +int hostapd_start_radar_detection(struct hostapd_data *hapd, int freq, + int flags) +{ + int ret; + struct os_time now; + + if (!hapd->driver || !hapd->driver->start_radar_detection) + return 0; + + if (!(flags & HOSTAPD_CHAN_RADAR)) { + wpa_printf(MSG_ERROR, "Can't start radar detection, the channel" + " %d is not DFS channel", (int)hapd->iconf->channel); + return -1; + } + + if (!(hapd->iface->dfs_state & DFS_ENABLED)) { + wpa_printf(MSG_ERROR, "Can't start radar detection, " + "DFS functionality is not enabled"); + return -1; + } + + if (hapd->iface->conf->secondary_channel) { + wpa_printf(MSG_ERROR, "Can't start radar detection, " + "DFS functionality on HT40 is not supported"); + return -1; + } + + ret = hapd->driver->start_radar_detection(hapd->drv_priv, freq); + if (!ret) { + os_get_time(&now); + hapd->iface->dfs_start_cac_ts = now.sec; + } else + hapd->iface->dfs_start_cac_ts = 0; + + return ret; +} diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 9c53b99..f36bec1 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -97,6 +97,11 @@ int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr, int reassoc, u16 status, const u8 *ie, size_t len); int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr, u8 *tspec_ie, size_t tspec_ielen); +int hostapd_enable_tx(struct hostapd_data *hapd, int freq, int flags); +int hostapd_channel_switch(struct hostapd_data *hapd, int freq, int flags, + u8 tx_block, u8 post_switch_block_tx); +int hostapd_start_radar_detection(struct hostapd_data *hapd, int freq, + int flags); #include "drivers/driver.h" diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index f7ed311..cdd7556 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -240,6 +240,12 @@ struct hostapd_iface { int olbc_ht; u16 ht_op_mode; + + /* dfs states */ + u8 dfs_state; + /* dfs start channel availability check time stamp */ + os_time_t dfs_start_cac_ts; + void (*scan_cb)(struct hostapd_iface *iface); int (*ctrl_iface_init)(struct hostapd_data *hapd); diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 82b72cd..bc714e8 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -29,6 +29,19 @@ #define HOSTAPD_CHAN_HT40MINUS 0x00000020 #define HOSTAPD_CHAN_HT40 0x00000040 +/* + * DFS functionality is enabled. + */ +#define DFS_ENABLED BIT(0) + +/* + * DFS Channel Availability Check Time - the time a system shall monitor a + * 'radar channel' for presence of radar prior to initiating a TX, spec defines + * it as 60 seconds. + * Driver will block any attempt to enable the TX prior this minimal CAC time. + */ +#define DFS_MIN_CAC_TIME_SEC 60 + /** * struct hostapd_channel_data - Channel information */ @@ -904,6 +917,16 @@ struct hostapd_freq_params { * enabled, secondary channel above primary */ }; +struct hostapd_channel_switch { + int freq; + int tx_block; /* immediately block the tx on the + * operational channel + * (prior channel switch) */ + int post_switch_block_tx; /* block tx on the target ch (after + * channel switch) */ + int ch_switch_count; +}; + enum wpa_driver_if_type { /** * WPA_IF_STATION - Station mode interface @@ -2603,6 +2626,31 @@ struct wpa_driver_ops { * avoid frequency conflict in single channel concurrency. */ int (*switch_channel)(void *priv, unsigned int freq); + + /** + * hapd_channel_switch - Perform an AP channel switch + * @priv: Private driver interface data + * @params: Channels switch parameters + * Returns: 0 on success, -1 on failure + */ + int (*hapd_channel_switch)(void *priv, + struct hostapd_channel_switch *params); + + /** + * enable_tx - Enable TX + * @priv: Private driver interface data + * @freq: Frequency (in MHz) of the channel + * Returns: 0 on success, -1 on failure + */ + int (*enable_tx)(void *priv, int freq); + + /** + * start_radar_detection - Listen for radar interference on the channel. + * @priv: Private driver interface data + * @freq: Frequency (in MHz) of the channel + * Returns: 0 on success, -1 on failure + */ + int (*start_radar_detection)(void *priv, int freq); }; -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html