summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: fc38f7f)
raw | patch | inline | side by side (parent: fc38f7f)
author | KN <sudharshan@ti.com> | |
Tue, 9 Jun 2020 21:38:12 +0000 (16:38 -0500) | ||
committer | KN <sudharshan@ti.com> | |
Tue, 9 Jun 2020 21:38:12 +0000 (16:38 -0500) |
Support for connection of an "empty" MP to a "full" MP
if no other MP are available.
Signed-off-by: KN <sudharshan@ti.com>
if no other MP are available.
Signed-off-by: KN <sudharshan@ti.com>
14 files changed:
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 084ad3a460c5998896e2eeb152197b00773e5354..0f882d09cab73e139af69862812ae0d6c29f0134 100644 (file)
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
int max_plinks;
void (*mesh_sta_free_cb)(struct hostapd_data *hapd,
struct sta_info *sta);
+ Boolean mesh_switch_connection;
struct wpabuf *mesh_pending_auth;
+ struct wpabuf *mesh_pending_action;
+ u8 mesh_beacon_pending_peer[ETH_ALEN];
struct os_reltime mesh_pending_auth_time;
u8 mesh_required_peer[ETH_ALEN];
#endif /* CONFIG_MESH */
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index a6b7d62558a7892898db08a8090fe20c9f722596..679be56095ae1515ce97f4f497d2ee850979179d 100644 (file)
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
#endif /* CONFIG_MESH */
} else {
#ifdef CONFIG_MESH
- if (hapd->conf->mesh & MESH_ENABLED) {
+
+ if (hapd->conf->mesh & MESH_ENABLED) {
/* if the mesh peer is not available, we don't do auth.
*/
- wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
- " not yet known - drop Authentication frame",
- MAC2STR(mgmt->sa));
- /*
- * Save a copy of the frame so that it can be processed
- * if a new peer entry is added shortly after this.
- */
- wpabuf_free(hapd->mesh_pending_auth);
- hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len);
- os_get_reltime(&hapd->mesh_pending_auth_time);
+ if (!hapd->mesh_switch_connection) {
+ /* During switch connection ignore any
+ * auth frame.
+ */
+ wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
+ " not yet known - SAVE Authentication frame",
+ MAC2STR(mgmt->sa));
+ /*
+ * Save a copy of the frame so that it can be processed
+ * if a new peer entry is added shortly after this.
+ */
+ wpabuf_free(hapd->mesh_pending_auth);
+ hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len);
+ os_get_reltime(&hapd->mesh_pending_auth_time);
+ }
return;
}
#endif /* CONFIG_MESH */
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 7d90b5afe10361bb92cb8697255fbd42cb5d903a..fed0ed55909dac3225ae0fa5ea6d352e6fb9ec79 100644 (file)
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
*/
int (*leave_mesh)(void *priv);
+ /**
+ * get_worst_mesh - get lowest signal mesh peer link
+ * : Private driver interface data
+ * : mac of the lowest mesh peer link
+ * Returns 0 on success, -1 on failure
+ */
+ int (*get_worst_mesh)(void *priv, u8 *macaddr);
+
/**
* probe_mesh_link - Inject a frame over direct mesh link to a given
* peer skipping the next_hop lookup from mpath table.
index e58ee636dfe4d7093f2cc27b4e61f0b6b55cbf5e..9224dc26d282c713c4cc7c2ec9eab3c58a2b1c49 100644 (file)
@@ -10936,6 +10936,20 @@ static int nl80211_configure_data_frame_filters(void *priv, u32 filter_flags)
return 0;
}
+static int nl80211_get_low_signal_mesh(void *priv, u8 *macaddr)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+ struct nl_msg *msg;
+ struct wiphy_idx_data info = {
+ .macaddr = macaddr,
+ };
+
+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_LOW_SIGNAL_MESH);
+ os_memset(macaddr, 0, ETH_ALEN);
+
+ return send_and_recv_msgs(drv, msg, netdev_info_handler, &info);
+}
static int nl80211_get_ext_capab(void *priv, enum wpa_driver_if_type type,
const u8 **ext_capa, const u8 **ext_capa_mask,
.join_mesh = wpa_driver_nl80211_join_mesh,
.leave_mesh = wpa_driver_nl80211_leave_mesh,
.probe_mesh_link = nl80211_probe_mesh_link,
+ .get_worst_mesh = nl80211_get_low_signal_mesh,
#endif /* CONFIG_MESH */
.br_add_ip_neigh = wpa_driver_br_add_ip_neigh,
.br_delete_ip_neigh = wpa_driver_br_delete_ip_neigh,
index 6f09d1500960d98eb7cc35bfe9970e25aad728d9..1aec5da6b394fe0fd3ea75ea5fa4af041c24b1db 100644 (file)
NL80211_CMD_PROBE_MESH_LINK,
+
+ NL80211_CMD_GET_LOW_SIGNAL_MESH,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
index d5c5c00a9dfb78ae8fd6d7902341cf1a1858514d..4f472cbc54229f49491dc2851b914e6fbecd0b2b 100644 (file)
#define DEFAULT_BG_SCAN_PERIOD -1
#define DEFAULT_MESH_MAX_RETRIES 2
-#define DEFAULT_MESH_RETRY_TIMEOUT 40
+#define DEFAULT_MESH_RETRY_TIMEOUT 100
#define DEFAULT_MESH_CONFIRM_TIMEOUT 40
#define DEFAULT_MESH_HOLDING_TIMEOUT 40
#define DEFAULT_MESH_RSSI_THRESHOLD 1 /* no change */
index 656ccb1c560d28bc0b88a93e2a44f6b245d0e249..60bf6e5c38fc597b1f0b83e5baef68a264af3de4 100644 (file)
return -1;
}
+static inline int wpa_drv_get_worst_mesh_point(struct wpa_supplicant *wpa_s, u8 *macaddr)
+{
+ if (wpa_s->driver->get_worst_mesh)
+ return wpa_s->driver->get_worst_mesh(wpa_s->drv_priv, macaddr);
+ return -1;
+}
+
static inline int wpa_drv_scan(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *params)
{
index ed5d34fe765380287c04df832eaacb2f0f7ed9d9..22fdca60c0259c8390b626e5407acef4321a8335 100644 (file)
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
if (ssid->mode != WPAS_MODE_MESH && !bss_is_ess(bss) &&
!bss_is_pbss(bss)) {
- if (debug_print)
- wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - not ESS, PBSS, or MBSS");
+ wpa_dbg(wpa_s, MSG_DEBUG, " skip - neither ESS nor PBSS network");
continue;
}
int only_first_ssid)
{
unsigned int i;
+ struct wpa_ssid *temp_selected_ssid = NULL;
+ struct wpa_bss *temp_bss = NULL;
if (wpa_s->current_ssid) {
struct wpa_ssid *ssid;
wpa_s->owe_transition_select = 0;
if (!*selected_ssid)
continue;
+#ifdef CONFIG_MESH
+ /*if this is mesh - need to make sure selected is accapting new connections*/
+ if (wpa_s->ifmsh) {
+ const u8 *mesh_ie = wpa_bss_get_ie(bss, WLAN_EID_MESH_CONFIG);
+ if (!mesh_ie) {
+ *selected_ssid = NULL;
+ continue;
+ }
+ if (!(mesh_ie[8] & 0x1)) {
+ /* Mesh not accapting new connections - save it for later*/
+ wpa_dbg(wpa_s, MSG_DEBUG, "Skip selected for now - MP not accapting new links");
+ if (!temp_selected_ssid) {
+ temp_selected_ssid = *selected_ssid;
+ temp_bss = bss;
+ }
+ *selected_ssid = NULL;
+ continue;
+ }
+ }
+#endif /*CONFIG_MESH*/
+
wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR
" ssid='%s'",
MAC2STR(bss->bssid),
return bss;
}
+ if (temp_selected_ssid) {
+ /* No "accapting" mesh peers - select best "not-accapting"*/
+ *selected_ssid = temp_selected_ssid;
+ wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR
+ " ssid='%s'",
+ MAC2STR(temp_bss->bssid),
+ wpa_ssid_txt(temp_bss->ssid, temp_bss->ssid_len));
+ return temp_bss;
+ }
+
return NULL;
}
return 1;
} else {
#ifdef CONFIG_MESH
- // in case we are running mesh on demand and didn't find our AP we should unblock mesh connections now
- if (wpa_s->global->mesh_on_demand.enabled)
- {
- if (wpa_s != wpa_s->global->mesh_on_demand.mesh_wpa_s)
- {
+ /* in case we are running mesh on demand and didn't find our AP
+ * we should unblock mesh connections now
+ */
+ if (wpa_s->global->mesh_on_demand.enabled) {
+ if (wpa_s != wpa_s->global->mesh_on_demand.mesh_wpa_s) {
wpa_s->global->mesh_on_demand.meshBlocked = FALSE;
wpa_msg(wpa_s, MSG_DEBUG,"Mesh on demand - ********************* MESH IS UNBLOCKED");
}
if (wpa_s->ifmsh) {
wpa_msg(wpa_s, MSG_DEBUG,
"Avoiding join because we already joined a mesh group");
+
+ /* Schedule delayed scan for the mesh interface*/
+ wpa_supplicant_mesh_delayed_scan(wpa_s,
+ MESH_CONNECT_SCAN_PERIOD, 0);
return 0;
}
#endif /* CONFIG_MESH */
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 3dc25b4cde3716bdb07e49fcf9b8e56917025a9e..b328059004263c00793308d949fd15be233cab1b 100644 (file)
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
#include "mesh_mpm.h"
#include "mesh_rsn.h"
#include "mesh.h"
+#include "scan.h"
#include "../src/drivers/driver_nl80211.h"
+/* Time for initial mesh connection after join*/
+#define INIT_MESH_CONNECTION_TIME 3
+
static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
{
wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh);
* anyway, so it's not urgent */
}
+static void mesh_delayed_scan_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+
+ /* Mesh will only scan if it currently has no links*/
+ if (hapd->num_plinks == 0) {
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ }
+}
+
+void wpa_supplicant_mesh_delayed_scan(struct wpa_supplicant *wpa_s,
+ int sec, int usec)
+{
+ eloop_register_timeout(sec, usec,
+ mesh_delayed_scan_timeout,
+ wpa_s, NULL);
+}
void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s,
struct hostapd_iface *ifmsh)
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+ /* Schedule delayed scan for the mesh interface */
+ wpa_supplicant_mesh_delayed_scan(wpa_s, INIT_MESH_CONNECTION_TIME, 0);
+
out:
return ret;
}
diff --git a/wpa_supplicant/mesh.h b/wpa_supplicant/mesh.h
index 36128c97b42a304f70e80394877e0a53c64d5c46..2ee36d7f3437344bbad9c93754512464e0b40055 100644 (file)
--- a/wpa_supplicant/mesh.h
+++ b/wpa_supplicant/mesh.h
#ifndef MESH_H
#define MESH_H
+#define MESH_CONNECT_SCAN_PERIOD 30
+
int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid);
int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s);
+void wpa_supplicant_mesh_delayed_scan(struct wpa_supplicant *wpa_s,
+ int sec, int usec);
void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s,
struct hostapd_iface *ifmsh);
int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf,
void wpa_supplicant_leave_mesh_initiate(struct wpa_supplicant *wpa_s);
+extern void wpa_mesh_connect(struct wpa_supplicant *wpa_s, const u8 *addr,
+ u8 *ies, size_t ie_len);
#ifdef CONFIG_MESH
void wpa_mesh_notify_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
index c67141a64764898c2fd28f9aa9d5d375d3b8afbc..b4f50747f2070957248c62385ca4c037f62dd99a 100644 (file)
#include "config.h"
#include "../src/drivers/driver_nl80211.h"
+
+#define SWITCH_CONN_TIMEOUT 2
+#define EXTENDED_RETRY_TIMEOUT 200
+
struct mesh_peer_mgmt_ie {
const u8 *proto_id; /* Mesh Peering Protocol Identifier (2 octets) */
const u8 *llid; /* Local Link ID (2 octets) */
}
+static void start_mesh_switch_connection(struct wpa_supplicant *wpa_s,
+ const struct ieee80211_mgmt *mgmt,
+ size_t len)
+{
+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+ u8 macaddr[ETH_ALEN] = {0};
+
+ /* Already switching*/
+ if (hapd->mesh_switch_connection)
+ return;
+
+ /* Links state unstable (during connect/disconnect)*/
+ if (hapd->num_plinks < hapd->num_sta)
+ return;
+
+ wpa_msg(wpa_s, MSG_DEBUG, "Starting switch connection process");
+
+ /* Mark beginning of the switch connection */
+ hapd->mesh_switch_connection = TRUE;
+ os_memset(hapd->mesh_beacon_pending_peer, 0, ETH_ALEN);
+
+ /* Save pending action if needed*/
+ if (mgmt)
+ hapd->mesh_pending_action = wpabuf_alloc_copy(mgmt, len);
+
+ /* Find a candidate for disconnect*/
+ if (wpa_drv_get_worst_mesh_point(wpa_s, macaddr)) {
+ wpa_msg(wpa_s, MSG_DEBUG, "Cannot find a candidate for disconnect");
+ goto fail;
+ }
+
+ /* Found a candidate - disconnect it. Upon completing disconnection,
+ new connection will be triggered */
+ if (!mesh_mpm_close_peer(wpa_s, macaddr))
+ return;
+
+fail:
+ /* Mark ending of switch connection process*/
+ hapd->mesh_switch_connection = FALSE;
+
+ /* Release pending*/
+ wpabuf_free(hapd->mesh_pending_action);
+ hapd->mesh_pending_action = NULL;
+}
+
+static void switch_connection_timer(void *eloop_ctx, void *user_data)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
+
+ /* Didn't receive the required beacon,
+ * cancel the process
+ */
+ hapd->mesh_switch_connection = FALSE;
+ wpabuf_free(hapd->mesh_pending_auth);
+ hapd->mesh_pending_auth = NULL;
+ os_memset(hapd->mesh_beacon_pending_peer, 0, ETH_ALEN);
+}
+
+
/* configure peering state in ours and driver's station entry */
void wpa_mesh_set_plink_state(struct wpa_supplicant *wpa_s,
struct sta_info *sta,
break;
case PLINK_HOLDING:
/* holding timer */
-
- if (sta->mesh_sae_pmksa_caching) {
- wpa_printf(MSG_DEBUG, "MPM: Peer " MACSTR
+ if (sta->mesh_sae_pmksa_caching ||
+ hapd->mesh_switch_connection) {
+ wpa_printf(MSG_DEBUG, "MPM: Peer " MACSTR
" looks like it does not support mesh SAE PMKSA caching, so remove the cached entry for it",
MAC2STR(sta->addr));
wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
}
+
mesh_mpm_fsm_restart(wpa_s, sta);
if (wpa_s->global->mesh_on_demand.enabled &&
hapd && (hapd->num_plinks == 0)) {
wpa_s->global->mesh_on_demand.anyMeshConnected = FALSE;
}
+
+ /* If this is switch connection process - trigger new connection*/
+ if (hapd->mesh_switch_connection) {
+ if (hapd->mesh_pending_action) {
+ /* open connection*/
+ hapd->mesh_switch_connection = FALSE;
+ mesh_mpm_action_rx(wpa_s,
+ wpabuf_head(hapd->mesh_pending_action),
+ wpabuf_len(hapd->mesh_pending_action));
+ hapd->mesh_pending_action = NULL;
+ } else if (hapd->mesh_pending_auth) {
+ /* secured connection*/
+ const struct ieee80211_mgmt *mgmt =
+ wpabuf_head(hapd->mesh_pending_auth);
+ /* Save the mac addr of the pending peer */
+ os_memcpy(hapd->mesh_beacon_pending_peer, mgmt->sa, ETH_ALEN);
+ /* Start timer on the switch connection process*/
+ eloop_register_timeout(SWITCH_CONN_TIMEOUT, 0,
+ switch_connection_timer,
+ wpa_s, NULL);
+ }
+ }
break;
default:
break;
/* initiate peering with station */
static void mesh_mpm_plink_open(struct wpa_supplicant *wpa_s, struct sta_info *sta,
- enum mesh_plink_state next_state)
+ enum mesh_plink_state next_state, int retry_timeout)
{
- struct mesh_conf *conf = wpa_s->ifmsh->mconf;
-
eloop_cancel_timeout(plink_timer, wpa_s, sta);
- eloop_register_timeout(conf->dot11MeshRetryTimeout / 1000,
- (conf->dot11MeshRetryTimeout % 1000) * 1000,
+ eloop_register_timeout(retry_timeout / 1000,
+ (retry_timeout % 1000) * 1000,
plink_timer, wpa_s, sta);
mesh_mpm_send_plink_action(wpa_s, sta, PLINK_OPEN, 0);
wpa_mesh_set_plink_state(wpa_s, sta, next_state);
}
if (conf->security == MESH_CONF_SEC_NONE) {
- mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT);
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT, conf->dot11MeshRetryTimeout);
} else {
mesh_rsn_auth_sae_sta(wpa_s, sta);
os_memcpy(hapd->mesh_required_peer, addr, ETH_ALEN);
if (!sta->my_lid)
mesh_mpm_init_link(wpa_s, sta);
- mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT);
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT,
+ wpa_s->ifmsh->mconf->dot11MeshRetryTimeout);
}
/*
#endif /* CONFIG_IEEE80211N */
int ret;
- if (elems->mesh_config_len >= 7 &&
- !(elems->mesh_config[6] & MESH_CAP_ACCEPT_ADDITIONAL_PEER)) {
- wpa_msg(wpa_s, MSG_DEBUG,
- "mesh: Ignore a crowded peer " MACSTR,
- MAC2STR(addr));
+ sta = ap_sta_add(data, addr);
+ if (!sta)
return NULL;
- }
-
- sta = ap_get_sta(data, addr);
- if (!sta) {
- sta = ap_sta_add(data, addr);
- if (!sta)
- return NULL;
- }
/* Set WMM by default since Mesh STAs are QoS STAs */
sta->flags |= WLAN_STA_WMM;
struct os_reltime age;
struct hostapd_frame_info fi;
-
if (wpa_s->ifmsh->mesh_deinit_process)
- return;
+ return;
+
+ /* in switch connection process we might be waiting for a beacon from
+ * a specific peer to trigger connection and complete the process.
+ * Otherwise, drop all beacons.
+ */
+ if (data->mesh_switch_connection) {
+ if (os_memcmp(data->mesh_beacon_pending_peer, addr, ETH_ALEN) != 0)
+ return;
+
+ eloop_cancel_timeout(switch_connection_timer, wpa_s, NULL);
+ wpabuf_free(data->mesh_pending_auth);
+ data->mesh_pending_auth = NULL;
+ os_memset(data->mesh_beacon_pending_peer, 0, ETH_ALEN);
+ data->mesh_switch_connection = FALSE;
+ }
if ((wpa_s->global->mesh_on_demand.enabled) && (wpa_s->global->mesh_on_demand.meshBlocked)) {
if (!data->mesh_pending_auth)
mgmt = wpabuf_head(data->mesh_pending_auth);
os_reltime_age(&data->mesh_pending_auth_time, &age);
if (age.sec < 2 && os_memcmp(mgmt->sa, addr, ETH_ALEN) == 0) {
- data->mesh_pending_auth = FALSE;
+ wpabuf_free(data->mesh_pending_auth);
+ data->mesh_pending_auth = NULL;
} else
return;
}
/* check if peer accepts new connection. Don't initiate link if peer is full*/
- if ((ssid && ssid->no_auto_peer &&
- (is_zero_ether_addr(data->mesh_required_peer) ||
- os_memcmp(data->mesh_required_peer, addr, ETH_ALEN) != 0)) ||
- !(mesh_conf_ie->capab & WLAN_MESHCONF_CAPAB_ACCEPT_PLINKS)) {
+ if (!(mesh_conf_ie->capab & WLAN_MESHCONF_CAPAB_ACCEPT_PLINKS))
+ return;
+
+ if (ssid && ssid->no_auto_peer &&
+ (is_zero_ether_addr(data->mesh_required_peer) ||
+ os_memcmp(data->mesh_required_peer, addr, ETH_ALEN) != 0)) {
wpa_msg(wpa_s, MSG_ERROR, "will not initiate new peer link with "
- MACSTR " either no_auto_peer or peer does not allow new links", MAC2STR(addr));
+ MACSTR " no_auto_peer", MAC2STR(addr));
if (data->mesh_pending_auth) {
mgmt = wpabuf_head(data->mesh_pending_auth);
return;
}
+ return;
+ }
+
+ sta = mesh_mpm_add_peer(wpa_s, addr, elems);
+ if (!sta) {
+ if (!data->mesh_pending_auth)
+ return;
+
+ /* If we are full, we need to check if we have a pending auth.
+ * if so, we would like to try and switch connections to help
+ * the requesting MP.
+ */
+ mgmt = wpabuf_head(data->mesh_pending_auth);
+ os_reltime_age(&data->mesh_pending_auth_time, &age);
+ if (age.sec < 2 && os_memcmp(mgmt->sa, addr, ETH_ALEN) == 0) {
+ /* If peer has other links - ignore the pending auth */
+ if (elems->mesh_config_len && ((elems->mesh_config[5]>>1) & 0x3F))
+ return;
+ /*Peer has no other links - lets try to help*/
+ start_mesh_switch_connection(wpa_s, NULL, 0);
+ }
+
+ return;
+ }
+
+ if (conf->security == MESH_CONF_SEC_NONE) {
+ if (sta->plink_state < PLINK_OPN_SNT ||
+ sta->plink_state > PLINK_ESTAB)
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT, conf->dot11MeshRetryTimeout);
+ } else {
+ mesh_rsn_auth_sae_sta(wpa_s, sta);
+ }
+}
+
+void wpa_mesh_connect(struct wpa_supplicant *wpa_s, const u8 *addr,
+ u8 *ies, size_t ie_len)
+{
+ struct mesh_conf *conf = wpa_s->ifmsh->mconf;
+ struct ieee802_11_elems elems;
+ struct sta_info *sta;
+ if (ieee802_11_parse_elems(ies, ie_len, &elems, 0) == ParseFailed) {
+ wpa_msg(wpa_s, MSG_INFO, "Could not parse beacon from " MACSTR,
+ MAC2STR(addr));
return;
}
- sta = mesh_mpm_add_peer(wpa_s, addr, elems);
+ sta = mesh_mpm_add_peer(wpa_s, addr, &elems);
if (!sta)
return;
if (conf->security == MESH_CONF_SEC_NONE) {
if (sta->plink_state < PLINK_OPN_SNT ||
sta->plink_state > PLINK_ESTAB)
- mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT);
- } else {
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT,
+ EXTENDED_RETRY_TIMEOUT);
+ } else if (sta->plink_state) {
mesh_rsn_auth_sae_sta(wpa_s, sta);
}
}
-
void mesh_mpm_mgmt_rx(struct wpa_supplicant *wpa_s, struct rx_mgmt *rx_mgmt)
{
struct hostapd_frame_info fi;
mesh_mpm_fsm_restart(wpa_s, sta);
break;
case OPN_ACPT:
- mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_RCVD);
+ mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_RCVD, conf->dot11MeshRetryTimeout);
mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CONFIRM,
0);
break;
@@ -1261,17 +1396,42 @@ static void mesh_mpm_fsm(struct wpa_supplicant *wpa_s, struct sta_info *sta,
case PLINK_HOLDING:
switch (event) {
case CLS_ACPT:
- mesh_mpm_fsm_restart(wpa_s, sta);
- if ( (hapd) && (hapd->num_plinks == 0) )
- {
+ if (hapd->mesh_switch_connection)
+ wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
+ mesh_mpm_fsm_restart(wpa_s, sta);
+
+ if (hapd && (hapd->num_plinks == 0)) {
wpa_s->global->mesh_on_demand.anyMeshConnected = FALSE;
- if ( (wpa_s->ifmsh) && (wpa_s->ifmsh->mesh_deinit_process))
+ if ((wpa_s->ifmsh) && (wpa_s->ifmsh->mesh_deinit_process))
wpa_supplicant_leave_mesh(wpa_s);
}
+
+ /* If this is switch connection process - trigger new connection*/
+ if (hapd->mesh_switch_connection) {
+ if (hapd->mesh_pending_action) {
+ /* open connection*/
+ hapd->mesh_switch_connection = FALSE;
+ mesh_mpm_action_rx(wpa_s,
+ wpabuf_head(hapd->mesh_pending_action),
+ wpabuf_len(hapd->mesh_pending_action));
+ hapd->mesh_pending_action = NULL;
+ } else if (hapd->mesh_pending_auth) {
+ /* secured connection*/
+ const struct ieee80211_mgmt *mgmt =
+ wpabuf_head(hapd->mesh_pending_auth);
+ /* Save the mac addr of the pending peer */
+ os_memcpy(hapd->mesh_beacon_pending_peer, mgmt->sa, ETH_ALEN);
+ /* Start timer on the switch connection process*/
+ eloop_register_timeout(SWITCH_CONN_TIMEOUT, 0,
+ switch_connection_timer,
+ wpa_s, NULL);
+ }
+ }
break;
+
case OPN_ACPT:
case CNF_ACPT:
case OPN_RJCT:
if (!sta) {
wpa_printf(MSG_DEBUG, "MPM: No STA entry for peer");
+
+ /* If peer has other links - ignore this action */
+ if (elems.mesh_config_len && ((elems.mesh_config[5]>>1) & 0x3F))
+ return;
+
+ /*Peer has no other links - lets try to help*/
+ start_mesh_switch_connection(wpa_s, mgmt, len);
return;
}
if (hapd->num_plinks == 0) {
struct wpa_supplicant *wpa_s = hapd->iface->owner;
wpa_s->global->mesh_on_demand.anyMeshConnected = FALSE;
+ /* trigger scan in 1.1sec - enough time to create new links*/
+ wpa_supplicant_mesh_delayed_scan(wpa_s, 1, 100000);
}
}
index 4b00945394143fc526fc861d28814f2be1df305e..6f4abf31932a93d87b3b10ab3f9053ed59c4023f 100644 (file)
/* notify MPM of new mesh peer to be inserted in MPM and driver */
void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
struct ieee802_11_elems *elems);
+void wpa_mesh_connect(struct wpa_supplicant *wpa_s, const u8 *addr,
+ u8 *ies, size_t ie_len);
void mesh_mpm_close_links(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh);
void mesh_mpm_auth_peer(struct wpa_supplicant *wpa_s, const u8 *addr);
void mesh_mpm_free_sta(struct hostapd_data *hapd, struct sta_info *sta);
index 4b8d6c46917315b277dcc5562a6645a39a55aa28..fcd46604a390d6c3dd75d192e937378803d6e4e7 100644 (file)
return -1;
}
+ if (sta->sae && sta->sae->state > SAE_NOTHING) {
+ wpa_msg(wpa_s, MSG_DEBUG,
+ "AUTH: No nested connections!!");
+ return -1;
+ }
+
if (!sta->sae) {
sta->sae = os_zalloc(sizeof(*sta->sae));
if (sta->sae == NULL)
index 0c33b20559256bbe35a063b5a70807009db0c958..25eeb3d2834b6cf2ad89d6fb4558fdbabb92788f 100644 (file)
return;
}
}
-
- if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
- wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
- return;
+ if (wpa_s->ifmsh) {
+ wpa_mesh_connect(wpa_s, bss->bssid,
+ (u8*) (bss + 1),
+ bss->ie_len);
+ } else {
+ if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) {
+ wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh");
+ return;
+ }
+ wpa_s->current_bss = bss;
+ wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
+ ssid->id);
+ wpas_notify_mesh_group_started(wpa_s, ssid);
}
- wpa_s->current_bss = bss;
- wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len),
- ssid->id);
- wpas_notify_mesh_group_started(wpa_s, ssid);
#else /* CONFIG_MESH */
wpa_msg(wpa_s, MSG_ERROR,
"mesh mode support not included in the build");
#endif /* CONFIG_MESH */
+
return;
}