linux/net/mac80211/mesh_plink.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2008 open80211s Ltd.
   3 * Author:     Luis Carlos Cobo <luisca@cozybit.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 */
   9#include <linux/kernel.h>
  10#include <linux/random.h>
  11#include "ieee80211_i.h"
  12#include "rate.h"
  13#include "mesh.h"
  14
  15#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
  16#define mpl_dbg(fmt, args...)   printk(KERN_DEBUG fmt, ##args)
  17#else
  18#define mpl_dbg(fmt, args...)   do { (void)(0); } while (0)
  19#endif
  20
  21#define PLINK_GET_FRAME_SUBTYPE(p) (p)
  22#define PLINK_GET_LLID(p) (p + 1)
  23#define PLINK_GET_PLID(p) (p + 3)
  24
  25#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
  26                                jiffies + HZ * t / 1000))
  27
  28/* Peer link cancel reasons, all subject to ANA approval */
  29#define MESH_LINK_CANCELLED                     2
  30#define MESH_MAX_NEIGHBORS                      3
  31#define MESH_CAPABILITY_POLICY_VIOLATION        4
  32#define MESH_CLOSE_RCVD                         5
  33#define MESH_MAX_RETRIES                        6
  34#define MESH_CONFIRM_TIMEOUT                    7
  35#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS  8
  36#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9
  37#define MESH_SECURITY_FAILED_VERIFICATION       10
  38
  39#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)
  40#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)
  41#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)
  42#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
  43#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
  44
  45enum plink_frame_type {
  46        PLINK_OPEN = 0,
  47        PLINK_CONFIRM,
  48        PLINK_CLOSE
  49};
  50
  51enum plink_event {
  52        PLINK_UNDEFINED,
  53        OPN_ACPT,
  54        OPN_RJCT,
  55        OPN_IGNR,
  56        CNF_ACPT,
  57        CNF_RJCT,
  58        CNF_IGNR,
  59        CLS_ACPT,
  60        CLS_IGNR
  61};
  62
  63static inline
  64void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
  65{
  66        atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
  67        mesh_accept_plinks_update(sdata);
  68}
  69
  70static inline
  71void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
  72{
  73        atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
  74        mesh_accept_plinks_update(sdata);
  75}
  76
  77/**
  78 * mesh_plink_fsm_restart - restart a mesh peer link finite state machine
  79 *
  80 * @sta: mes peer link to restart
  81 *
  82 * Locking: this function must be called holding sta->lock
  83 */
  84static inline void mesh_plink_fsm_restart(struct sta_info *sta)
  85{
  86        sta->plink_state = PLINK_LISTEN;
  87        sta->llid = sta->plid = sta->reason = 0;
  88        sta->plink_retries = 0;
  89}
  90
  91/*
  92 * NOTE: This is just an alias for sta_info_alloc(), see notes
  93 *       on it in the lifecycle management section!
  94 */
  95static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
  96                                         u8 *hw_addr, u32 rates)
  97{
  98        struct ieee80211_local *local = sdata->local;
  99        struct sta_info *sta;
 100
 101        if (local->num_sta >= MESH_MAX_PLINKS)
 102                return NULL;
 103
 104        sta = sta_info_alloc(sdata, hw_addr, GFP_ATOMIC);
 105        if (!sta)
 106                return NULL;
 107
 108        sta->flags = WLAN_STA_AUTHORIZED;
 109        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
 110        rate_control_rate_init(sta);
 111
 112        return sta;
 113}
 114
 115/**
 116 * mesh_plink_deactivate - deactivate mesh peer link
 117 *
 118 * @sta: mesh peer link to deactivate
 119 *
 120 * All mesh paths with this peer as next hop will be flushed
 121 *
 122 * Locking: the caller must hold sta->lock
 123 */
 124static void __mesh_plink_deactivate(struct sta_info *sta)
 125{
 126        struct ieee80211_sub_if_data *sdata = sta->sdata;
 127
 128        if (sta->plink_state == PLINK_ESTAB)
 129                mesh_plink_dec_estab_count(sdata);
 130        sta->plink_state = PLINK_BLOCKED;
 131        mesh_path_flush_by_nexthop(sta);
 132}
 133
 134/**
 135 * __mesh_plink_deactivate - deactivate mesh peer link
 136 *
 137 * @sta: mesh peer link to deactivate
 138 *
 139 * All mesh paths with this peer as next hop will be flushed
 140 */
 141void mesh_plink_deactivate(struct sta_info *sta)
 142{
 143        spin_lock_bh(&sta->lock);
 144        __mesh_plink_deactivate(sta);
 145        spin_unlock_bh(&sta->lock);
 146}
 147
 148static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 149                enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid,
 150                __le16 reason) {
 151        struct ieee80211_local *local = sdata->local;
 152        struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
 153        struct ieee80211_mgmt *mgmt;
 154        bool include_plid = false;
 155        u8 *pos;
 156        int ie_len;
 157
 158        if (!skb)
 159                return -1;
 160        skb_reserve(skb, local->hw.extra_tx_headroom);
 161        /* 25 is the size of the common mgmt part (24) plus the size of the
 162         * common action part (1)
 163         */
 164        mgmt = (struct ieee80211_mgmt *)
 165                skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action));
 166        memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action));
 167        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
 168                                          IEEE80211_STYPE_ACTION);
 169        memcpy(mgmt->da, da, ETH_ALEN);
 170        memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
 171        /* BSSID is left zeroed, wildcard value */
 172        mgmt->u.action.category = PLINK_CATEGORY;
 173        mgmt->u.action.u.plink_action.action_code = action;
 174
 175        if (action == PLINK_CLOSE)
 176                mgmt->u.action.u.plink_action.aux = reason;
 177        else {
 178                mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0);
 179                if (action == PLINK_CONFIRM) {
 180                        pos = skb_put(skb, 4);
 181                        /* two-byte status code followed by two-byte AID */
 182                        memset(pos, 0, 4);
 183                }
 184                mesh_mgmt_ies_add(skb, sdata);
 185        }
 186
 187        /* Add Peer Link Management element */
 188        switch (action) {
 189        case PLINK_OPEN:
 190                ie_len = 3;
 191                break;
 192        case PLINK_CONFIRM:
 193                ie_len = 5;
 194                include_plid = true;
 195                break;
 196        case PLINK_CLOSE:
 197        default:
 198                if (!plid)
 199                        ie_len = 5;
 200                else {
 201                        ie_len = 7;
 202                        include_plid = true;
 203                }
 204                break;
 205        }
 206
 207        pos = skb_put(skb, 2 + ie_len);
 208        *pos++ = WLAN_EID_PEER_LINK;
 209        *pos++ = ie_len;
 210        *pos++ = action;
 211        memcpy(pos, &llid, 2);
 212        if (include_plid) {
 213                pos += 2;
 214                memcpy(pos, &plid, 2);
 215        }
 216        if (action == PLINK_CLOSE) {
 217                pos += 2;
 218                memcpy(pos, &reason, 2);
 219        }
 220
 221        ieee80211_tx_skb(sdata, skb, 1);
 222        return 0;
 223}
 224
 225void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata,
 226                           bool peer_accepting_plinks)
 227{
 228        struct ieee80211_local *local = sdata->local;
 229        struct sta_info *sta;
 230
 231        rcu_read_lock();
 232
 233        sta = sta_info_get(local, hw_addr);
 234        if (!sta) {
 235                sta = mesh_plink_alloc(sdata, hw_addr, rates);
 236                if (!sta) {
 237                        rcu_read_unlock();
 238                        return;
 239                }
 240                if (sta_info_insert(sta)) {
 241                        rcu_read_unlock();
 242                        return;
 243                }
 244        }
 245
 246        sta->last_rx = jiffies;
 247        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
 248        if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN &&
 249                        sdata->u.mesh.accepting_plinks &&
 250                        sdata->u.mesh.mshcfg.auto_open_plinks)
 251                mesh_plink_open(sta);
 252
 253        rcu_read_unlock();
 254}
 255
 256static void mesh_plink_timer(unsigned long data)
 257{
 258        struct sta_info *sta;
 259        __le16 llid, plid, reason;
 260        struct ieee80211_sub_if_data *sdata;
 261
 262        /*
 263         * This STA is valid because sta_info_destroy() will
 264         * del_timer_sync() this timer after having made sure
 265         * it cannot be readded (by deleting the plink.)
 266         */
 267        sta = (struct sta_info *) data;
 268
 269        spin_lock_bh(&sta->lock);
 270        if (sta->ignore_plink_timer) {
 271                sta->ignore_plink_timer = false;
 272                spin_unlock_bh(&sta->lock);
 273                return;
 274        }
 275        mpl_dbg("Mesh plink timer for %pM fired on state %d\n",
 276                sta->sta.addr, sta->plink_state);
 277        reason = 0;
 278        llid = sta->llid;
 279        plid = sta->plid;
 280        sdata = sta->sdata;
 281
 282        switch (sta->plink_state) {
 283        case PLINK_OPN_RCVD:
 284        case PLINK_OPN_SNT:
 285                /* retry timer */
 286                if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
 287                        u32 rand;
 288                        mpl_dbg("Mesh plink for %pM (retry, timeout): %d %d\n",
 289                                sta->sta.addr, sta->plink_retries,
 290                                sta->plink_timeout);
 291                        get_random_bytes(&rand, sizeof(u32));
 292                        sta->plink_timeout = sta->plink_timeout +
 293                                             rand % sta->plink_timeout;
 294                        ++sta->plink_retries;
 295                        mod_plink_timer(sta, sta->plink_timeout);
 296                        spin_unlock_bh(&sta->lock);
 297                        mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid,
 298                                            0, 0);
 299                        break;
 300                }
 301                reason = cpu_to_le16(MESH_MAX_RETRIES);
 302                /* fall through on else */
 303        case PLINK_CNF_RCVD:
 304                /* confirm timer */
 305                if (!reason)
 306                        reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT);
 307                sta->plink_state = PLINK_HOLDING;
 308                mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
 309                spin_unlock_bh(&sta->lock);
 310                mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid,
 311                                    reason);
 312                break;
 313        case PLINK_HOLDING:
 314                /* holding timer */
 315                del_timer(&sta->plink_timer);
 316                mesh_plink_fsm_restart(sta);
 317                spin_unlock_bh(&sta->lock);
 318                break;
 319        default:
 320                spin_unlock_bh(&sta->lock);
 321                break;
 322        }
 323}
 324
 325static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
 326{
 327        sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
 328        sta->plink_timer.data = (unsigned long) sta;
 329        sta->plink_timer.function = mesh_plink_timer;
 330        sta->plink_timeout = timeout;
 331        add_timer(&sta->plink_timer);
 332}
 333
 334int mesh_plink_open(struct sta_info *sta)
 335{
 336        __le16 llid;
 337        struct ieee80211_sub_if_data *sdata = sta->sdata;
 338
 339        spin_lock_bh(&sta->lock);
 340        get_random_bytes(&llid, 2);
 341        sta->llid = llid;
 342        if (sta->plink_state != PLINK_LISTEN) {
 343                spin_unlock_bh(&sta->lock);
 344                return -EBUSY;
 345        }
 346        sta->plink_state = PLINK_OPN_SNT;
 347        mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
 348        spin_unlock_bh(&sta->lock);
 349        mpl_dbg("Mesh plink: starting establishment with %pM\n",
 350                sta->sta.addr);
 351
 352        return mesh_plink_frame_tx(sdata, PLINK_OPEN,
 353                                   sta->sta.addr, llid, 0, 0);
 354}
 355
 356void mesh_plink_block(struct sta_info *sta)
 357{
 358        spin_lock_bh(&sta->lock);
 359        __mesh_plink_deactivate(sta);
 360        sta->plink_state = PLINK_BLOCKED;
 361        spin_unlock_bh(&sta->lock);
 362}
 363
 364
 365void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
 366                         size_t len, struct ieee80211_rx_status *rx_status)
 367{
 368        struct ieee80211_local *local = sdata->local;
 369        struct ieee802_11_elems elems;
 370        struct sta_info *sta;
 371        enum plink_event event;
 372        enum plink_frame_type ftype;
 373        size_t baselen;
 374        u8 ie_len;
 375        u8 *baseaddr;
 376        __le16 plid, llid, reason;
 377
 378        /* need action_code, aux */
 379        if (len < IEEE80211_MIN_ACTION_SIZE + 3)
 380                return;
 381
 382        if (is_multicast_ether_addr(mgmt->da)) {
 383                mpl_dbg("Mesh plink: ignore frame from multicast address");
 384                return;
 385        }
 386
 387        baseaddr = mgmt->u.action.u.plink_action.variable;
 388        baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;
 389        if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {
 390                baseaddr += 4;
 391                baselen -= 4;
 392        }
 393        ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
 394        if (!elems.peer_link) {
 395                mpl_dbg("Mesh plink: missing necessary peer link ie\n");
 396                return;
 397        }
 398
 399        ftype = *((u8 *)PLINK_GET_FRAME_SUBTYPE(elems.peer_link));
 400        ie_len = elems.peer_link_len;
 401        if ((ftype == PLINK_OPEN && ie_len != 3) ||
 402            (ftype == PLINK_CONFIRM && ie_len != 5) ||
 403            (ftype == PLINK_CLOSE && ie_len != 5 && ie_len != 7)) {
 404                mpl_dbg("Mesh plink: incorrect plink ie length\n");
 405                return;
 406        }
 407
 408        if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) {
 409                mpl_dbg("Mesh plink: missing necessary ie\n");
 410                return;
 411        }
 412        /* Note the lines below are correct, the llid in the frame is the plid
 413         * from the point of view of this host.
 414         */
 415        memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2);
 416        if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 7))
 417                memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2);
 418
 419        rcu_read_lock();
 420
 421        sta = sta_info_get(local, mgmt->sa);
 422        if (!sta && ftype != PLINK_OPEN) {
 423                mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
 424                rcu_read_unlock();
 425                return;
 426        }
 427
 428        if (sta && sta->plink_state == PLINK_BLOCKED) {
 429                rcu_read_unlock();
 430                return;
 431        }
 432
 433        /* Now we will figure out the appropriate event... */
 434        event = PLINK_UNDEFINED;
 435        if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) {
 436                switch (ftype) {
 437                case PLINK_OPEN:
 438                        event = OPN_RJCT;
 439                        break;
 440                case PLINK_CONFIRM:
 441                        event = CNF_RJCT;
 442                        break;
 443                case PLINK_CLOSE:
 444                        /* avoid warning */
 445                        break;
 446                }
 447                spin_lock_bh(&sta->lock);
 448        } else if (!sta) {
 449                /* ftype == PLINK_OPEN */
 450                u32 rates;
 451                if (!mesh_plink_free_count(sdata)) {
 452                        mpl_dbg("Mesh plink error: no more free plinks\n");
 453                        rcu_read_unlock();
 454                        return;
 455                }
 456
 457                rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
 458                sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
 459                if (!sta) {
 460                        mpl_dbg("Mesh plink error: plink table full\n");
 461                        rcu_read_unlock();
 462                        return;
 463                }
 464                if (sta_info_insert(sta)) {
 465                        rcu_read_unlock();
 466                        return;
 467                }
 468                event = OPN_ACPT;
 469                spin_lock_bh(&sta->lock);
 470        } else {
 471                spin_lock_bh(&sta->lock);
 472                switch (ftype) {
 473                case PLINK_OPEN:
 474                        if (!mesh_plink_free_count(sdata) ||
 475                            (sta->plid && sta->plid != plid))
 476                                event = OPN_IGNR;
 477                        else
 478                                event = OPN_ACPT;
 479                        break;
 480                case PLINK_CONFIRM:
 481                        if (!mesh_plink_free_count(sdata) ||
 482                            (sta->llid != llid || sta->plid != plid))
 483                                event = CNF_IGNR;
 484                        else
 485                                event = CNF_ACPT;
 486                        break;
 487                case PLINK_CLOSE:
 488                        if (sta->plink_state == PLINK_ESTAB)
 489                                /* Do not check for llid or plid. This does not
 490                                 * follow the standard but since multiple plinks
 491                                 * per sta are not supported, it is necessary in
 492                                 * order to avoid a livelock when MP A sees an
 493                                 * establish peer link to MP B but MP B does not
 494                                 * see it. This can be caused by a timeout in
 495                                 * B's peer link establishment or B beign
 496                                 * restarted.
 497                                 */
 498                                event = CLS_ACPT;
 499                        else if (sta->plid != plid)
 500                                event = CLS_IGNR;
 501                        else if (ie_len == 7 && sta->llid != llid)
 502                                event = CLS_IGNR;
 503                        else
 504                                event = CLS_ACPT;
 505                        break;
 506                default:
 507                        mpl_dbg("Mesh plink: unknown frame subtype\n");
 508                        spin_unlock_bh(&sta->lock);
 509                        rcu_read_unlock();
 510                        return;
 511                }
 512        }
 513
 514        mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %d %d %d %d\n",
 515                mgmt->sa, sta->plink_state,
 516                le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
 517                event);
 518        reason = 0;
 519        switch (sta->plink_state) {
 520                /* spin_unlock as soon as state is updated at each case */
 521        case PLINK_LISTEN:
 522                switch (event) {
 523                case CLS_ACPT:
 524                        mesh_plink_fsm_restart(sta);
 525                        spin_unlock_bh(&sta->lock);
 526                        break;
 527                case OPN_ACPT:
 528                        sta->plink_state = PLINK_OPN_RCVD;
 529                        sta->plid = plid;
 530                        get_random_bytes(&llid, 2);
 531                        sta->llid = llid;
 532                        mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
 533                        spin_unlock_bh(&sta->lock);
 534                        mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid,
 535                                            0, 0);
 536                        mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr,
 537                                            llid, plid, 0);
 538                        break;
 539                default:
 540                        spin_unlock_bh(&sta->lock);
 541                        break;
 542                }
 543                break;
 544
 545        case PLINK_OPN_SNT:
 546                switch (event) {
 547                case OPN_RJCT:
 548                case CNF_RJCT:
 549                        reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
 550                case CLS_ACPT:
 551                        if (!reason)
 552                                reason = cpu_to_le16(MESH_CLOSE_RCVD);
 553                        sta->reason = reason;
 554                        sta->plink_state = PLINK_HOLDING;
 555                        if (!mod_plink_timer(sta,
 556                                             dot11MeshHoldingTimeout(sdata)))
 557                                sta->ignore_plink_timer = true;
 558
 559                        llid = sta->llid;
 560                        spin_unlock_bh(&sta->lock);
 561                        mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
 562                                            plid, reason);
 563                        break;
 564                case OPN_ACPT:
 565                        /* retry timer is left untouched */
 566                        sta->plink_state = PLINK_OPN_RCVD;
 567                        sta->plid = plid;
 568                        llid = sta->llid;
 569                        spin_unlock_bh(&sta->lock);
 570                        mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
 571                                            plid, 0);
 572                        break;
 573                case CNF_ACPT:
 574                        sta->plink_state = PLINK_CNF_RCVD;
 575                        if (!mod_plink_timer(sta,
 576                                             dot11MeshConfirmTimeout(sdata)))
 577                                sta->ignore_plink_timer = true;
 578
 579                        spin_unlock_bh(&sta->lock);
 580                        break;
 581                default:
 582                        spin_unlock_bh(&sta->lock);
 583                        break;
 584                }
 585                break;
 586
 587        case PLINK_OPN_RCVD:
 588                switch (event) {
 589                case OPN_RJCT:
 590                case CNF_RJCT:
 591                        reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
 592                case CLS_ACPT:
 593                        if (!reason)
 594                                reason = cpu_to_le16(MESH_CLOSE_RCVD);
 595                        sta->reason = reason;
 596                        sta->plink_state = PLINK_HOLDING;
 597                        if (!mod_plink_timer(sta,
 598                                             dot11MeshHoldingTimeout(sdata)))
 599                                sta->ignore_plink_timer = true;
 600
 601                        llid = sta->llid;
 602                        spin_unlock_bh(&sta->lock);
 603                        mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
 604                                            plid, reason);
 605                        break;
 606                case OPN_ACPT:
 607                        llid = sta->llid;
 608                        spin_unlock_bh(&sta->lock);
 609                        mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
 610                                            plid, 0);
 611                        break;
 612                case CNF_ACPT:
 613                        del_timer(&sta->plink_timer);
 614                        sta->plink_state = PLINK_ESTAB;
 615                        mesh_plink_inc_estab_count(sdata);
 616                        spin_unlock_bh(&sta->lock);
 617                        mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
 618                                sta->sta.addr);
 619                        break;
 620                default:
 621                        spin_unlock_bh(&sta->lock);
 622                        break;
 623                }
 624                break;
 625
 626        case PLINK_CNF_RCVD:
 627                switch (event) {
 628                case OPN_RJCT:
 629                case CNF_RJCT:
 630                        reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION);
 631                case CLS_ACPT:
 632                        if (!reason)
 633                                reason = cpu_to_le16(MESH_CLOSE_RCVD);
 634                        sta->reason = reason;
 635                        sta->plink_state = PLINK_HOLDING;
 636                        if (!mod_plink_timer(sta,
 637                                             dot11MeshHoldingTimeout(sdata)))
 638                                sta->ignore_plink_timer = true;
 639
 640                        llid = sta->llid;
 641                        spin_unlock_bh(&sta->lock);
 642                        mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
 643                                            plid, reason);
 644                        break;
 645                case OPN_ACPT:
 646                        del_timer(&sta->plink_timer);
 647                        sta->plink_state = PLINK_ESTAB;
 648                        mesh_plink_inc_estab_count(sdata);
 649                        spin_unlock_bh(&sta->lock);
 650                        mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
 651                                sta->sta.addr);
 652                        mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
 653                                            plid, 0);
 654                        break;
 655                default:
 656                        spin_unlock_bh(&sta->lock);
 657                        break;
 658                }
 659                break;
 660
 661        case PLINK_ESTAB:
 662                switch (event) {
 663                case CLS_ACPT:
 664                        reason = cpu_to_le16(MESH_CLOSE_RCVD);
 665                        sta->reason = reason;
 666                        __mesh_plink_deactivate(sta);
 667                        sta->plink_state = PLINK_HOLDING;
 668                        llid = sta->llid;
 669                        mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
 670                        spin_unlock_bh(&sta->lock);
 671                        mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
 672                                            plid, reason);
 673                        break;
 674                case OPN_ACPT:
 675                        llid = sta->llid;
 676                        spin_unlock_bh(&sta->lock);
 677                        mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
 678                                            plid, 0);
 679                        break;
 680                default:
 681                        spin_unlock_bh(&sta->lock);
 682                        break;
 683                }
 684                break;
 685        case PLINK_HOLDING:
 686                switch (event) {
 687                case CLS_ACPT:
 688                        if (del_timer(&sta->plink_timer))
 689                                sta->ignore_plink_timer = 1;
 690                        mesh_plink_fsm_restart(sta);
 691                        spin_unlock_bh(&sta->lock);
 692                        break;
 693                case OPN_ACPT:
 694                case CNF_ACPT:
 695                case OPN_RJCT:
 696                case CNF_RJCT:
 697                        llid = sta->llid;
 698                        reason = sta->reason;
 699                        spin_unlock_bh(&sta->lock);
 700                        mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr,
 701                                            llid, plid, reason);
 702                        break;
 703                default:
 704                        spin_unlock_bh(&sta->lock);
 705                }
 706                break;
 707        default:
 708                /* should not get here, PLINK_BLOCKED is dealt with at the
 709                 * beggining of the function
 710                 */
 711                spin_unlock_bh(&sta->lock);
 712                break;
 713        }
 714
 715        rcu_read_unlock();
 716}
 717