Add no_cck parameter for send_action() driver_ops

This can be used to apply the no-CCK rule conditionally depending on
which frame is being sent. The no-CCK rule applies only for P2P
management frames while SA Query and FT use cases do not have similar
restrictions.

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2011-10-29 21:49:46 +03:00
parent 970fa12ea2
commit b106173a82
10 changed files with 42 additions and 26 deletions

View file

@ -1862,6 +1862,7 @@ struct wpa_driver_ops {
* @bssid: BSSID (Address 3) * @bssid: BSSID (Address 3)
* @data: Frame body * @data: Frame body
* @data_len: data length in octets * @data_len: data length in octets
@ @no_cck: Whether CCK rates must not be used to transmit this frame
* Returns: 0 on success, -1 on failure * Returns: 0 on success, -1 on failure
* *
* This command can be used to request the driver to transmit an action * This command can be used to request the driver to transmit an action
@ -1879,7 +1880,7 @@ struct wpa_driver_ops {
*/ */
int (*send_action)(void *priv, unsigned int freq, unsigned int wait, int (*send_action)(void *priv, unsigned int freq, unsigned int wait,
const u8 *dst, const u8 *src, const u8 *bssid, const u8 *dst, const u8 *src, const u8 *bssid,
const u8 *data, size_t data_len); const u8 *data, size_t data_len, int no_cck);
/** /**
* send_action_cancel_wait - Cancel action frame TX wait * send_action_cancel_wait - Cancel action frame TX wait

View file

@ -266,7 +266,8 @@ static void nl80211_remove_monitor_interface(
struct wpa_driver_nl80211_data *drv); struct wpa_driver_nl80211_data *drv);
static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv,
unsigned int freq, unsigned int wait, unsigned int freq, unsigned int wait,
const u8 *buf, size_t buf_len, u64 *cookie); const u8 *buf, size_t buf_len, u64 *cookie,
int no_cck);
static int wpa_driver_nl80211_probe_req_report(void *priv, int report); static int wpa_driver_nl80211_probe_req_report(void *priv, int report);
#ifdef HOSTAPD #ifdef HOSTAPD
@ -4140,12 +4141,12 @@ static int wpa_driver_nl80211_send_mlme(void *priv, const u8 *data,
* of wpa_supplicant. * of wpa_supplicant.
*/ */
return nl80211_send_frame_cmd(drv, drv->last_mgmt_freq, 0, return nl80211_send_frame_cmd(drv, drv->last_mgmt_freq, 0,
data, data_len, NULL); data, data_len, NULL, 1);
} }
if (drv->no_monitor_iface_capab && is_ap_interface(drv->nlmode)) { if (drv->no_monitor_iface_capab && is_ap_interface(drv->nlmode)) {
return nl80211_send_frame_cmd(drv, drv->ap_oper_freq, 0, return nl80211_send_frame_cmd(drv, drv->ap_oper_freq, 0,
data, data_len, NULL); data, data_len, NULL, 0);
} }
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
@ -6743,7 +6744,7 @@ static int cookie_handler(struct nl_msg *msg, void *arg)
static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv, static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv,
unsigned int freq, unsigned int wait, unsigned int freq, unsigned int wait,
const u8 *buf, size_t buf_len, const u8 *buf, size_t buf_len,
u64 *cookie_out) u64 *cookie_out, int no_cck)
{ {
struct nl_msg *msg; struct nl_msg *msg;
u64 cookie; u64 cookie;
@ -6760,6 +6761,7 @@ static int nl80211_send_frame_cmd(struct wpa_driver_nl80211_data *drv,
if (wait) if (wait)
NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait); NLA_PUT_U32(msg, NL80211_ATTR_DURATION, wait);
NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK);
if (no_cck)
NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE); NLA_PUT_FLAG(msg, NL80211_ATTR_TX_NO_CCK_RATE);
NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf); NLA_PUT(msg, NL80211_ATTR_FRAME, buf_len, buf);
@ -6789,7 +6791,8 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq,
unsigned int wait_time, unsigned int wait_time,
const u8 *dst, const u8 *src, const u8 *dst, const u8 *src,
const u8 *bssid, const u8 *bssid,
const u8 *data, size_t data_len) const u8 *data, size_t data_len,
int no_cck)
{ {
struct i802_bss *bss = priv; struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv; struct wpa_driver_nl80211_data *drv = bss->drv;
@ -6798,7 +6801,7 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq,
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, " wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
"wait=%d ms)", drv->ifindex, wait_time); "wait=%d ms no_cck=%d)", drv->ifindex, wait_time, no_cck);
buf = os_zalloc(24 + data_len); buf = os_zalloc(24 + data_len);
if (buf == NULL) if (buf == NULL)
@ -6816,7 +6819,8 @@ static int wpa_driver_nl80211_send_action(void *priv, unsigned int freq,
else else
ret = nl80211_send_frame_cmd(drv, freq, wait_time, buf, ret = nl80211_send_frame_cmd(drv, freq, wait_time, buf,
24 + data_len, 24 + data_len,
&drv->send_action_cookie); &drv->send_action_cookie,
no_cck);
os_free(buf); os_free(buf);
return ret; return ret;
@ -7086,7 +7090,7 @@ static int nl80211_send_ft_action(void *priv, u8 action, const u8 *target_ap,
ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, 0, ret = wpa_driver_nl80211_send_action(bss, drv->assoc_freq, 0,
drv->bssid, own_addr, drv->bssid, drv->bssid, own_addr, drv->bssid,
data, data_len); data, data_len, 0);
os_free(data); os_free(data);
return ret; return ret;

View file

@ -116,6 +116,7 @@ struct wpa_driver_test_data {
u8 pending_action_dst[ETH_ALEN]; u8 pending_action_dst[ETH_ALEN];
u8 pending_action_bssid[ETH_ALEN]; u8 pending_action_bssid[ETH_ALEN];
unsigned int pending_action_freq; unsigned int pending_action_freq;
unsigned int pending_action_no_cck;
unsigned int pending_listen_freq; unsigned int pending_listen_freq;
unsigned int pending_listen_duration; unsigned int pending_listen_duration;
int pending_p2p_scan; int pending_p2p_scan;
@ -2670,7 +2671,8 @@ static int wpa_driver_test_send_action(void *priv, unsigned int freq,
unsigned int wait, unsigned int wait,
const u8 *dst, const u8 *src, const u8 *dst, const u8 *src,
const u8 *bssid, const u8 *bssid,
const u8 *data, size_t data_len) const u8 *data, size_t data_len,
int no_cck)
{ {
struct test_driver_bss *dbss = priv; struct test_driver_bss *dbss = priv;
struct wpa_driver_test_data *drv = dbss->drv; struct wpa_driver_test_data *drv = dbss->drv;
@ -2730,7 +2732,8 @@ static void test_send_action_cb(void *eloop_ctx, void *timeout_ctx)
drv->pending_action_src, drv->pending_action_src,
drv->pending_action_bssid, drv->pending_action_bssid,
wpabuf_head(drv->pending_action_tx), wpabuf_head(drv->pending_action_tx),
wpabuf_len(drv->pending_action_tx)); wpabuf_len(drv->pending_action_tx),
drv->pending_action_no_cck);
} }
#endif /* CONFIG_P2P */ #endif /* CONFIG_P2P */
@ -3013,6 +3016,7 @@ static int test_send_action(void *ctx, unsigned int freq, const u8 *dst,
os_memcpy(drv->pending_action_dst, dst, ETH_ALEN); os_memcpy(drv->pending_action_dst, dst, ETH_ALEN);
os_memcpy(drv->pending_action_bssid, bssid, ETH_ALEN); os_memcpy(drv->pending_action_bssid, bssid, ETH_ALEN);
drv->pending_action_freq = freq; drv->pending_action_freq = freq;
drv->pending_action_no_cck = 1;
if (drv->off_channel_freq == freq) { if (drv->off_channel_freq == freq) {
/* Already on requested channel; send immediately */ /* Already on requested channel; send immediately */

View file

@ -352,12 +352,13 @@ static inline int wpa_drv_send_action(struct wpa_supplicant *wpa_s,
unsigned int wait, unsigned int wait,
const u8 *dst, const u8 *src, const u8 *dst, const u8 *src,
const u8 *bssid, const u8 *bssid,
const u8 *data, size_t data_len) const u8 *data, size_t data_len,
int no_cck)
{ {
if (wpa_s->driver->send_action) if (wpa_s->driver->send_action)
return wpa_s->driver->send_action(wpa_s->drv_priv, freq, return wpa_s->driver->send_action(wpa_s->drv_priv, freq,
wait, dst, src, bssid, wait, dst, src, bssid,
data, data_len); data, data_len, no_cck);
return -1; return -1;
} }

View file

@ -138,7 +138,7 @@ static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query,
res = offchannel_send_action(gas->wpa_s, query->freq, query->addr, res = offchannel_send_action(gas->wpa_s, query->freq, query->addr,
gas->wpa_s->own_addr, query->addr, gas->wpa_s->own_addr, query->addr,
wpabuf_head(req), wpabuf_len(req), 1000, wpabuf_head(req), wpabuf_len(req), 1000,
NULL); NULL, 0);
if (res == 0) if (res == 0)
query->offchannel_tx_started = 1; query->offchannel_tx_started = 1;
return res; return res;

View file

@ -120,7 +120,8 @@ static void wpas_send_action_cb(void *eloop_ctx, void *timeout_ctx)
wpa_s->pending_action_src, wpa_s->pending_action_src,
wpa_s->pending_action_bssid, wpa_s->pending_action_bssid,
wpabuf_head(wpa_s->pending_action_tx), wpabuf_head(wpa_s->pending_action_tx),
wpabuf_len(wpa_s->pending_action_tx)); wpabuf_len(wpa_s->pending_action_tx),
wpa_s->pending_action_no_cck);
if (res) { if (res) {
wpa_printf(MSG_DEBUG, "Off-channel: Failed to send the " wpa_printf(MSG_DEBUG, "Off-channel: Failed to send the "
"pending Action frame"); "pending Action frame");
@ -177,7 +178,8 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
const u8 *src, const u8 *bssid, const u8 *src, const u8 *bssid,
const u8 *data, size_t data_len, const u8 *data, size_t data_len,
enum offchannel_send_action_result enum offchannel_send_action_result
result)) result),
int no_cck)
{ {
wpa_printf(MSG_DEBUG, "Off-channel: Send action frame: freq=%d dst=" wpa_printf(MSG_DEBUG, "Off-channel: Send action frame: freq=%d dst="
MACSTR " src=" MACSTR " bssid=" MACSTR " len=%d", MACSTR " src=" MACSTR " bssid=" MACSTR " len=%d",
@ -204,6 +206,7 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
os_memcpy(wpa_s->pending_action_dst, dst, ETH_ALEN); os_memcpy(wpa_s->pending_action_dst, dst, ETH_ALEN);
os_memcpy(wpa_s->pending_action_bssid, bssid, ETH_ALEN); os_memcpy(wpa_s->pending_action_bssid, bssid, ETH_ALEN);
wpa_s->pending_action_freq = freq; wpa_s->pending_action_freq = freq;
wpa_s->pending_action_no_cck = no_cck;
if (freq != 0 && wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) { if (freq != 0 && wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) {
struct wpa_supplicant *iface; struct wpa_supplicant *iface;
@ -212,12 +215,13 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
wpa_s->pending_action_src); wpa_s->pending_action_src);
wpa_s->action_tx_wait_time = wait_time; wpa_s->action_tx_wait_time = wait_time;
return wpa_drv_send_action(iface, wpa_s->pending_action_freq, return wpa_drv_send_action(
iface, wpa_s->pending_action_freq,
wait_time, wpa_s->pending_action_dst, wait_time, wpa_s->pending_action_dst,
wpa_s->pending_action_src, wpa_s->pending_action_src, wpa_s->pending_action_bssid,
wpa_s->pending_action_bssid,
wpabuf_head(wpa_s->pending_action_tx), wpabuf_head(wpa_s->pending_action_tx),
wpabuf_len(wpa_s->pending_action_tx)); wpabuf_len(wpa_s->pending_action_tx),
wpa_s->pending_action_no_cck);
} }
if (freq) { if (freq) {

View file

@ -24,7 +24,8 @@ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq,
const u8 *src, const u8 *bssid, const u8 *src, const u8 *bssid,
const u8 *data, size_t data_len, const u8 *data, size_t data_len,
enum offchannel_send_action_result enum offchannel_send_action_result
result)); result),
int no_cck);
void offchannel_send_action_done(struct wpa_supplicant *wpa_s); void offchannel_send_action_done(struct wpa_supplicant *wpa_s);
void offchannel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, void offchannel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
unsigned int freq, unsigned int duration); unsigned int freq, unsigned int duration);

