mac80211: factor out peering FSM
Signed-off-by: Thomas Pedersen <thomas@cozybit.com> [fix some indentation, squash llid assignment] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
5bbdd6c646
commit
c7e678115a
1 changed files with 155 additions and 143 deletions
|
@ -691,21 +691,172 @@ static u32 mesh_plink_establish(struct ieee80211_sub_if_data *sdata,
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mesh_plink_fsm - step @sta MPM based on @event
|
||||||
|
*
|
||||||
|
* @sdata: interface
|
||||||
|
* @sta: mesh neighbor
|
||||||
|
* @event: peering event
|
||||||
|
*
|
||||||
|
* Return: changed MBSS flags
|
||||||
|
*/
|
||||||
|
static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct sta_info *sta, enum plink_event event)
|
||||||
|
{
|
||||||
|
struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
|
||||||
|
enum ieee80211_self_protected_actioncode action = 0;
|
||||||
|
u32 changed = 0;
|
||||||
|
|
||||||
|
mpl_dbg(sdata, "peer %pM in state %s got event %s\n", sta->sta.addr,
|
||||||
|
mplstates[sta->plink_state], mplevents[event]);
|
||||||
|
|
||||||
|
spin_lock_bh(&sta->lock);
|
||||||
|
switch (sta->plink_state) {
|
||||||
|
case NL80211_PLINK_LISTEN:
|
||||||
|
switch (event) {
|
||||||
|
case CLS_ACPT:
|
||||||
|
mesh_plink_fsm_restart(sta);
|
||||||
|
break;
|
||||||
|
case OPN_ACPT:
|
||||||
|
sta->plink_state = NL80211_PLINK_OPN_RCVD;
|
||||||
|
get_random_bytes(&sta->llid, 2);
|
||||||
|
mesh_plink_timer_set(sta,
|
||||||
|
mshcfg->dot11MeshRetryTimeout);
|
||||||
|
|
||||||
|
/* set the non-peer mode to active during peering */
|
||||||
|
changed |= ieee80211_mps_local_status_update(sdata);
|
||||||
|
action = WLAN_SP_MESH_PEERING_OPEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NL80211_PLINK_OPN_SNT:
|
||||||
|
switch (event) {
|
||||||
|
case OPN_RJCT:
|
||||||
|
case CNF_RJCT:
|
||||||
|
case CLS_ACPT:
|
||||||
|
mesh_plink_close(sdata, sta, event);
|
||||||
|
action = WLAN_SP_MESH_PEERING_CLOSE;
|
||||||
|
break;
|
||||||
|
case OPN_ACPT:
|
||||||
|
/* retry timer is left untouched */
|
||||||
|
sta->plink_state = NL80211_PLINK_OPN_RCVD;
|
||||||
|
action = WLAN_SP_MESH_PEERING_CONFIRM;
|
||||||
|
break;
|
||||||
|
case CNF_ACPT:
|
||||||
|
sta->plink_state = NL80211_PLINK_CNF_RCVD;
|
||||||
|
if (!mod_plink_timer(sta,
|
||||||
|
mshcfg->dot11MeshConfirmTimeout))
|
||||||
|
sta->ignore_plink_timer = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NL80211_PLINK_OPN_RCVD:
|
||||||
|
switch (event) {
|
||||||
|
case OPN_RJCT:
|
||||||
|
case CNF_RJCT:
|
||||||
|
case CLS_ACPT:
|
||||||
|
mesh_plink_close(sdata, sta, event);
|
||||||
|
action = WLAN_SP_MESH_PEERING_CLOSE;
|
||||||
|
break;
|
||||||
|
case OPN_ACPT:
|
||||||
|
action = WLAN_SP_MESH_PEERING_CONFIRM;
|
||||||
|
break;
|
||||||
|
case CNF_ACPT:
|
||||||
|
changed |= mesh_plink_establish(sdata, sta);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NL80211_PLINK_CNF_RCVD:
|
||||||
|
switch (event) {
|
||||||
|
case OPN_RJCT:
|
||||||
|
case CNF_RJCT:
|
||||||
|
case CLS_ACPT:
|
||||||
|
mesh_plink_close(sdata, sta, event);
|
||||||
|
action = WLAN_SP_MESH_PEERING_CLOSE;
|
||||||
|
break;
|
||||||
|
case OPN_ACPT:
|
||||||
|
changed |= mesh_plink_establish(sdata, sta);
|
||||||
|
action = WLAN_SP_MESH_PEERING_CONFIRM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NL80211_PLINK_ESTAB:
|
||||||
|
switch (event) {
|
||||||
|
case CLS_ACPT:
|
||||||
|
changed |= __mesh_plink_deactivate(sta);
|
||||||
|
changed |= mesh_set_ht_prot_mode(sdata);
|
||||||
|
changed |= mesh_set_short_slot_time(sdata);
|
||||||
|
mesh_plink_close(sdata, sta, event);
|
||||||
|
action = WLAN_SP_MESH_PEERING_CLOSE;
|
||||||
|
break;
|
||||||
|
case OPN_ACPT:
|
||||||
|
action = WLAN_SP_MESH_PEERING_CONFIRM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NL80211_PLINK_HOLDING:
|
||||||
|
switch (event) {
|
||||||
|
case CLS_ACPT:
|
||||||
|
if (del_timer(&sta->plink_timer))
|
||||||
|
sta->ignore_plink_timer = 1;
|
||||||
|
mesh_plink_fsm_restart(sta);
|
||||||
|
break;
|
||||||
|
case OPN_ACPT:
|
||||||
|
case CNF_ACPT:
|
||||||
|
case OPN_RJCT:
|
||||||
|
case CNF_RJCT:
|
||||||
|
action = WLAN_SP_MESH_PEERING_CLOSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* should not get here, PLINK_BLOCKED is dealt with at the
|
||||||
|
* beginning of the function
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&sta->lock);
|
||||||
|
if (action) {
|
||||||
|
mesh_plink_frame_tx(sdata, action, sta->sta.addr,
|
||||||
|
sta->llid, sta->plid, sta->reason);
|
||||||
|
|
||||||
|
/* also send confirm in open case */
|
||||||
|
if (action == WLAN_SP_MESH_PEERING_OPEN) {
|
||||||
|
mesh_plink_frame_tx(sdata,
|
||||||
|
WLAN_SP_MESH_PEERING_CONFIRM,
|
||||||
|
sta->sta.addr, sta->llid,
|
||||||
|
sta->plid, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
|
mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_mgmt *mgmt,
|
struct ieee80211_mgmt *mgmt,
|
||||||
struct ieee802_11_elems *elems)
|
struct ieee802_11_elems *elems)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
|
|
||||||
enum ieee80211_self_protected_actioncode action = 0;
|
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
enum plink_event event;
|
enum plink_event event;
|
||||||
enum ieee80211_self_protected_actioncode ftype;
|
enum ieee80211_self_protected_actioncode ftype;
|
||||||
bool matches_local;
|
bool matches_local;
|
||||||
u32 changed = 0;
|
u32 changed = 0;
|
||||||
u8 ie_len;
|
u8 ie_len;
|
||||||
__le16 plid, llid;
|
__le16 plid, llid = 0;
|
||||||
|
|
||||||
if (!elems->peering) {
|
if (!elems->peering) {
|
||||||
mpl_dbg(sdata,
|
mpl_dbg(sdata,
|
||||||
|
@ -847,146 +998,7 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
|
||||||
sta->plid = plid;
|
sta->plid = plid;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpl_dbg(sdata, "peer %pM in state %s got event %s\n", mgmt->sa,
|
changed |= mesh_plink_fsm(sdata, sta, event);
|
||||||
mplstates[sta->plink_state], mplevents[event]);
|
|
||||||
spin_lock_bh(&sta->lock);
|
|
||||||
switch (sta->plink_state) {
|
|
||||||
case NL80211_PLINK_LISTEN:
|
|
||||||
switch (event) {
|
|
||||||
case CLS_ACPT:
|
|
||||||
mesh_plink_fsm_restart(sta);
|
|
||||||
break;
|
|
||||||
case OPN_ACPT:
|
|
||||||
sta->plink_state = NL80211_PLINK_OPN_RCVD;
|
|
||||||
get_random_bytes(&llid, 2);
|
|
||||||
sta->llid = llid;
|
|
||||||
mesh_plink_timer_set(sta,
|
|
||||||
mshcfg->dot11MeshRetryTimeout);
|
|
||||||
|
|
||||||
/* set the non-peer mode to active during peering */
|
|
||||||
changed |= ieee80211_mps_local_status_update(sdata);
|
|
||||||
|
|
||||||
action = WLAN_SP_MESH_PEERING_OPEN;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NL80211_PLINK_OPN_SNT:
|
|
||||||
switch (event) {
|
|
||||||
case OPN_RJCT:
|
|
||||||
case CNF_RJCT:
|
|
||||||
case CLS_ACPT:
|
|
||||||
mesh_plink_close(sdata, sta, event);
|
|
||||||
action = WLAN_SP_MESH_PEERING_CLOSE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPN_ACPT:
|
|
||||||
/* retry timer is left untouched */
|
|
||||||
sta->plink_state = NL80211_PLINK_OPN_RCVD;
|
|
||||||
action = WLAN_SP_MESH_PEERING_CONFIRM;
|
|
||||||
break;
|
|
||||||
case CNF_ACPT:
|
|
||||||
sta->plink_state = NL80211_PLINK_CNF_RCVD;
|
|
||||||
if (!mod_plink_timer(sta,
|
|
||||||
mshcfg->dot11MeshConfirmTimeout))
|
|
||||||
sta->ignore_plink_timer = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NL80211_PLINK_OPN_RCVD:
|
|
||||||
switch (event) {
|
|
||||||
case OPN_RJCT:
|
|
||||||
case CNF_RJCT:
|
|
||||||
case CLS_ACPT:
|
|
||||||
mesh_plink_close(sdata, sta, event);
|
|
||||||
action = WLAN_SP_MESH_PEERING_CLOSE;
|
|
||||||
break;
|
|
||||||
case OPN_ACPT:
|
|
||||||
action = WLAN_SP_MESH_PEERING_CONFIRM;
|
|
||||||
break;
|
|
||||||
case CNF_ACPT:
|
|
||||||
changed |= mesh_plink_establish(sdata, sta);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NL80211_PLINK_CNF_RCVD:
|
|
||||||
switch (event) {
|
|
||||||
case OPN_RJCT:
|
|
||||||
case CNF_RJCT:
|
|
||||||
case CLS_ACPT:
|
|
||||||
mesh_plink_close(sdata, sta, event);
|
|
||||||
action = WLAN_SP_MESH_PEERING_CLOSE;
|
|
||||||
break;
|
|
||||||
case OPN_ACPT:
|
|
||||||
changed |= mesh_plink_establish(sdata, sta);
|
|
||||||
action = WLAN_SP_MESH_PEERING_CONFIRM;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NL80211_PLINK_ESTAB:
|
|
||||||
switch (event) {
|
|
||||||
case CLS_ACPT:
|
|
||||||
changed |= __mesh_plink_deactivate(sta);
|
|
||||||
changed |= mesh_set_ht_prot_mode(sdata);
|
|
||||||
changed |= mesh_set_short_slot_time(sdata);
|
|
||||||
mesh_plink_close(sdata, sta, event);
|
|
||||||
action = WLAN_SP_MESH_PEERING_CLOSE;
|
|
||||||
break;
|
|
||||||
case OPN_ACPT:
|
|
||||||
action = WLAN_SP_MESH_PEERING_CONFIRM;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NL80211_PLINK_HOLDING:
|
|
||||||
switch (event) {
|
|
||||||
case CLS_ACPT:
|
|
||||||
if (del_timer(&sta->plink_timer))
|
|
||||||
sta->ignore_plink_timer = 1;
|
|
||||||
mesh_plink_fsm_restart(sta);
|
|
||||||
break;
|
|
||||||
case OPN_ACPT:
|
|
||||||
case CNF_ACPT:
|
|
||||||
case OPN_RJCT:
|
|
||||||
case CNF_RJCT:
|
|
||||||
action = WLAN_SP_MESH_PEERING_CLOSE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* should not get here, PLINK_BLOCKED is dealt with at the
|
|
||||||
* beginning of the function
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
spin_unlock_bh(&sta->lock);
|
|
||||||
if (action) {
|
|
||||||
mesh_plink_frame_tx(sdata, action, sta->sta.addr,
|
|
||||||
sta->llid, sta->plid, sta->reason);
|
|
||||||
|
|
||||||
/* also send confirm in open case */
|
|
||||||
if (action == WLAN_SP_MESH_PEERING_OPEN) {
|
|
||||||
mesh_plink_frame_tx(sdata,
|
|
||||||
WLAN_SP_MESH_PEERING_CONFIRM,
|
|
||||||
sta->sta.addr, sta->llid,
|
|
||||||
sta->plid, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock_rcu:
|
unlock_rcu:
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
Loading…
Reference in a new issue