mac80211: factor out peering FSM
authorThomas Pedersen <thomas@cozybit.com>
Tue, 5 Nov 2013 19:17:02 +0000 (11:17 -0800)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 25 Nov 2013 19:50:23 +0000 (20:50 +0100)
Signed-off-by: Thomas Pedersen <thomas@cozybit.com>
[fix some indentation, squash llid assignment]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/mesh_plink.c

index fa86d354f622bb861f262bd7fa93f90b34247f3c..4311d4571ec872355538d5622843f7720e337a43 100644 (file)
@@ -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();