View file

@ -593,7 +593,7 @@ static int wpas_send_action(void *ctx, unsigned int freq, const u8 *dst,
struct wpa_supplicant *wpa_s = ctx; struct wpa_supplicant *wpa_s = ctx;
return offchannel_send_action(wpa_s, freq, dst, src, bssid, buf, len, return offchannel_send_action(wpa_s, freq, dst, src, bssid, buf, len,
wait_time, wait_time,
wpas_p2p_send_action_tx_status); wpas_p2p_send_action_tx_status, 1);
} }

View file

@ -647,7 +647,7 @@ static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN); os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
wpa_s->own_addr, wpa_s->bssid, wpa_s->own_addr, wpa_s->bssid,
req, sizeof(req)) < 0) req, sizeof(req), 0) < 0)
wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query " wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
"Request"); "Request");
} }

View file

@ -406,6 +406,7 @@ struct wpa_supplicant {
u8 pending_action_dst[ETH_ALEN]; u8 pending_action_dst[ETH_ALEN];
u8 pending_action_bssid[ETH_ALEN]; u8 pending_action_bssid[ETH_ALEN];
unsigned int pending_action_freq; unsigned int pending_action_freq;
int pending_action_no_cck;
int pending_action_without_roc; int pending_action_without_roc;
void (*pending_action_tx_status_cb)(struct wpa_supplicant *wpa_s, void (*pending_action_tx_status_cb)(struct wpa_supplicant *wpa_s,
unsigned int freq, const u8 *dst, unsigned int freq, const u8 *dst,