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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_mgmt *mgmt,
|
||||
struct ieee802_11_elems *elems)
|
||||
{
|
||||
|
||||
struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg;
|
||||
enum ieee80211_self_protected_actioncode action = 0;
|
||||
struct sta_info *sta;
|
||||
enum plink_event event;
|
||||
enum ieee80211_self_protected_actioncode ftype;
|
||||
bool matches_local;
|
||||
u32 changed = 0;
|
||||
u8 ie_len;
|
||||
__le16 plid, llid;
|
||||
__le16 plid, llid = 0;
|
||||
|
||||
if (!elems->peering) {
|
||||
mpl_dbg(sdata,
|
||||
|
@ -847,146 +998,7 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
|
|||
sta->plid = plid;
|
||||
}
|
||||
|
||||
mpl_dbg(sdata, "peer %pM in state %s got event %s\n", mgmt->sa,
|
||||
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);
|
||||
}
|
||||
}
|
||||
changed |= mesh_plink_fsm(sdata, sta, event);
|
||||
|
||||
unlock_rcu:
|
||||
rcu_read_unlock();
|
||||
|
|
Loading…
Add table
Reference in a new issue