FST: Add the Fast Session Transfer (FST) module
Fast Session Transfer (FST) is the transfer of a session from a channel
to another channel in a different frequency band. The term "session"
refers to non-physical layer state information kept by a pair of
stations (STAs) that communicate directly (i.e., excludes forwarding).
The FST is implemented in accordance with IEEE Std 802.11ad-2012.
Definitions
* FST interface - an interface for which FST functionality is enabled
* FST group - a bunch of FST interfaces representing single
multi-band STA
* FST peer - a multi-band capable STA connected
* FST module - multi-band operation functionality implemented in
accordance with IEEE Std 802.11ad-2012 (see 10.32
Multi-band operation) as a part of hostapd/wpa_supplicant
* FST manager - an external application that implements custom FST
related logic, using the FST module's interfaces
accessible via CLI or D-Bus
This commit introduces only the FST module. Integration of the FST
module into the hostapd/wpa_supplicant and corresponding CLI/D-Bus
interfaces and FST related tests are covered in separate commits.
FST manager application is out of scope of these commits.
As FST aggregates a few interfaces into FST group, the FST module uses
global CLI for both commands and notifications. It also exposes
alternative non-interface based D-Bus subtree for this purposes.
Configuration and Initialization
* FST functionality can enabled by compilation flag (CONFIG_FST)
* hostapd/wpa_supplicant controlling multiple interfaces are used for
FST
* once enabled by compilation, the FST can be enabled for specific
interfaces in the configuration files
* FST interfaces are aggregated in FST groups (fst_group_id config file
entry), where each FST group:
- represents one multi-band device
- should have two or more FST interfaces in it
* priority (fst_priority config file entry) must be configured for each
FST interface. FST interface with higher priority is the interface FST
will always try to switch to. Thus, for example, for the maximal
throughput, it should be the fastest FST interface in the FST setup.
* default Link Loss Timeout (LLT) value can be configured for each FST
interface (fst_llt config file entry). It represents LLT to be used
by FST when this interface is active.
* FST interfaces advertise the Multi-band capability by including the
Multi-band element in the corresponding frames
FST CLI commands:
* fst list_groups - list FST groups configured.
* fst list_ifaces - list FST interfaces which belong to specific group
* fst iface_peers - list Multi-Band STAs connected to specific interface
* fst list_sessions - list existing FST sessions
* fst session_get - get FST session info
* fst session_add - create FST session object
* fst session_set - set FST session parameters (old_iface, new_iface,
peer_addr, llt)
* fst session_initiate - initiate FST setup
* fst session_respond - respond to FST setup establishemnt attempt by
counterpart
* fst session_transfer - initiate FST switch
* fst session_teardown - tear down FST Setup but leave the session object
for reuse
* fst session_remove - remove FST session object
FST CLI notifications:
* FST-EVENT-PEER - peer state changed (CONNECT/DISCONNECT)
* FST-EVENT-SESSION - FST session level notification with following
sub-events:
- EVENT_FST_SESSION_STATE - FST session state changed
- EVENT_FST_ESTABLISHED - previously initiated FST session became
established
- EVENT_FST_SETUP - new FST session object created due to FST session
negotiation attempt by counterpart
All the FST CLI commands and notifications are also implemented on D-Bus
for wpa_supplicant.
IEEE 802.11 standard compliance
FST module implements FST setup statemachine in compliance with IEEE
802.11ad (P802.11-REVmc/D3.3), as it described in 10.32 Multi-band
operation (see also Figure 10-34 - States of the FST setup protocol).
Thus, for example, the FST module initiates FST switch automatically
when FST setup becomes established with LLT=0 in accordance with
10.32.2.2 Transitioning between states.
At the moment, FST module only supports non-transparent STA-based FST
(see 10.32.1 General).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2015-02-18 15:59:21 +01:00
|
|
|
/*
|
|
|
|
* FST module - Control Interface implementation
|
|
|
|
* Copyright (c) 2014, Qualcomm Atheros, Inc.
|
|
|
|
*
|
|
|
|
* This software may be distributed under the terms of the BSD license.
|
|
|
|
* See README for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "utils/includes.h"
|
|
|
|
#include "utils/common.h"
|
|
|
|
#include "common/defs.h"
|
|
|
|
#include "list.h"
|
|
|
|
#include "fst/fst.h"
|
|
|
|
#include "fst/fst_internal.h"
|
|
|
|
#include "fst_ctrl_defs.h"
|
|
|
|
#include "fst_ctrl_iface.h"
|
|
|
|
|
|
|
|
|
|
|
|
static struct fst_group * get_fst_group_by_id(const char *id)
|
|
|
|
{
|
|
|
|
struct fst_group *g;
|
|
|
|
|
|
|
|
foreach_fst_group(g) {
|
|
|
|
const char *group_id = fst_group_get_id(g);
|
|
|
|
|
|
|
|
if (os_strncmp(group_id, id, os_strlen(group_id)) == 0)
|
|
|
|
return g;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* notifications */
|
2015-07-18 11:40:23 +02:00
|
|
|
static Boolean format_session_state_extra(const union fst_event_extra *extra,
|
|
|
|
char *buffer, size_t size)
|
FST: Add the Fast Session Transfer (FST) module
Fast Session Transfer (FST) is the transfer of a session from a channel
to another channel in a different frequency band. The term "session"
refers to non-physical layer state information kept by a pair of
stations (STAs) that communicate directly (i.e., excludes forwarding).
The FST is implemented in accordance with IEEE Std 802.11ad-2012.
Definitions
* FST interface - an interface for which FST functionality is enabled
* FST group - a bunch of FST interfaces representing single
multi-band STA
* FST peer - a multi-band capable STA connected
* FST module - multi-band operation functionality implemented in
accordance with IEEE Std 802.11ad-2012 (see 10.32
Multi-band operation) as a part of hostapd/wpa_supplicant
* FST manager - an external application that implements custom FST
related logic, using the FST module's interfaces
accessible via CLI or D-Bus
This commit introduces only the FST module. Integration of the FST
module into the hostapd/wpa_supplicant and corresponding CLI/D-Bus
interfaces and FST related tests are covered in separate commits.
FST manager application is out of scope of these commits.
As FST aggregates a few interfaces into FST group, the FST module uses
global CLI for both commands and notifications. It also exposes
alternative non-interface based D-Bus subtree for this purposes.
Configuration and Initialization
* FST functionality can enabled by compilation flag (CONFIG_FST)
* hostapd/wpa_supplicant controlling multiple interfaces are used for
FST
* once enabled by compilation, the FST can be enabled for specific
interfaces in the configuration files
* FST interfaces are aggregated in FST groups (fst_group_id config file
entry), where each FST group:
- represents one multi-band device
- should have two or more FST interfaces in it
* priority (fst_priority config file entry) must be configured for each
FST interface. FST interface with higher priority is the interface FST
will always try to switch to. Thus, for example, for the maximal
throughput, it should be the fastest FST interface in the FST setup.
* default Link Loss Timeout (LLT) value can be configured for each FST
interface (fst_llt config file entry). It represents LLT to be used
by FST when this interface is active.
* FST interfaces advertise the Multi-band capability by including the
Multi-band element in the corresponding frames
FST CLI commands:
* fst list_groups - list FST groups configured.
* fst list_ifaces - list FST interfaces which belong to specific group
* fst iface_peers - list Multi-Band STAs connected to specific interface
* fst list_sessions - list existing FST sessions
* fst session_get - get FST session info
* fst session_add - create FST session object
* fst session_set - set FST session parameters (old_iface, new_iface,
peer_addr, llt)
* fst session_initiate - initiate FST setup
* fst session_respond - respond to FST setup establishemnt attempt by
counterpart
* fst session_transfer - initiate FST switch
* fst session_teardown - tear down FST Setup but leave the session object
for reuse
* fst session_remove - remove FST session object
FST CLI notifications:
* FST-EVENT-PEER - peer state changed (CONNECT/DISCONNECT)
* FST-EVENT-SESSION - FST session level notification with following
sub-events:
- EVENT_FST_SESSION_STATE - FST session state changed
- EVENT_FST_ESTABLISHED - previously initiated FST session became
established
- EVENT_FST_SETUP - new FST session object created due to FST session
negotiation attempt by counterpart
All the FST CLI commands and notifications are also implemented on D-Bus
for wpa_supplicant.
IEEE 802.11 standard compliance
FST module implements FST setup statemachine in compliance with IEEE
802.11ad (P802.11-REVmc/D3.3), as it described in 10.32 Multi-band
operation (see also Figure 10-34 - States of the FST setup protocol).
Thus, for example, the FST module initiates FST switch automatically
when FST setup becomes established with LLT=0 in accordance with
10.32.2.2 Transitioning between states.
At the moment, FST module only supports non-transparent STA-based FST
(see 10.32.1 General).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2015-02-18 15:59:21 +01:00
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char reject_str[32] = FST_CTRL_PVAL_NONE;
|
|
|
|
const char *initiator = FST_CTRL_PVAL_NONE;
|
|
|
|
const struct fst_event_extra_session_state *ss;
|
|
|
|
|
|
|
|
ss = &extra->session_state;
|
|
|
|
if (ss->new_state != FST_SESSION_STATE_INITIAL)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
switch (ss->extra.to_initial.reason) {
|
|
|
|
case REASON_REJECT:
|
|
|
|
if (ss->extra.to_initial.reject_code != WLAN_STATUS_SUCCESS)
|
|
|
|
os_snprintf(reject_str, sizeof(reject_str), "%u",
|
|
|
|
ss->extra.to_initial.reject_code);
|
|
|
|
/* no break */
|
|
|
|
case REASON_TEARDOWN:
|
|
|
|
case REASON_SWITCH:
|
|
|
|
switch (ss->extra.to_initial.initiator) {
|
|
|
|
case FST_INITIATOR_LOCAL:
|
|
|
|
initiator = FST_CS_PVAL_INITIATOR_LOCAL;
|
|
|
|
break;
|
|
|
|
case FST_INITIATOR_REMOTE:
|
|
|
|
initiator = FST_CS_PVAL_INITIATOR_REMOTE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = os_snprintf(buffer, size,
|
|
|
|
FST_CES_PNAME_REASON "=%s "
|
|
|
|
FST_CES_PNAME_REJECT_CODE "=%s "
|
|
|
|
FST_CES_PNAME_INITIATOR "=%s",
|
|
|
|
fst_reason_name(ss->extra.to_initial.reason),
|
|
|
|
reject_str, initiator);
|
|
|
|
|
|
|
|
return !os_snprintf_error(size, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void fst_ctrl_iface_notify(u32 session_id,
|
|
|
|
enum fst_event_type event_type,
|
|
|
|
const union fst_event_extra *extra)
|
|
|
|
{
|
|
|
|
struct fst_group *g;
|
|
|
|
struct fst_iface *f;
|
|
|
|
char extra_str[128] = "";
|
|
|
|
const struct fst_event_extra_session_state *ss;
|
|
|
|
const struct fst_event_extra_iface_state *is;
|
|
|
|
const struct fst_event_extra_peer_state *ps;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FST can use any of interface objects as it only sends messages
|
|
|
|
* on global Control Interface, so we just pick the 1st one.
|
|
|
|
*/
|
|
|
|
|
|
|
|
g = fst_first_group();
|
|
|
|
if (!g)
|
|
|
|
return;
|
|
|
|
|
|
|
|
f = fst_group_first_iface(g);
|
|
|
|
if (!f)
|
|
|
|
return;
|
|
|
|
|
|
|
|
WPA_ASSERT(f->iface_obj.ctx);
|
|
|
|
|
|
|
|
switch (event_type) {
|
|
|
|
case EVENT_FST_IFACE_STATE_CHANGED:
|
|
|
|
if (!extra)
|
|
|
|
return;
|
|
|
|
is = &extra->iface_state;
|
|
|
|
wpa_msg_global_only(f->iface_obj.ctx, MSG_INFO,
|
|
|
|
FST_CTRL_EVENT_IFACE " %s "
|
|
|
|
FST_CEI_PNAME_IFNAME "=%s "
|
|
|
|
FST_CEI_PNAME_GROUP "=%s",
|
|
|
|
is->attached ? FST_CEI_PNAME_ATTACHED :
|
|
|
|
FST_CEI_PNAME_DETACHED,
|
|
|
|
is->ifname, is->group_id);
|
|
|
|
break;
|
|
|
|
case EVENT_PEER_STATE_CHANGED:
|
|
|
|
if (!extra)
|
|
|
|
return;
|
|
|
|
ps = &extra->peer_state;
|
|
|
|
wpa_msg_global_only(fst_iface_get_wpa_obj_ctx(f), MSG_INFO,
|
|
|
|
FST_CTRL_EVENT_PEER " %s "
|
|
|
|
FST_CEP_PNAME_IFNAME "=%s "
|
|
|
|
FST_CEP_PNAME_ADDR "=" MACSTR,
|
|
|
|
ps->connected ? FST_CEP_PNAME_CONNECTED :
|
|
|
|
FST_CEP_PNAME_DISCONNECTED,
|
|
|
|
ps->ifname, MAC2STR(ps->addr));
|
|
|
|
break;
|
|
|
|
case EVENT_FST_SESSION_STATE_CHANGED:
|
|
|
|
if (!extra)
|
|
|
|
return;
|
|
|
|
if (!format_session_state_extra(extra, extra_str,
|
|
|
|
sizeof(extra_str))) {
|
|
|
|
fst_printf(MSG_ERROR,
|
|
|
|
"CTRL: Cannot format STATE_CHANGE extra");
|
|
|
|
extra_str[0] = 0;
|
|
|
|
}
|
|
|
|
ss = &extra->session_state;
|
|
|
|
wpa_msg_global_only(fst_iface_get_wpa_obj_ctx(f), MSG_INFO,
|
|
|
|
FST_CTRL_EVENT_SESSION " "
|
|
|
|
FST_CES_PNAME_SESSION_ID "=%u "
|
|
|
|
FST_CES_PNAME_EVT_TYPE "=%s "
|
|
|
|
FST_CES_PNAME_OLD_STATE "=%s "
|
|
|
|
FST_CES_PNAME_NEW_STATE "=%s %s",
|
|
|
|
session_id,
|
|
|
|
fst_session_event_type_name(event_type),
|
|
|
|
fst_session_state_name(ss->old_state),
|
|
|
|
fst_session_state_name(ss->new_state),
|
|
|
|
extra_str);
|
|
|
|
break;
|
|
|
|
case EVENT_FST_ESTABLISHED:
|
|
|
|
case EVENT_FST_SETUP:
|
|
|
|
wpa_msg_global_only(fst_iface_get_wpa_obj_ctx(f), MSG_INFO,
|
|
|
|
FST_CTRL_EVENT_SESSION " "
|
|
|
|
FST_CES_PNAME_SESSION_ID "=%u "
|
|
|
|
FST_CES_PNAME_EVT_TYPE "=%s",
|
|
|
|
session_id,
|
|
|
|
fst_session_event_type_name(event_type));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* command processors */
|
|
|
|
|
|
|
|
/* fst session_get */
|
|
|
|
static int session_get(const char *session_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_session *s;
|
|
|
|
struct fst_iface *new_iface, *old_iface;
|
|
|
|
const u8 *old_peer_addr, *new_peer_addr;
|
|
|
|
u32 id;
|
|
|
|
|
|
|
|
id = strtoul(session_id, NULL, 0);
|
|
|
|
|
|
|
|
s = fst_session_get_by_id(id);
|
|
|
|
if (!s) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
old_peer_addr = fst_session_get_peer_addr(s, TRUE);
|
|
|
|
new_peer_addr = fst_session_get_peer_addr(s, FALSE);
|
|
|
|
new_iface = fst_session_get_iface(s, FALSE);
|
|
|
|
old_iface = fst_session_get_iface(s, TRUE);
|
|
|
|
|
|
|
|
return os_snprintf(buf, buflen,
|
|
|
|
FST_CSG_PNAME_OLD_PEER_ADDR "=" MACSTR "\n"
|
|
|
|
FST_CSG_PNAME_NEW_PEER_ADDR "=" MACSTR "\n"
|
|
|
|
FST_CSG_PNAME_NEW_IFNAME "=%s\n"
|
|
|
|
FST_CSG_PNAME_OLD_IFNAME "=%s\n"
|
|
|
|
FST_CSG_PNAME_LLT "=%u\n"
|
|
|
|
FST_CSG_PNAME_STATE "=%s\n",
|
|
|
|
MAC2STR(old_peer_addr),
|
|
|
|
MAC2STR(new_peer_addr),
|
|
|
|
new_iface ? fst_iface_get_name(new_iface) :
|
|
|
|
FST_CTRL_PVAL_NONE,
|
|
|
|
old_iface ? fst_iface_get_name(old_iface) :
|
|
|
|
FST_CTRL_PVAL_NONE,
|
|
|
|
fst_session_get_llt(s),
|
|
|
|
fst_session_state_name(fst_session_get_state(s)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst session_set */
|
|
|
|
static int session_set(const char *session_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_session *s;
|
|
|
|
char *p, *q;
|
|
|
|
u32 id;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
id = strtoul(session_id, &p, 0);
|
|
|
|
|
|
|
|
s = fst_session_get_by_id(id);
|
|
|
|
if (!s) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p != ' ' || !(q = os_strchr(p + 1, '=')))
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
p++;
|
|
|
|
|
|
|
|
if (os_strncasecmp(p, FST_CSS_PNAME_OLD_IFNAME, q - p) == 0) {
|
|
|
|
ret = fst_session_set_str_ifname(s, q + 1, TRUE);
|
|
|
|
} else if (os_strncasecmp(p, FST_CSS_PNAME_NEW_IFNAME, q - p) == 0) {
|
|
|
|
ret = fst_session_set_str_ifname(s, q + 1, FALSE);
|
|
|
|
} else if (os_strncasecmp(p, FST_CSS_PNAME_OLD_PEER_ADDR, q - p) == 0) {
|
|
|
|
ret = fst_session_set_str_peer_addr(s, q + 1, TRUE);
|
|
|
|
} else if (os_strncasecmp(p, FST_CSS_PNAME_NEW_PEER_ADDR, q - p) == 0) {
|
|
|
|
ret = fst_session_set_str_peer_addr(s, q + 1, FALSE);
|
|
|
|
} else if (os_strncasecmp(p, FST_CSS_PNAME_LLT, q - p) == 0) {
|
|
|
|
ret = fst_session_set_str_llt(s, q + 1);
|
|
|
|
} else {
|
|
|
|
fst_printf(MSG_ERROR, "CTRL: Unknown parameter: %s", p);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return os_snprintf(buf, buflen, "%s\n", ret ? "FAIL" : "OK");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst session_add/remove */
|
|
|
|
static int session_add(const char *group_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_group *g;
|
|
|
|
struct fst_session *s;
|
|
|
|
|
|
|
|
g = get_fst_group_by_id(group_id);
|
|
|
|
if (!g) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find group '%s'",
|
|
|
|
group_id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
s = fst_session_create(g);
|
|
|
|
if (!s) {
|
|
|
|
fst_printf(MSG_ERROR,
|
|
|
|
"CTRL: Cannot create session for group '%s'",
|
|
|
|
group_id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return os_snprintf(buf, buflen, "%u\n", fst_session_get_id(s));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int session_remove(const char *session_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_session *s;
|
|
|
|
struct fst_group *g;
|
|
|
|
u32 id;
|
|
|
|
|
|
|
|
id = strtoul(session_id, NULL, 0);
|
|
|
|
|
|
|
|
s = fst_session_get_by_id(id);
|
|
|
|
if (!s) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
g = fst_session_get_group(s);
|
|
|
|
fst_session_reset(s);
|
|
|
|
fst_session_delete(s);
|
|
|
|
fst_group_delete_if_empty(g);
|
|
|
|
|
|
|
|
return os_snprintf(buf, buflen, "OK\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst session_initiate */
|
|
|
|
static int session_initiate(const char *session_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_session *s;
|
|
|
|
u32 id;
|
|
|
|
|
|
|
|
id = strtoul(session_id, NULL, 0);
|
|
|
|
|
|
|
|
s = fst_session_get_by_id(id);
|
|
|
|
if (!s) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fst_session_initiate_setup(s)) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot initiate session %u", id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return os_snprintf(buf, buflen, "OK\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst session_respond */
|
|
|
|
static int session_respond(const char *session_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_session *s;
|
|
|
|
char *p;
|
|
|
|
u32 id;
|
|
|
|
u8 status_code;
|
|
|
|
|
|
|
|
id = strtoul(session_id, &p, 0);
|
|
|
|
|
|
|
|
s = fst_session_get_by_id(id);
|
|
|
|
if (!s) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*p != ' ')
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
p++;
|
|
|
|
|
|
|
|
if (!os_strcasecmp(p, FST_CS_PVAL_RESPONSE_ACCEPT)) {
|
|
|
|
status_code = WLAN_STATUS_SUCCESS;
|
|
|
|
} else if (!os_strcasecmp(p, FST_CS_PVAL_RESPONSE_REJECT)) {
|
|
|
|
status_code = WLAN_STATUS_PENDING_ADMITTING_FST_SESSION;
|
|
|
|
} else {
|
|
|
|
fst_printf(MSG_WARNING,
|
|
|
|
"CTRL: session %u: unknown response status: %s",
|
|
|
|
id, p);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fst_session_respond(s, status_code)) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot respond to session %u",
|
|
|
|
id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
fst_printf(MSG_INFO, "CTRL: session %u responded", id);
|
|
|
|
|
|
|
|
return os_snprintf(buf, buflen, "OK\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst session_transfer */
|
|
|
|
static int session_transfer(const char *session_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_session *s;
|
|
|
|
u32 id;
|
|
|
|
|
|
|
|
id = strtoul(session_id, NULL, 0);
|
|
|
|
|
|
|
|
s = fst_session_get_by_id(id);
|
|
|
|
if (!s) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fst_session_initiate_switch(s)) {
|
|
|
|
fst_printf(MSG_WARNING,
|
|
|
|
"CTRL: Cannot initiate ST for session %u", id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return os_snprintf(buf, buflen, "OK\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst session_teardown */
|
|
|
|
static int session_teardown(const char *session_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_session *s;
|
|
|
|
u32 id;
|
|
|
|
|
|
|
|
id = strtoul(session_id, NULL, 0);
|
|
|
|
|
|
|
|
s = fst_session_get_by_id(id);
|
|
|
|
if (!s) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find session %u", id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fst_session_tear_down_setup(s)) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot tear down session %u",
|
|
|
|
id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return os_snprintf(buf, buflen, "OK\n");
|
|
|
|
}
|
|
|
|
|
2014-12-04 18:20:56 +01:00
|
|
|
|
|
|
|
#ifdef CONFIG_FST_TEST
|
|
|
|
/* fst test_request */
|
|
|
|
static int test_request(const char *request, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
const char *p = request;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!os_strncasecmp(p, FST_CTR_SEND_SETUP_REQUEST,
|
|
|
|
os_strlen(FST_CTR_SEND_SETUP_REQUEST))) {
|
|
|
|
ret = fst_test_req_send_fst_request(
|
|
|
|
p + os_strlen(FST_CTR_SEND_SETUP_REQUEST));
|
|
|
|
} else if (!os_strncasecmp(p, FST_CTR_SEND_SETUP_RESPONSE,
|
|
|
|
os_strlen(FST_CTR_SEND_SETUP_RESPONSE))) {
|
|
|
|
ret = fst_test_req_send_fst_response(
|
|
|
|
p + os_strlen(FST_CTR_SEND_SETUP_RESPONSE));
|
|
|
|
} else if (!os_strncasecmp(p, FST_CTR_SEND_ACK_REQUEST,
|
|
|
|
os_strlen(FST_CTR_SEND_ACK_REQUEST))) {
|
|
|
|
ret = fst_test_req_send_ack_request(
|
|
|
|
p + os_strlen(FST_CTR_SEND_ACK_REQUEST));
|
|
|
|
} else if (!os_strncasecmp(p, FST_CTR_SEND_ACK_RESPONSE,
|
|
|
|
os_strlen(FST_CTR_SEND_ACK_RESPONSE))) {
|
|
|
|
ret = fst_test_req_send_ack_response(
|
|
|
|
p + os_strlen(FST_CTR_SEND_ACK_RESPONSE));
|
|
|
|
} else if (!os_strncasecmp(p, FST_CTR_SEND_TEAR_DOWN,
|
|
|
|
os_strlen(FST_CTR_SEND_TEAR_DOWN))) {
|
|
|
|
ret = fst_test_req_send_tear_down(
|
|
|
|
p + os_strlen(FST_CTR_SEND_TEAR_DOWN));
|
|
|
|
} else if (!os_strncasecmp(p, FST_CTR_GET_FSTS_ID,
|
|
|
|
os_strlen(FST_CTR_GET_FSTS_ID))) {
|
|
|
|
u32 fsts_id = fst_test_req_get_fsts_id(
|
|
|
|
p + os_strlen(FST_CTR_GET_FSTS_ID));
|
|
|
|
if (fsts_id != FST_FSTS_ID_NOT_FOUND)
|
|
|
|
return os_snprintf(buf, buflen, "%u\n", fsts_id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
} else if (!os_strncasecmp(p, FST_CTR_GET_LOCAL_MBIES,
|
|
|
|
os_strlen(FST_CTR_GET_LOCAL_MBIES))) {
|
|
|
|
return fst_test_req_get_local_mbies(
|
|
|
|
p + os_strlen(FST_CTR_GET_LOCAL_MBIES), buf, buflen);
|
|
|
|
} else if (!os_strncasecmp(p, FST_CTR_IS_SUPPORTED,
|
|
|
|
os_strlen(FST_CTR_IS_SUPPORTED))) {
|
|
|
|
ret = 0;
|
|
|
|
} else {
|
|
|
|
fst_printf(MSG_ERROR, "CTRL: Unknown parameter: %s", p);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
return os_snprintf(buf, buflen, "%s\n", ret ? "FAIL" : "OK");
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_FST_TEST */
|
|
|
|
|
|
|
|
|
FST: Add the Fast Session Transfer (FST) module
Fast Session Transfer (FST) is the transfer of a session from a channel
to another channel in a different frequency band. The term "session"
refers to non-physical layer state information kept by a pair of
stations (STAs) that communicate directly (i.e., excludes forwarding).
The FST is implemented in accordance with IEEE Std 802.11ad-2012.
Definitions
* FST interface - an interface for which FST functionality is enabled
* FST group - a bunch of FST interfaces representing single
multi-band STA
* FST peer - a multi-band capable STA connected
* FST module - multi-band operation functionality implemented in
accordance with IEEE Std 802.11ad-2012 (see 10.32
Multi-band operation) as a part of hostapd/wpa_supplicant
* FST manager - an external application that implements custom FST
related logic, using the FST module's interfaces
accessible via CLI or D-Bus
This commit introduces only the FST module. Integration of the FST
module into the hostapd/wpa_supplicant and corresponding CLI/D-Bus
interfaces and FST related tests are covered in separate commits.
FST manager application is out of scope of these commits.
As FST aggregates a few interfaces into FST group, the FST module uses
global CLI for both commands and notifications. It also exposes
alternative non-interface based D-Bus subtree for this purposes.
Configuration and Initialization
* FST functionality can enabled by compilation flag (CONFIG_FST)
* hostapd/wpa_supplicant controlling multiple interfaces are used for
FST
* once enabled by compilation, the FST can be enabled for specific
interfaces in the configuration files
* FST interfaces are aggregated in FST groups (fst_group_id config file
entry), where each FST group:
- represents one multi-band device
- should have two or more FST interfaces in it
* priority (fst_priority config file entry) must be configured for each
FST interface. FST interface with higher priority is the interface FST
will always try to switch to. Thus, for example, for the maximal
throughput, it should be the fastest FST interface in the FST setup.
* default Link Loss Timeout (LLT) value can be configured for each FST
interface (fst_llt config file entry). It represents LLT to be used
by FST when this interface is active.
* FST interfaces advertise the Multi-band capability by including the
Multi-band element in the corresponding frames
FST CLI commands:
* fst list_groups - list FST groups configured.
* fst list_ifaces - list FST interfaces which belong to specific group
* fst iface_peers - list Multi-Band STAs connected to specific interface
* fst list_sessions - list existing FST sessions
* fst session_get - get FST session info
* fst session_add - create FST session object
* fst session_set - set FST session parameters (old_iface, new_iface,
peer_addr, llt)
* fst session_initiate - initiate FST setup
* fst session_respond - respond to FST setup establishemnt attempt by
counterpart
* fst session_transfer - initiate FST switch
* fst session_teardown - tear down FST Setup but leave the session object
for reuse
* fst session_remove - remove FST session object
FST CLI notifications:
* FST-EVENT-PEER - peer state changed (CONNECT/DISCONNECT)
* FST-EVENT-SESSION - FST session level notification with following
sub-events:
- EVENT_FST_SESSION_STATE - FST session state changed
- EVENT_FST_ESTABLISHED - previously initiated FST session became
established
- EVENT_FST_SETUP - new FST session object created due to FST session
negotiation attempt by counterpart
All the FST CLI commands and notifications are also implemented on D-Bus
for wpa_supplicant.
IEEE 802.11 standard compliance
FST module implements FST setup statemachine in compliance with IEEE
802.11ad (P802.11-REVmc/D3.3), as it described in 10.32 Multi-band
operation (see also Figure 10-34 - States of the FST setup protocol).
Thus, for example, the FST module initiates FST switch automatically
when FST setup becomes established with LLT=0 in accordance with
10.32.2.2 Transitioning between states.
At the moment, FST module only supports non-transparent STA-based FST
(see 10.32.1 General).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2015-02-18 15:59:21 +01:00
|
|
|
/* fst list_sessions */
|
|
|
|
struct list_sessions_cb_ctx {
|
|
|
|
char *buf;
|
|
|
|
size_t buflen;
|
|
|
|
size_t reply_len;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void list_session_enum_cb(struct fst_group *g, struct fst_session *s,
|
|
|
|
void *ctx)
|
|
|
|
{
|
|
|
|
struct list_sessions_cb_ctx *c = ctx;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = os_snprintf(c->buf, c->buflen, " %u", fst_session_get_id(s));
|
|
|
|
|
|
|
|
c->buf += ret;
|
|
|
|
c->buflen -= ret;
|
|
|
|
c->reply_len += ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int list_sessions(const char *group_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct list_sessions_cb_ctx ctx;
|
|
|
|
struct fst_group *g;
|
|
|
|
|
|
|
|
g = get_fst_group_by_id(group_id);
|
|
|
|
if (!g) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find group '%s'",
|
|
|
|
group_id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.buf = buf;
|
|
|
|
ctx.buflen = buflen;
|
|
|
|
ctx.reply_len = 0;
|
|
|
|
|
|
|
|
fst_session_enum(g, list_session_enum_cb, &ctx);
|
|
|
|
|
|
|
|
ctx.reply_len += os_snprintf(buf + ctx.reply_len, ctx.buflen, "\n");
|
|
|
|
|
|
|
|
return ctx.reply_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst iface_peers */
|
|
|
|
static int iface_peers(const char *group_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
const char *ifname;
|
|
|
|
struct fst_group *g;
|
|
|
|
struct fst_iface *f;
|
|
|
|
struct fst_get_peer_ctx *ctx;
|
|
|
|
const u8 *addr;
|
|
|
|
unsigned found = 0;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
g = get_fst_group_by_id(group_id);
|
|
|
|
if (!g) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find group '%s'",
|
|
|
|
group_id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
ifname = os_strchr(group_id, ' ');
|
|
|
|
if (!ifname)
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
ifname++;
|
|
|
|
|
|
|
|
foreach_fst_group_iface(g, f) {
|
|
|
|
const char *in = fst_iface_get_name(f);
|
|
|
|
|
|
|
|
if (os_strncmp(ifname, in, os_strlen(in)) == 0) {
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found)
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
|
|
|
|
addr = fst_iface_get_peer_first(f, &ctx, FALSE);
|
|
|
|
for (; addr != NULL; addr = fst_iface_get_peer_next(f, &ctx, FALSE)) {
|
|
|
|
int res;
|
|
|
|
|
|
|
|
res = os_snprintf(buf + ret, buflen - ret, MACSTR "\n",
|
|
|
|
MAC2STR(addr));
|
|
|
|
if (os_snprintf_error(buflen - ret, res))
|
|
|
|
break;
|
|
|
|
ret += res;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int get_peer_mbies(const char *params, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
char *endp;
|
|
|
|
char ifname[FST_MAX_INTERFACE_SIZE];
|
|
|
|
u8 peer_addr[ETH_ALEN];
|
|
|
|
struct fst_group *g;
|
|
|
|
struct fst_iface *iface = NULL;
|
2015-07-18 15:16:26 +02:00
|
|
|
const struct wpabuf *mbies;
|
FST: Add the Fast Session Transfer (FST) module
Fast Session Transfer (FST) is the transfer of a session from a channel
to another channel in a different frequency band. The term "session"
refers to non-physical layer state information kept by a pair of
stations (STAs) that communicate directly (i.e., excludes forwarding).
The FST is implemented in accordance with IEEE Std 802.11ad-2012.
Definitions
* FST interface - an interface for which FST functionality is enabled
* FST group - a bunch of FST interfaces representing single
multi-band STA
* FST peer - a multi-band capable STA connected
* FST module - multi-band operation functionality implemented in
accordance with IEEE Std 802.11ad-2012 (see 10.32
Multi-band operation) as a part of hostapd/wpa_supplicant
* FST manager - an external application that implements custom FST
related logic, using the FST module's interfaces
accessible via CLI or D-Bus
This commit introduces only the FST module. Integration of the FST
module into the hostapd/wpa_supplicant and corresponding CLI/D-Bus
interfaces and FST related tests are covered in separate commits.
FST manager application is out of scope of these commits.
As FST aggregates a few interfaces into FST group, the FST module uses
global CLI for both commands and notifications. It also exposes
alternative non-interface based D-Bus subtree for this purposes.
Configuration and Initialization
* FST functionality can enabled by compilation flag (CONFIG_FST)
* hostapd/wpa_supplicant controlling multiple interfaces are used for
FST
* once enabled by compilation, the FST can be enabled for specific
interfaces in the configuration files
* FST interfaces are aggregated in FST groups (fst_group_id config file
entry), where each FST group:
- represents one multi-band device
- should have two or more FST interfaces in it
* priority (fst_priority config file entry) must be configured for each
FST interface. FST interface with higher priority is the interface FST
will always try to switch to. Thus, for example, for the maximal
throughput, it should be the fastest FST interface in the FST setup.
* default Link Loss Timeout (LLT) value can be configured for each FST
interface (fst_llt config file entry). It represents LLT to be used
by FST when this interface is active.
* FST interfaces advertise the Multi-band capability by including the
Multi-band element in the corresponding frames
FST CLI commands:
* fst list_groups - list FST groups configured.
* fst list_ifaces - list FST interfaces which belong to specific group
* fst iface_peers - list Multi-Band STAs connected to specific interface
* fst list_sessions - list existing FST sessions
* fst session_get - get FST session info
* fst session_add - create FST session object
* fst session_set - set FST session parameters (old_iface, new_iface,
peer_addr, llt)
* fst session_initiate - initiate FST setup
* fst session_respond - respond to FST setup establishemnt attempt by
counterpart
* fst session_transfer - initiate FST switch
* fst session_teardown - tear down FST Setup but leave the session object
for reuse
* fst session_remove - remove FST session object
FST CLI notifications:
* FST-EVENT-PEER - peer state changed (CONNECT/DISCONNECT)
* FST-EVENT-SESSION - FST session level notification with following
sub-events:
- EVENT_FST_SESSION_STATE - FST session state changed
- EVENT_FST_ESTABLISHED - previously initiated FST session became
established
- EVENT_FST_SETUP - new FST session object created due to FST session
negotiation attempt by counterpart
All the FST CLI commands and notifications are also implemented on D-Bus
for wpa_supplicant.
IEEE 802.11 standard compliance
FST module implements FST setup statemachine in compliance with IEEE
802.11ad (P802.11-REVmc/D3.3), as it described in 10.32 Multi-band
operation (see also Figure 10-34 - States of the FST setup protocol).
Thus, for example, the FST module initiates FST switch automatically
when FST setup becomes established with LLT=0 in accordance with
10.32.2.2 Transitioning between states.
At the moment, FST module only supports non-transparent STA-based FST
(see 10.32.1 General).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2015-02-18 15:59:21 +01:00
|
|
|
|
|
|
|
if (fst_read_next_text_param(params, ifname, sizeof(ifname), &endp) ||
|
|
|
|
!*ifname)
|
|
|
|
goto problem;
|
|
|
|
|
|
|
|
while (isspace(*endp))
|
|
|
|
endp++;
|
|
|
|
if (fst_read_peer_addr(endp, peer_addr))
|
|
|
|
goto problem;
|
|
|
|
|
|
|
|
foreach_fst_group(g) {
|
|
|
|
iface = fst_group_get_iface_by_name(g, ifname);
|
|
|
|
if (!iface)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!iface)
|
|
|
|
goto problem;
|
|
|
|
|
|
|
|
mbies = fst_iface_get_peer_mb_ie(iface, peer_addr);
|
|
|
|
if (!mbies)
|
|
|
|
goto problem;
|
|
|
|
|
2015-07-18 15:09:42 +02:00
|
|
|
return wpa_snprintf_hex(buf, buflen, wpabuf_head(mbies),
|
|
|
|
wpabuf_len(mbies));
|
FST: Add the Fast Session Transfer (FST) module
Fast Session Transfer (FST) is the transfer of a session from a channel
to another channel in a different frequency band. The term "session"
refers to non-physical layer state information kept by a pair of
stations (STAs) that communicate directly (i.e., excludes forwarding).
The FST is implemented in accordance with IEEE Std 802.11ad-2012.
Definitions
* FST interface - an interface for which FST functionality is enabled
* FST group - a bunch of FST interfaces representing single
multi-band STA
* FST peer - a multi-band capable STA connected
* FST module - multi-band operation functionality implemented in
accordance with IEEE Std 802.11ad-2012 (see 10.32
Multi-band operation) as a part of hostapd/wpa_supplicant
* FST manager - an external application that implements custom FST
related logic, using the FST module's interfaces
accessible via CLI or D-Bus
This commit introduces only the FST module. Integration of the FST
module into the hostapd/wpa_supplicant and corresponding CLI/D-Bus
interfaces and FST related tests are covered in separate commits.
FST manager application is out of scope of these commits.
As FST aggregates a few interfaces into FST group, the FST module uses
global CLI for both commands and notifications. It also exposes
alternative non-interface based D-Bus subtree for this purposes.
Configuration and Initialization
* FST functionality can enabled by compilation flag (CONFIG_FST)
* hostapd/wpa_supplicant controlling multiple interfaces are used for
FST
* once enabled by compilation, the FST can be enabled for specific
interfaces in the configuration files
* FST interfaces are aggregated in FST groups (fst_group_id config file
entry), where each FST group:
- represents one multi-band device
- should have two or more FST interfaces in it
* priority (fst_priority config file entry) must be configured for each
FST interface. FST interface with higher priority is the interface FST
will always try to switch to. Thus, for example, for the maximal
throughput, it should be the fastest FST interface in the FST setup.
* default Link Loss Timeout (LLT) value can be configured for each FST
interface (fst_llt config file entry). It represents LLT to be used
by FST when this interface is active.
* FST interfaces advertise the Multi-band capability by including the
Multi-band element in the corresponding frames
FST CLI commands:
* fst list_groups - list FST groups configured.
* fst list_ifaces - list FST interfaces which belong to specific group
* fst iface_peers - list Multi-Band STAs connected to specific interface
* fst list_sessions - list existing FST sessions
* fst session_get - get FST session info
* fst session_add - create FST session object
* fst session_set - set FST session parameters (old_iface, new_iface,
peer_addr, llt)
* fst session_initiate - initiate FST setup
* fst session_respond - respond to FST setup establishemnt attempt by
counterpart
* fst session_transfer - initiate FST switch
* fst session_teardown - tear down FST Setup but leave the session object
for reuse
* fst session_remove - remove FST session object
FST CLI notifications:
* FST-EVENT-PEER - peer state changed (CONNECT/DISCONNECT)
* FST-EVENT-SESSION - FST session level notification with following
sub-events:
- EVENT_FST_SESSION_STATE - FST session state changed
- EVENT_FST_ESTABLISHED - previously initiated FST session became
established
- EVENT_FST_SETUP - new FST session object created due to FST session
negotiation attempt by counterpart
All the FST CLI commands and notifications are also implemented on D-Bus
for wpa_supplicant.
IEEE 802.11 standard compliance
FST module implements FST setup statemachine in compliance with IEEE
802.11ad (P802.11-REVmc/D3.3), as it described in 10.32 Multi-band
operation (see also Figure 10-34 - States of the FST setup protocol).
Thus, for example, the FST module initiates FST switch automatically
when FST setup becomes established with LLT=0 in accordance with
10.32.2.2 Transitioning between states.
At the moment, FST module only supports non-transparent STA-based FST
(see 10.32.1 General).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2015-02-18 15:59:21 +01:00
|
|
|
|
|
|
|
problem:
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst list_ifaces */
|
|
|
|
static int list_ifaces(const char *group_id, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_group *g;
|
|
|
|
struct fst_iface *f;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
g = get_fst_group_by_id(group_id);
|
|
|
|
if (!g) {
|
|
|
|
fst_printf(MSG_WARNING, "CTRL: Cannot find group '%s'",
|
|
|
|
group_id);
|
|
|
|
return os_snprintf(buf, buflen, "FAIL\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach_fst_group_iface(g, f) {
|
|
|
|
int res;
|
|
|
|
const u8 *iface_addr = fst_iface_get_addr(f);
|
|
|
|
|
|
|
|
res = os_snprintf(buf + ret, buflen - ret,
|
|
|
|
"%s|" MACSTR "|%u|%u\n",
|
|
|
|
fst_iface_get_name(f),
|
|
|
|
MAC2STR(iface_addr),
|
|
|
|
fst_iface_get_priority(f),
|
|
|
|
fst_iface_get_llt(f));
|
|
|
|
if (os_snprintf_error(buflen - ret, res))
|
|
|
|
break;
|
|
|
|
ret += res;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst list_groups */
|
|
|
|
static int list_groups(const char *cmd, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_group *g;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
foreach_fst_group(g) {
|
|
|
|
int res;
|
|
|
|
|
|
|
|
res = os_snprintf(buf + ret, buflen - ret, "%s\n",
|
|
|
|
fst_group_get_id(g));
|
|
|
|
if (os_snprintf_error(buflen - ret, res))
|
|
|
|
break;
|
|
|
|
ret += res;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char * band_freq(enum mb_band_id band)
|
|
|
|
{
|
|
|
|
static const char *band_names[] = {
|
|
|
|
[MB_BAND_ID_WIFI_2_4GHZ] "2.4GHZ",
|
|
|
|
[MB_BAND_ID_WIFI_5GHZ] "5GHZ",
|
|
|
|
[MB_BAND_ID_WIFI_60GHZ] "60GHZ",
|
|
|
|
};
|
|
|
|
|
|
|
|
return fst_get_str_name(band, band_names, ARRAY_SIZE(band_names));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int print_band(unsigned num, struct fst_iface *iface, const u8 *addr,
|
|
|
|
char *buf, size_t buflen)
|
|
|
|
{
|
2015-07-18 15:16:26 +02:00
|
|
|
const struct wpabuf *wpabuf;
|
FST: Add the Fast Session Transfer (FST) module
Fast Session Transfer (FST) is the transfer of a session from a channel
to another channel in a different frequency band. The term "session"
refers to non-physical layer state information kept by a pair of
stations (STAs) that communicate directly (i.e., excludes forwarding).
The FST is implemented in accordance with IEEE Std 802.11ad-2012.
Definitions
* FST interface - an interface for which FST functionality is enabled
* FST group - a bunch of FST interfaces representing single
multi-band STA
* FST peer - a multi-band capable STA connected
* FST module - multi-band operation functionality implemented in
accordance with IEEE Std 802.11ad-2012 (see 10.32
Multi-band operation) as a part of hostapd/wpa_supplicant
* FST manager - an external application that implements custom FST
related logic, using the FST module's interfaces
accessible via CLI or D-Bus
This commit introduces only the FST module. Integration of the FST
module into the hostapd/wpa_supplicant and corresponding CLI/D-Bus
interfaces and FST related tests are covered in separate commits.
FST manager application is out of scope of these commits.
As FST aggregates a few interfaces into FST group, the FST module uses
global CLI for both commands and notifications. It also exposes
alternative non-interface based D-Bus subtree for this purposes.
Configuration and Initialization
* FST functionality can enabled by compilation flag (CONFIG_FST)
* hostapd/wpa_supplicant controlling multiple interfaces are used for
FST
* once enabled by compilation, the FST can be enabled for specific
interfaces in the configuration files
* FST interfaces are aggregated in FST groups (fst_group_id config file
entry), where each FST group:
- represents one multi-band device
- should have two or more FST interfaces in it
* priority (fst_priority config file entry) must be configured for each
FST interface. FST interface with higher priority is the interface FST
will always try to switch to. Thus, for example, for the maximal
throughput, it should be the fastest FST interface in the FST setup.
* default Link Loss Timeout (LLT) value can be configured for each FST
interface (fst_llt config file entry). It represents LLT to be used
by FST when this interface is active.
* FST interfaces advertise the Multi-band capability by including the
Multi-band element in the corresponding frames
FST CLI commands:
* fst list_groups - list FST groups configured.
* fst list_ifaces - list FST interfaces which belong to specific group
* fst iface_peers - list Multi-Band STAs connected to specific interface
* fst list_sessions - list existing FST sessions
* fst session_get - get FST session info
* fst session_add - create FST session object
* fst session_set - set FST session parameters (old_iface, new_iface,
peer_addr, llt)
* fst session_initiate - initiate FST setup
* fst session_respond - respond to FST setup establishemnt attempt by
counterpart
* fst session_transfer - initiate FST switch
* fst session_teardown - tear down FST Setup but leave the session object
for reuse
* fst session_remove - remove FST session object
FST CLI notifications:
* FST-EVENT-PEER - peer state changed (CONNECT/DISCONNECT)
* FST-EVENT-SESSION - FST session level notification with following
sub-events:
- EVENT_FST_SESSION_STATE - FST session state changed
- EVENT_FST_ESTABLISHED - previously initiated FST session became
established
- EVENT_FST_SETUP - new FST session object created due to FST session
negotiation attempt by counterpart
All the FST CLI commands and notifications are also implemented on D-Bus
for wpa_supplicant.
IEEE 802.11 standard compliance
FST module implements FST setup statemachine in compliance with IEEE
802.11ad (P802.11-REVmc/D3.3), as it described in 10.32 Multi-band
operation (see also Figure 10-34 - States of the FST setup protocol).
Thus, for example, the FST module initiates FST switch automatically
when FST setup becomes established with LLT=0 in accordance with
10.32.2.2 Transitioning between states.
At the moment, FST module only supports non-transparent STA-based FST
(see 10.32.1 General).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2015-02-18 15:59:21 +01:00
|
|
|
enum hostapd_hw_mode hw_mode;
|
|
|
|
u8 channel;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
fst_iface_get_channel_info(iface, &hw_mode, &channel);
|
|
|
|
|
|
|
|
ret += os_snprintf(buf + ret, buflen - ret, "band%u_frequency=%s\n",
|
|
|
|
num, band_freq(fst_hw_mode_to_band(hw_mode)));
|
|
|
|
ret += os_snprintf(buf + ret, buflen - ret, "band%u_iface=%s\n",
|
|
|
|
num, fst_iface_get_name(iface));
|
|
|
|
wpabuf = fst_iface_get_peer_mb_ie(iface, addr);
|
|
|
|
if (wpabuf) {
|
|
|
|
ret += os_snprintf(buf + ret, buflen - ret, "band%u_mb_ies=",
|
|
|
|
num);
|
2015-07-18 15:09:42 +02:00
|
|
|
ret += wpa_snprintf_hex(buf + ret, buflen - ret,
|
|
|
|
wpabuf_head(wpabuf),
|
|
|
|
wpabuf_len(wpabuf));
|
FST: Add the Fast Session Transfer (FST) module
Fast Session Transfer (FST) is the transfer of a session from a channel
to another channel in a different frequency band. The term "session"
refers to non-physical layer state information kept by a pair of
stations (STAs) that communicate directly (i.e., excludes forwarding).
The FST is implemented in accordance with IEEE Std 802.11ad-2012.
Definitions
* FST interface - an interface for which FST functionality is enabled
* FST group - a bunch of FST interfaces representing single
multi-band STA
* FST peer - a multi-band capable STA connected
* FST module - multi-band operation functionality implemented in
accordance with IEEE Std 802.11ad-2012 (see 10.32
Multi-band operation) as a part of hostapd/wpa_supplicant
* FST manager - an external application that implements custom FST
related logic, using the FST module's interfaces
accessible via CLI or D-Bus
This commit introduces only the FST module. Integration of the FST
module into the hostapd/wpa_supplicant and corresponding CLI/D-Bus
interfaces and FST related tests are covered in separate commits.
FST manager application is out of scope of these commits.
As FST aggregates a few interfaces into FST group, the FST module uses
global CLI for both commands and notifications. It also exposes
alternative non-interface based D-Bus subtree for this purposes.
Configuration and Initialization
* FST functionality can enabled by compilation flag (CONFIG_FST)
* hostapd/wpa_supplicant controlling multiple interfaces are used for
FST
* once enabled by compilation, the FST can be enabled for specific
interfaces in the configuration files
* FST interfaces are aggregated in FST groups (fst_group_id config file
entry), where each FST group:
- represents one multi-band device
- should have two or more FST interfaces in it
* priority (fst_priority config file entry) must be configured for each
FST interface. FST interface with higher priority is the interface FST
will always try to switch to. Thus, for example, for the maximal
throughput, it should be the fastest FST interface in the FST setup.
* default Link Loss Timeout (LLT) value can be configured for each FST
interface (fst_llt config file entry). It represents LLT to be used
by FST when this interface is active.
* FST interfaces advertise the Multi-band capability by including the
Multi-band element in the corresponding frames
FST CLI commands:
* fst list_groups - list FST groups configured.
* fst list_ifaces - list FST interfaces which belong to specific group
* fst iface_peers - list Multi-Band STAs connected to specific interface
* fst list_sessions - list existing FST sessions
* fst session_get - get FST session info
* fst session_add - create FST session object
* fst session_set - set FST session parameters (old_iface, new_iface,
peer_addr, llt)
* fst session_initiate - initiate FST setup
* fst session_respond - respond to FST setup establishemnt attempt by
counterpart
* fst session_transfer - initiate FST switch
* fst session_teardown - tear down FST Setup but leave the session object
for reuse
* fst session_remove - remove FST session object
FST CLI notifications:
* FST-EVENT-PEER - peer state changed (CONNECT/DISCONNECT)
* FST-EVENT-SESSION - FST session level notification with following
sub-events:
- EVENT_FST_SESSION_STATE - FST session state changed
- EVENT_FST_ESTABLISHED - previously initiated FST session became
established
- EVENT_FST_SETUP - new FST session object created due to FST session
negotiation attempt by counterpart
All the FST CLI commands and notifications are also implemented on D-Bus
for wpa_supplicant.
IEEE 802.11 standard compliance
FST module implements FST setup statemachine in compliance with IEEE
802.11ad (P802.11-REVmc/D3.3), as it described in 10.32 Multi-band
operation (see also Figure 10-34 - States of the FST setup protocol).
Thus, for example, the FST module initiates FST switch automatically
when FST setup becomes established with LLT=0 in accordance with
10.32.2.2 Transitioning between states.
At the moment, FST module only supports non-transparent STA-based FST
(see 10.32.1 General).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2015-02-18 15:59:21 +01:00
|
|
|
ret += os_snprintf(buf + ret, buflen - ret, "\n");
|
|
|
|
}
|
|
|
|
ret += os_snprintf(buf + ret, buflen - ret, "band%u_fst_group_id=%s\n",
|
|
|
|
num, fst_iface_get_group_id(iface));
|
|
|
|
ret += os_snprintf(buf + ret, buflen - ret, "band%u_fst_priority=%u\n",
|
|
|
|
num, fst_iface_get_priority(iface));
|
|
|
|
ret += os_snprintf(buf + ret, buflen - ret, "band%u_fst_llt=%u\n",
|
|
|
|
num, fst_iface_get_llt(iface));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void fst_ctrl_iface_on_iface_state_changed(struct fst_iface *i,
|
|
|
|
Boolean attached)
|
|
|
|
{
|
|
|
|
union fst_event_extra extra;
|
|
|
|
|
|
|
|
os_memset(&extra, 0, sizeof(extra));
|
|
|
|
extra.iface_state.attached = attached;
|
|
|
|
os_strlcpy(extra.iface_state.ifname, fst_iface_get_name(i),
|
|
|
|
sizeof(extra.iface_state.ifname));
|
|
|
|
os_strlcpy(extra.iface_state.group_id, fst_iface_get_group_id(i),
|
|
|
|
sizeof(extra.iface_state.group_id));
|
|
|
|
|
|
|
|
fst_ctrl_iface_notify(FST_INVALID_SESSION_ID,
|
|
|
|
EVENT_FST_IFACE_STATE_CHANGED, &extra);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int fst_ctrl_iface_on_iface_added(struct fst_iface *i)
|
|
|
|
{
|
|
|
|
fst_ctrl_iface_on_iface_state_changed(i, TRUE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void fst_ctrl_iface_on_iface_removed(struct fst_iface *i)
|
|
|
|
{
|
|
|
|
fst_ctrl_iface_on_iface_state_changed(i, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void fst_ctrl_iface_on_event(enum fst_event_type event_type,
|
|
|
|
struct fst_iface *i, struct fst_session *s,
|
|
|
|
const union fst_event_extra *extra)
|
|
|
|
{
|
|
|
|
u32 session_id = s ? fst_session_get_id(s) : FST_INVALID_SESSION_ID;
|
|
|
|
|
|
|
|
fst_ctrl_iface_notify(session_id, event_type, extra);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const struct fst_ctrl ctrl_cli = {
|
|
|
|
.on_iface_added = fst_ctrl_iface_on_iface_added,
|
|
|
|
.on_iface_removed = fst_ctrl_iface_on_iface_removed,
|
|
|
|
.on_event = fst_ctrl_iface_on_event,
|
|
|
|
};
|
|
|
|
|
|
|
|
const struct fst_ctrl *fst_ctrl_cli = &ctrl_cli;
|
|
|
|
|
|
|
|
|
|
|
|
int fst_ctrl_iface_mb_info(const u8 *addr, char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
struct fst_group *g;
|
|
|
|
struct fst_iface *f;
|
|
|
|
unsigned num = 0;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
foreach_fst_group(g) {
|
|
|
|
foreach_fst_group_iface(g, f) {
|
|
|
|
if (fst_iface_is_connected(f, addr)) {
|
|
|
|
ret += print_band(num++, f, addr,
|
|
|
|
buf + ret, buflen - ret);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst ctrl processor */
|
|
|
|
int fst_ctrl_iface_receive(const char *cmd, char *reply, size_t reply_size)
|
|
|
|
{
|
|
|
|
static const struct fst_command {
|
|
|
|
const char *name;
|
|
|
|
unsigned has_param;
|
|
|
|
int (*process)(const char *group_id, char *buf, size_t buflen);
|
|
|
|
} commands[] = {
|
|
|
|
{ FST_CMD_LIST_GROUPS, 0, list_groups},
|
|
|
|
{ FST_CMD_LIST_IFACES, 1, list_ifaces},
|
|
|
|
{ FST_CMD_IFACE_PEERS, 1, iface_peers},
|
|
|
|
{ FST_CMD_GET_PEER_MBIES, 1, get_peer_mbies},
|
|
|
|
{ FST_CMD_LIST_SESSIONS, 1, list_sessions},
|
|
|
|
{ FST_CMD_SESSION_ADD, 1, session_add},
|
|
|
|
{ FST_CMD_SESSION_REMOVE, 1, session_remove},
|
|
|
|
{ FST_CMD_SESSION_GET, 1, session_get},
|
|
|
|
{ FST_CMD_SESSION_SET, 1, session_set},
|
|
|
|
{ FST_CMD_SESSION_INITIATE, 1, session_initiate},
|
|
|
|
{ FST_CMD_SESSION_RESPOND, 1, session_respond},
|
|
|
|
{ FST_CMD_SESSION_TRANSFER, 1, session_transfer},
|
|
|
|
{ FST_CMD_SESSION_TEARDOWN, 1, session_teardown},
|
2014-12-04 18:20:56 +01:00
|
|
|
#ifdef CONFIG_FST_TEST
|
|
|
|
{ FST_CMD_TEST_REQUEST, 1, test_request },
|
|
|
|
#endif /* CONFIG_FST_TEST */
|
FST: Add the Fast Session Transfer (FST) module
Fast Session Transfer (FST) is the transfer of a session from a channel
to another channel in a different frequency band. The term "session"
refers to non-physical layer state information kept by a pair of
stations (STAs) that communicate directly (i.e., excludes forwarding).
The FST is implemented in accordance with IEEE Std 802.11ad-2012.
Definitions
* FST interface - an interface for which FST functionality is enabled
* FST group - a bunch of FST interfaces representing single
multi-band STA
* FST peer - a multi-band capable STA connected
* FST module - multi-band operation functionality implemented in
accordance with IEEE Std 802.11ad-2012 (see 10.32
Multi-band operation) as a part of hostapd/wpa_supplicant
* FST manager - an external application that implements custom FST
related logic, using the FST module's interfaces
accessible via CLI or D-Bus
This commit introduces only the FST module. Integration of the FST
module into the hostapd/wpa_supplicant and corresponding CLI/D-Bus
interfaces and FST related tests are covered in separate commits.
FST manager application is out of scope of these commits.
As FST aggregates a few interfaces into FST group, the FST module uses
global CLI for both commands and notifications. It also exposes
alternative non-interface based D-Bus subtree for this purposes.
Configuration and Initialization
* FST functionality can enabled by compilation flag (CONFIG_FST)
* hostapd/wpa_supplicant controlling multiple interfaces are used for
FST
* once enabled by compilation, the FST can be enabled for specific
interfaces in the configuration files
* FST interfaces are aggregated in FST groups (fst_group_id config file
entry), where each FST group:
- represents one multi-band device
- should have two or more FST interfaces in it
* priority (fst_priority config file entry) must be configured for each
FST interface. FST interface with higher priority is the interface FST
will always try to switch to. Thus, for example, for the maximal
throughput, it should be the fastest FST interface in the FST setup.
* default Link Loss Timeout (LLT) value can be configured for each FST
interface (fst_llt config file entry). It represents LLT to be used
by FST when this interface is active.
* FST interfaces advertise the Multi-band capability by including the
Multi-band element in the corresponding frames
FST CLI commands:
* fst list_groups - list FST groups configured.
* fst list_ifaces - list FST interfaces which belong to specific group
* fst iface_peers - list Multi-Band STAs connected to specific interface
* fst list_sessions - list existing FST sessions
* fst session_get - get FST session info
* fst session_add - create FST session object
* fst session_set - set FST session parameters (old_iface, new_iface,
peer_addr, llt)
* fst session_initiate - initiate FST setup
* fst session_respond - respond to FST setup establishemnt attempt by
counterpart
* fst session_transfer - initiate FST switch
* fst session_teardown - tear down FST Setup but leave the session object
for reuse
* fst session_remove - remove FST session object
FST CLI notifications:
* FST-EVENT-PEER - peer state changed (CONNECT/DISCONNECT)
* FST-EVENT-SESSION - FST session level notification with following
sub-events:
- EVENT_FST_SESSION_STATE - FST session state changed
- EVENT_FST_ESTABLISHED - previously initiated FST session became
established
- EVENT_FST_SETUP - new FST session object created due to FST session
negotiation attempt by counterpart
All the FST CLI commands and notifications are also implemented on D-Bus
for wpa_supplicant.
IEEE 802.11 standard compliance
FST module implements FST setup statemachine in compliance with IEEE
802.11ad (P802.11-REVmc/D3.3), as it described in 10.32 Multi-band
operation (see also Figure 10-34 - States of the FST setup protocol).
Thus, for example, the FST module initiates FST switch automatically
when FST setup becomes established with LLT=0 in accordance with
10.32.2.2 Transitioning between states.
At the moment, FST module only supports non-transparent STA-based FST
(see 10.32.1 General).
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
2015-02-18 15:59:21 +01:00
|
|
|
{ NULL, 0, NULL }
|
|
|
|
};
|
|
|
|
const struct fst_command *c;
|
|
|
|
const char *p;
|
|
|
|
const char *temp;
|
|
|
|
Boolean non_spaces_found;
|
|
|
|
|
|
|
|
for (c = commands; c->name; c++) {
|
|
|
|
if (os_strncasecmp(cmd, c->name, os_strlen(c->name)) != 0)
|
|
|
|
continue;
|
|
|
|
p = cmd + os_strlen(c->name);
|
|
|
|
if (c->has_param) {
|
|
|
|
if (!isspace(p[0]))
|
|
|
|
return os_snprintf(reply, reply_size, "FAIL\n");
|
|
|
|
p++;
|
|
|
|
temp = p;
|
|
|
|
non_spaces_found = FALSE;
|
|
|
|
while (*temp) {
|
|
|
|
if (!isspace(*temp)) {
|
|
|
|
non_spaces_found = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
temp++;
|
|
|
|
}
|
|
|
|
if (!non_spaces_found)
|
|
|
|
return os_snprintf(reply, reply_size, "FAIL\n");
|
|
|
|
}
|
|
|
|
return c->process(p, reply, reply_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
return os_snprintf(reply, reply_size, "UNKNOWN FST COMMAND\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fst_read_next_int_param(const char *params, Boolean *valid, char **endp)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
const char *curp;
|
|
|
|
|
|
|
|
*valid = FALSE;
|
|
|
|
*endp = (char *) params;
|
|
|
|
curp = params;
|
|
|
|
if (*curp) {
|
|
|
|
ret = (int) strtol(curp, endp, 0);
|
|
|
|
if (!**endp || isspace(**endp))
|
|
|
|
*valid = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fst_read_next_text_param(const char *params, char *buf, size_t buflen,
|
|
|
|
char **endp)
|
|
|
|
{
|
|
|
|
size_t max_chars_to_copy;
|
|
|
|
char *cur_dest;
|
|
|
|
|
|
|
|
if (buflen <= 1)
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
*endp = (char *) params;
|
|
|
|
while (isspace(**endp))
|
|
|
|
(*endp)++;
|
|
|
|
if (!**endp)
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
max_chars_to_copy = buflen - 1;
|
|
|
|
/* We need 1 byte for the terminating zero */
|
|
|
|
cur_dest = buf;
|
|
|
|
while (**endp && !isspace(**endp) && max_chars_to_copy > 0) {
|
|
|
|
*cur_dest = **endp;
|
|
|
|
(*endp)++;
|
|
|
|
cur_dest++;
|
|
|
|
max_chars_to_copy--;
|
|
|
|
}
|
|
|
|
*cur_dest = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fst_read_peer_addr(const char *mac, u8 *peer_addr)
|
|
|
|
{
|
|
|
|
if (hwaddr_aton(mac, peer_addr)) {
|
|
|
|
fst_printf(MSG_WARNING, "Bad peer_mac %s: invalid addr string",
|
|
|
|
mac);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_zero_ether_addr(peer_addr) ||
|
|
|
|
is_multicast_ether_addr(peer_addr)) {
|
|
|
|
fst_printf(MSG_WARNING, "Bad peer_mac %s: not a unicast addr",
|
|
|
|
mac);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fst_parse_attach_command(const char *cmd, char *ifname, size_t ifname_size,
|
|
|
|
struct fst_iface_cfg *cfg)
|
|
|
|
{
|
|
|
|
char *pos;
|
|
|
|
char *endp;
|
|
|
|
Boolean is_valid;
|
|
|
|
int val;
|
|
|
|
|
|
|
|
if (fst_read_next_text_param(cmd, ifname, ifname_size, &endp) ||
|
|
|
|
fst_read_next_text_param(endp, cfg->group_id, sizeof(cfg->group_id),
|
|
|
|
&endp))
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
cfg->llt = FST_DEFAULT_LLT_CFG_VALUE;
|
|
|
|
cfg->priority = 0;
|
|
|
|
pos = os_strstr(endp, FST_ATTACH_CMD_PNAME_LLT);
|
|
|
|
if (pos) {
|
|
|
|
pos += os_strlen(FST_ATTACH_CMD_PNAME_LLT);
|
|
|
|
if (*pos == '=') {
|
|
|
|
val = fst_read_next_int_param(pos + 1, &is_valid,
|
|
|
|
&endp);
|
|
|
|
if (is_valid)
|
|
|
|
cfg->llt = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos = os_strstr(endp, FST_ATTACH_CMD_PNAME_PRIORITY);
|
|
|
|
if (pos) {
|
|
|
|
pos += os_strlen(FST_ATTACH_CMD_PNAME_PRIORITY);
|
|
|
|
if (*pos == '=') {
|
|
|
|
val = fst_read_next_int_param(pos + 1, &is_valid,
|
|
|
|
&endp);
|
|
|
|
if (is_valid)
|
|
|
|
cfg->priority = (u8) val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int fst_parse_detach_command(const char *cmd, char *ifname, size_t ifname_size)
|
|
|
|
{
|
|
|
|
char *endp;
|
|
|
|
|
|
|
|
if (fst_read_next_text_param(cmd, ifname, ifname_size, &endp))
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* fst iface_detach */
|
|
|
|
int fst_iface_detach(const char *ifname)
|
|
|
|
{
|
|
|
|
struct fst_group *g;
|
|
|
|
struct fst_iface *f;
|
|
|
|
|
|
|
|
foreach_fst_group(g) {
|
|
|
|
f = fst_group_get_iface_by_name(g, ifname);
|
|
|
|
if (f) {
|
|
|
|
fst_detach(f);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINVAL;
|
|
|
|
}
|