- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# /space/home/slher/rel/Beken/v6_4_5/macsw/ip/lmac/src/sta/sta_mgmt.c

Go to the documentation of this file.

    00001
    00020 /*
    00021  * INCLUDE FILES
    00022  ****************************************************************************************
    00023  */
    00024 #include "sta_mgmt.h"
    00025 #include "mac_frame.h"
    00026 #include "co_utils.h"
    00027 #include "co_status.h"
    00028 #include "txl_buffer.h"
    00029 #include "txl_frame.h"
    00030 #include "vif_mgmt.h"
    00031 #if (NX_UMAC_PRESENT)
    00032 #include "bam.h"
    00033 #include "mm_task.h"
    00034 #include "apm.h"
    00035 #endif //(NX_UMAC_PRESENT)
    00036 #if (NX_P2P)
    00037 #include "p2p.h"
    00038 #endif //(NX_P2P)
    00039 #if (RW_BFMER_EN)
    00041 #include "bfr.h"
    00042 #endif //(RW_BFMER_EN)
    00043 #if (RW_UMESH_EN)
    00044 #include "mm.h"
    00045 #include "mesh_ps.h"
    00046 #endif //(RW_UMESH_EN)
    00047 #if (NX_UMAC_PRESENT && NX_TDLS)
    00048 #include "tdls.h"
    00049 #endif // (NX_UMAC_PRESENT && NX_TDLS)
    00050
    00051 /*
    00052  * GLOBAL VARIABLES
    00053  ****************************************************************************************
    00054  */
    00055 struct sta_info_env_tag sta_info_env;
    00056 struct sta_info_tag sta_info_tab[STA_MAX];
    00057
    00058 /*
    00059  * FUNCTION DEFINITIONS
    00060  ****************************************************************************************
    00061  */
    00069 static void sta_mgmt_entry_init(struct sta_info_tag *sta)
    00070 {
    00071     #if (NX_TX_FRAME)
    00072     // Free all pending descriptor
    00073     while (!co_list_is_empty(&sta->tx_desc_post))
    00074     {
    00075         // Get first TX desc in the list
    00076         struct txdesc *txdesc = (struct txdesc *)co_list_pop_front(&sta->tx_desc_post);
    00077
    00078         // Insert it back in the list of free TX descriptors
    00079         txl_frame_release(txdesc, true);
    00080     }
    00081     #endif //(NX_TX_FRAME)
    00082
    00083     // Reset table
    00084     memset(sta, 0, sizeof(*sta));
    00085
    00086     #if (NX_UMAC_PRESENT)
    00087     for (int tid = 0; tid < TID_MAX; tid++)
    00088     {
    00089         sta->ba_info[tid].bam_idx_rx = BAM_INVALID_TASK_IDX;
    00090         sta->ba_info[tid].bam_idx_tx = BAM_INVALID_TASK_IDX;
    00091     }
    00092     #endif //(NX_UMAC_PRESENT)
    00093
    00094     // Set the instance number to 0xFF, indicate the sta is free
    00095     sta->inst_nbr = 0xFF;
    00096 }
    00097
    00098 void sta_mgmt_init(void)
    00099 {
    00100     int i;
    00101
    00102     // Initialize STA search lists
    00103     // init free list
    00104     co_list_init(&sta_info_env.free_sta_list);
    00105
    00106     // push all the entries to the free list
    00107     for(i = 0; i < NX_REMOTE_STA_MAX ; i++)
    00108     {
    00109         struct sta_info_tag *sta = &sta_info_tab[i];
    00110         // Init STA info table.
    00111         sta_mgmt_entry_init(sta);
    00112         // Push to free list.
    00113         co_list_push_back(&sta_info_env.free_sta_list, (struct co_list_hdr*)sta);
    00114     }
    00115
    00116     #if NX_UMAC_PRESENT
    00117     // Initialize the BC/MC pseudo stations
    00118     for(i = 0; i < NX_VIRT_DEV_MAX ; i++)
    00119     {
    00120         uint8_t idx = VIF_TO_BCMC_IDX(i);
    00121         struct sta_info_tag *sta = &sta_info_tab[idx];
    00122         struct vif_info_tag *vif = &vif_info_tab[i];
    00123
    00124         // Init STA info table.
    00125         sta_mgmt_entry_init(sta);
    00126
    00127         // Attach the station to its VIF
    00128         sta->inst_nbr = i;
    00129         sta->pol_tbl.buf_ctrl = &txl_buffer_control_desc_bcmc[i];
    00130         sta->ctrl_port_state = PORT_CLOSED;
    00131         sta->sta_sec_info.cur_key = &vif->default_key;
    00132         sta->staid = idx;
    00133         sta->aid = 0;
    00134     }
    00135     #endif
    00136
    00137     #if (RW_MESH_EN && !NX_UMAC_PRESENT)
    00138     // Initialize Mesh Information (for security keys management)
    00139     for (i = 0; i < RW_MESH_LINK_NB; i++)
    00140     {
    00141         sta_info_env.mesh_link_idx[i] = INVALID_STA_IDX;
    00142     }
    00143
    00144     sta_info_env.nb_mesh_sta = 0;
    00145     #endif //(RW_MESH_EN && !NX_UMAC_PRESENT)
    00146 }
    00147
    00148 uint8_t sta_mgmt_register(struct mm_sta_add_req const *param,
    00149                           uint8_t *sta_idx)
    00150 {
    00151     struct sta_info_tag *sta;
    00152     struct sta_info_tag *ref_bssid_sta;
    00153     #if (NX_UMAC_PRESENT || NX_P2P || NX_MULTI_ROLE || RW_MESH_EN || NX_TD_STA || NX_TDLS)
    00154     struct vif_info_tag *vif = &vif_info_tab[param->inst_nbr];
    00155     #endif //(NX_UMAC_PRESENT || NX_P2P || NX_MULTI_ROLE || RW_MESH_EN)
    00156     #if NX_UMAC_PRESENT
    00157     uint32_t time;
    00158     #endif
    00159
    00160     #if (RW_MESH_EN && !NX_UMAC_PRESENT)
    00161     // If Mesh VIF, number of available connection is limited
    00162     if ((vif->type == VIF_MESH_POINT) && (sta_info_env.nb_mesh_sta == RW_MESH_LINK_NB))
    00163     {
    00164         return CO_FAIL;
    00165     }
    00166     #endif //(RW_MESH_EN && !NX_UMAC_PRESENT)
    00167
    00168     // get an entry from the free station list
    00169     sta = (struct sta_info_tag*)co_list_pop_front(&sta_info_env.free_sta_list);
    00170
    00171     // no entries available return immediately
    00172     if (sta == NULL)
    00173         // there are no free tables
    00174         return CO_FAIL;
    00175
    00176     // If required, get a second entry for reference BSSID from the free station list
    00177     if (param->bssid_index)
    00178     {
    00179         ref_bssid_sta = (struct sta_info_tag*)co_list_pop_front(&sta_info_env.free_sta_list);
    00180         if (ref_bssid_sta == NULL)
    00181         {
    00182             // Push back the station entry in the free list
    00183             co_list_push_back(&sta_info_env.free_sta_list, (struct co_list_hdr*)sta);
    00184             return CO_FAIL;
    00185         }
    00186
    00187         // Link the stations together
    00188         sta->linked_sta = ref_bssid_sta;
    00189         ref_bssid_sta->linked_sta = sta;
    00190
    00191         // Configure the required fields the linked station entry
    00192         mac_ref_bssid_get(param->bssid_index, param->max_bssid_ind, &param->mac_addr,
    00193                           &ref_bssid_sta->mac_addr);
    00194         ref_bssid_sta->aid = STA_REF_BSSID_AID;
    00195         ref_bssid_sta->staid = CO_GET_INDEX(ref_bssid_sta, sta_info_tab);
    00196     }
    00197
    00198     // Initialize some fields from the parameters
    00199     sta->mac_addr = param->mac_addr;
    00200     sta->ampdu_spacing_min = co_max(param->ampdu_spacing_min, NX_TX_MPDU_SPACING);
    00201     sta->ampdu_size_max_ht = param->ampdu_size_max_ht;
    00202     sta->ampdu_size_max_vht = param->ampdu_size_max_vht;
    00203     sta->ampdu_size_max_he = param->ampdu_size_max_he;
    00204     sta->paid_gid = param->paid_gid;
    00205     sta->inst_nbr = param->inst_nbr;
    00206
    00207     // Get the station index
    00208     *sta_idx = CO_GET_INDEX(sta, sta_info_tab);
    00209     sta->staid = *sta_idx;
    00210     #if (NX_TDLS)
    00211     if (vif->type == VIF_STA)
    00212     {
    00213         sta->is_tdls = param->tdls_sta;
    00214         #if (NX_UMAC_PRESENT)
    00215         if (param->tdls_sta)
    00216         {
    00217             tdls_add_sta(sta, param->tdls_initiator, param->tdls_chsw_allowed);
    00218         }
    00219         else
    00220         {
    00221             vif->u.sta.tdls_chsw_sta_idx = INVALID_STA_IDX;
    00222         }
    00223         #endif //(NX_UMAC_PRESENT)
    00224     }
    00225     #endif
    00226
    00227     #if (RW_MESH_EN && !NX_UMAC_PRESENT)
    00228     // Get a Mesh Link Index
    00229     if (vif->type == VIF_MESH_POINT)
    00230     {
    00231         // Get Mesh Link Index
    00232         for (int i = 0; i < RW_MESH_LINK_NB; i++)
    00233         {
    00234             if (sta_info_env.mesh_link_idx[i] == INVALID_STA_IDX)
    00235             {
    00236                 sta->mlink_idx = i;
    00237                 sta_info_env.mesh_link_idx[i] = *sta_idx;
    00238                 break;
    00239             }
    00240         }
    00241
    00242         // Increase number of Mesh STA currently added
    00243         sta_info_env.nb_mesh_sta++;
    00244     }
    00245     #endif //(RW_MESH_EN && !NX_UMAC_PRESENT)
    00246
    00247     #if (!NX_UMAC_PRESENT && NX_MULTI_ROLE)
    00248     if (vif->type == VIF_STA)
    00249     {
    00250         sta->bcn_int = vif->u.sta.ap_bcn_intv * TU_DURATION;
    00251     }
    00252     #endif //(!NX_UMAC_PRESENT && NX_MULTI_ROLE)
    00253     {
    00254         sta->bcn_int = 100 * TU_DURATION;
    00255     }
    00256
    00257     #if (NX_P2P)
    00258     if (vif->p2p)
    00259     {
    00260         // Increase number of P2P STAs registered for the VIF
    00261         vif->p2p_link_nb++;
    00262     }
    00263     #endif //(NX_P2P)
    00264
    00265     #if NX_UMAC_PRESENT
    00266     sta->rx_nqos_last_seqcntl  = 0xFFFF;
    00267
    00268     for (int i = 0; i < TID_MAX; i++)
    00269     {
    00270         sta->rx_qos_last_seqcntl[i] = 0xFFFF;
    00271     }
    00272     sta->pol_tbl.buf_ctrl = &txl_buffer_control_desc[*sta_idx];
    00273     sta->ctrl_port_state = PORT_CLOSED;
    00274     if ((vif->flags & WPA_WPA2_IN_USE)
    00275         #if (RW_MESH_EN)
    00276             || (vif->type == VIF_MESH_POINT)
    00277         #endif //(RW_MESH_EN)
    00278         #if (NX_TDLS)
    00279             || ((vif->type == VIF_STA) && (param->tdls_sta))
    00280         #endif
    00281             )
    00282     {
    00283         struct sta_mgmt_sec_info *sec = &sta->sta_sec_info;
    00284         sec->cur_key = &sec->pairwise_key;
    00285     }
    00286     else
    00287     {
    00288         struct sta_mgmt_sec_info *sec = &sta->sta_sec_info;
    00289         sec->cur_key = &vif->default_key;
    00290     }
    00291     time = hal_machw_time();
    00292     for (int i = 0; i < TID_MAX; i++)
    00293     {
    00294         sta->ba_info[i].last_ba_add_time = time - BAM_ADDBA_REQ_INTERVAL;
    00295     }
    00296
    00297     #if NX_MFP
    00298     if (vif->flags & MFP_IN_USE)
    00299     {
    00300         STA_CAPA_SET(sta, MFP);
    00301     }
    00302     #endif //(NX_MFP)
    00303     #endif //(NX_UMAC_PRESENT)
    00304
    00305     #if (NX_UMAC_PRESENT || NX_TD_STA)
    00306     // Link the STA to its associated VIF
    00307     co_list_push_back(&vif->sta_list, &sta->list_hdr);
    00308     #endif //(NX_UMAC_PRESENT || NX_TD_STA)
    00309
    00310     #if NX_UMAC_PRESENT && NX_MAC_HE
    00311     // Put a default value in the BSR to ensure initial HE SU transmissions would have
    00312     // a meaningful value to put in the +HTC HE Variant
    00313     sta->bsr = MAC_HTC_HE(TX_HE_BSR_FULL);
    00314     #endif
    00315
    00316     // In order to keep the status of the STA and potential linked STA aligned in case
    00317     // they are checked under interrupt, update them in a critical section
    00318     GLOBAL_INT_DISABLE();
    00319     // The station and potential linked station are now considered as active
    00320     sta->valid = true;
    00321     if (sta->linked_sta != NULL)
    00322         sta->linked_sta->valid = true;
    00323     GLOBAL_INT_RESTORE();
    00324
    00325     // return the allocated station entry index
    00326     return CO_OK;
    00327 }
    00328
    00329 void sta_mgmt_unregister(uint8_t sta_idx)
    00330 {
    00331     struct sta_info_tag *sta = &sta_info_tab[sta_idx];
    00332     #if (NX_P2P || NX_UMAC_PRESENT || RW_MESH_EN || NX_TD_STA || NX_TDLS)
    00333     struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
    00334     #endif
    00335
    00336     #if (NX_P2P)
    00337     if (vif->p2p)
    00338     {
    00339         // Decrease number of P2P STAs registered for the VIF
    00340         vif->p2p_link_nb--;
    00341     }
    00342     #endif //(NX_P2P)
    00343
    00344     #if (RW_BFMER_EN)
    00345     if (bfr_is_enabled())
    00346     {
    00347         bfr_del_sta_ind(sta_idx);
    00348     }
    00349     #endif //(RW_BFMER_EN)
    00350
    00351     #if (NX_UMAC_PRESENT || NX_TD_STA)
    00352     co_list_extract(&vif->sta_list, &sta->list_hdr);
    00353     #endif //(NX_UMAC_PRESENT || NX_TD_STA)
    00354
    00355     #if (RW_MESH_EN && !NX_UMAC_PRESENT)
    00356     // Get a Mesh Link Index
    00357     if (vif->type == VIF_MESH_POINT)
    00358     {
    00359         // Sanity check
    00360         ASSERT_ERR(sta_info_env.mesh_link_idx[sta->mlink_idx] == sta->staid);
    00361
    00362         // Unlink STA index and Link index
    00363         sta_info_env.mesh_link_idx[sta->mlink_idx] = INVALID_STA_IDX;
    00364
    00365         // Decrease number of Mesh STA currently added
    00366         sta_info_env.nb_mesh_sta--;
    00367     }
    00368     #endif //(RW_MESH_EN && !NX_UMAC_PRESENT)
    00369
    00370     #if (NX_TDLS)
    00371     if (sta->is_tdls)
    00372     {
    00373         #if (NX_UMAC_PRESENT)
    00374         tdls_del_sta(sta);
    00375         #else
    00376         if (sta->tdls.chsw_active)
    00377         {
    00378             // Clear channel switch request timer
    00379             mm_timer_clear(&sta->tdls.chsw_req_timer);
    00380             sta->tdls.chsw_active = false;
    00381         }
    00382         if (vif->u.sta.tdls_chsw_sta_idx == sta_idx)
    00383         {
    00384             vif->u.sta.tdls_chsw_sta_idx = INVALID_STA_IDX;
    00385         }
    00386         #endif //(NX_UMAC_PRESENT)
    00387     }
    00388     #endif
    00389
    00390     // In order to keep the status of the STA and potential linked STA aligned in case
    00391     // they are checked under interrupt, update them in a critical section
    00392     GLOBAL_INT_DISABLE();
    00393     sta->valid = false;
    00394     if (sta->linked_sta != NULL)
    00395         sta->linked_sta->valid = false;
    00396     GLOBAL_INT_RESTORE();
    00397
    00398     if (sta->linked_sta != NULL)
    00399     {
    00400         // Fully reset the reference BSSID STA entry
    00401         sta_mgmt_entry_init(sta->linked_sta);
    00402
    00403         // Push it back in the free list
    00404         co_list_push_back(&sta_info_env.free_sta_list, (struct co_list_hdr*)sta->linked_sta);
    00405     }
    00406
    00407     // Fully reset the entry
    00408     sta_mgmt_entry_init(sta);
    00409
    00410     // Push it back in the free list
    00411     co_list_push_back(&sta_info_env.free_sta_list, (struct co_list_hdr*)sta);
    00412 }
    00413
    00414 #if (NX_UMAC_PRESENT)
    00415 void sta_mgmt_add_key(struct mm_key_add_req const *param, uint8_t hw_key_idx)
    00416 {
    00417     struct sta_info_tag *sta = &sta_info_tab[param->sta_idx];
    00418     struct sta_mgmt_sec_info *sec = &sta->sta_sec_info;
    00419     struct key_info_tag *key;
    00420     #if RW_WAPI_EN
    00421     struct vif_info_tag *vif = &vif_info_tab[sta->inst_nbr];
    00422     #endif
    00423
    00424     #if (RW_UMESH_EN)
    00425     if (hw_key_idx >= MM_SEC_MAX_MFP_KEY_NBR)
    00426     {
    00427         key = &sec->key_mfp_mesh_info[MM_MESH_MFP_KEY_TO_KEYID(hw_key_idx)];
    00428     }
    00429     else
    00430     #endif //(RW_UMESH_EN)
    00431     {
    00432         key = &sec->key_info;
    00433     }
    00434
    00435     // Store the key information
    00436     key->hw_key_idx = hw_key_idx;
    00437     key->cipher = param->cipher_suite;
    00438     key->key_idx = param->key_idx;
    00439
    00440     // Reset the replay counters
    00441     memset(key->rx_pn, 0, TID_MAX * sizeof(uint64_t));
    00442
    00443     // Check which encryption type has to be used
    00444     switch(key->cipher)
    00445     {
    00446         case MAC_CIPHER_WEP40:
    00447         case MAC_CIPHER_WEP104:
    00448             key->tx_pn = co_rand_word() & 0xFFFFFF;
    00449             break;
    00450         case MAC_CIPHER_TKIP:
    00451             key->tx_pn = 0;
    00452             key->u.mic.tx_key[0] = param->key.array[4];
    00453             key->u.mic.tx_key[1] = param->key.array[5];
    00454             key->u.mic.rx_key[0] = param->key.array[6];
    00455             key->u.mic.rx_key[1] = param->key.array[7];
    00456             break;
    00457         #if RW_WAPI_EN
    00458         case MAC_CIPHER_WPI_SMS4:
    00459             key->tx_pn = 0x5c365c365c365c36ULL;
    00460             if (vif->type == VIF_AP)
    00461                 key->tx_pn++;
    00462             break;
    00463         #endif
    00464         #if (RW_UMESH_EN)
    00465         #if NX_MFP
    00466         case MAC_CIPHER_BIP_CMAC_128:
    00467             memcpy(key->u.mfp.key, param->key.array, sizeof(key->u.mfp.key));
    00468             key->tx_pn = 0;
    00469             break;
    00470         #endif
    00471         #endif //(RW_UMESH_EN)
    00472         default:
    00473             key->tx_pn = 0;
    00474             break;
    00475     }
    00476
    00477     // Key is now valid
    00478     key->valid = true;
    00479
    00480     #if (RW_UMESH_EN)
    00481     if (hw_key_idx < MM_SEC_MAX_MFP_KEY_NBR)
    00482     #endif //(RW_UMESH_EN)
    00483     {
    00484         // Set the pairwise key and current key pointers
    00485         sec->pairwise_key = key;
    00486     }
    00487 }
    00488
    00489 void sta_mgmt_del_key(struct sta_info_tag *sta)
    00490 {
    00491     struct sta_mgmt_sec_info *sec = &sta->sta_sec_info;
    00492     struct key_info_tag *key = &sec->key_info;
    00493
    00494     // Key is now invalid
    00495     key->valid = false;
    00496     sec->pairwise_key = NULL;
    00497
    00498     // Port is now controlled
    00499     sta->ctrl_port_state = PORT_CONTROLED;
    00500 }
    00501 #endif //(NX_UMAC_PRESENT)
    00502
    00503 #if (NX_TX_FRAME)
    00504 int sta_mgmt_send_postponed_frame(struct vif_info_tag *vif, struct sta_info_tag *sta,
    00505                                   int limit)
    00506 {
    00507     int nb = 0;
    00508
    00509     // Go through list of packets pending for transmission
    00510     while (!co_list_is_empty(&sta->tx_desc_post))
    00511     {
    00512         // Get first TX desc
    00513         struct txdesc *txdesc = (struct txdesc *)co_list_pick(&sta->tx_desc_post);
    00514         // Get frame descriptor
    00515         struct txl_frame_desc_tag *frame_desc;
    00516         #if (NX_UMAC_PRESENT && NX_BEACONING)
    00517         int stop = 0;
    00518         #endif // (NX_UMAC_PRESENT && NX_BEACONING)
    00519
    00520         // Check that the packet can be transmitted
    00521         if (!txl_cntrl_tx_check(vif)
    00522         #if (NX_UMAC_PRESENT && NX_BEACONING)
    00523             || !apm_tx_int_ps_check(txdesc)
    00524         #endif // (NX_UMAC_PRESENT && NX_BEACONING)
    00525         #if (RW_UMESH_EN)
    00526             || !mesh_ps_check_peer_presence(vif, sta->staid)
    00527         #endif //(RW_UMESH_EN)
    00528             )
    00529         {
    00530             break;
    00531         }
    00532
    00533         #if (NX_UMAC_PRESENT && NX_BEACONING)
    00534         txdesc = apm_tx_int_ps_get_postpone(vif, sta, &stop);
    00535         if (stop)
    00536             break;
    00537         else if (!txdesc)
    00538         #endif //(NX_UMAC_PRESENT && NX_BEACONING)
    00539             txdesc = (struct txdesc *)co_list_pop_front(&sta->tx_desc_post);
    00540         frame_desc = (struct txl_frame_desc_tag *)txdesc;
    00541
    00542         #if (RW_UMESH_EN)
    00543         mesh_ps_send_postponed_frame(vif, sta, frame_desc);
    00544         #endif //(RW_UMESH_EN)
    00545
    00546         // clear postponed flagm
    00547         frame_desc->postponed = false;
    00548
    00549         // Send the frame
    00550         // In this case, Access Category has been stored in TID field
    00551         txl_cntrl_push_int(txdesc, txdesc->host.tid);
    00552
    00553         // Count the number of frame sent and limit if requested
    00554         nb++;
    00555         if ((limit) && (limit == nb))
    00556             break;
    00557     }
    00558
    00559     return nb;
    00560 }
    00561 #endif //(NX_TX_FRAME)
    00562