00001
00020
00021
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
00053
00054
00055 struct sta_info_env_tag sta_info_env;
00056 struct sta_info_tag sta_info_tab[STA_MAX];
00057
00058
00059
00060
00061
00069 static void sta_mgmt_entry_init(struct sta_info_tag *sta)
00070 {
00071 #if (NX_TX_FRAME)
00072
00073 while (!co_list_is_empty(&sta->tx_desc_post))
00074 {
00075
00076 struct txdesc *txdesc = (struct txdesc *)co_list_pop_front(&sta->tx_desc_post);
00077
00078
00079 txl_frame_release(txdesc, true);
00080 }
00081 #endif //(NX_TX_FRAME)
00082
00083
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
00095 sta->inst_nbr = 0xFF;
00096 }
00097
00098 void sta_mgmt_init(void)
00099 {
00100 int i;
00101
00102
00103
00104 co_list_init(&sta_info_env.free_sta_list);
00105
00106
00107 for(i = 0; i < NX_REMOTE_STA_MAX ; i++)
00108 {
00109 struct sta_info_tag *sta = &sta_info_tab[i];
00110
00111 sta_mgmt_entry_init(sta);
00112
00113 co_list_push_back(&sta_info_env.free_sta_list, (struct co_list_hdr*)sta);
00114 }
00115
00116 #if NX_UMAC_PRESENT
00117
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
00125 sta_mgmt_entry_init(sta);
00126
00127
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
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
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
00169 sta = (struct sta_info_tag*)co_list_pop_front(&sta_info_env.free_sta_list);
00170
00171
00172 if (sta == NULL)
00173
00174 return CO_FAIL;
00175
00176
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
00183 co_list_push_back(&sta_info_env.free_sta_list, (struct co_list_hdr*)sta);
00184 return CO_FAIL;
00185 }
00186
00187
00188 sta->linked_sta = ref_bssid_sta;
00189 ref_bssid_sta->linked_sta = sta;
00190
00191
00192 mac_ref_bssid_get(param->bssid_index, param->max_bssid_ind, ¶m->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
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
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
00229 if (vif->type == VIF_MESH_POINT)
00230 {
00231
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
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
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
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
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
00312
00313 sta->bsr = MAC_HTC_HE(TX_HE_BSR_FULL);
00314 #endif
00315
00316
00317
00318 GLOBAL_INT_DISABLE();
00319
00320 sta->valid = true;
00321 if (sta->linked_sta != NULL)
00322 sta->linked_sta->valid = true;
00323 GLOBAL_INT_RESTORE();
00324
00325
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
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
00357 if (vif->type == VIF_MESH_POINT)
00358 {
00359
00360 ASSERT_ERR(sta_info_env.mesh_link_idx[sta->mlink_idx] == sta->staid);
00361
00362
00363 sta_info_env.mesh_link_idx[sta->mlink_idx] = INVALID_STA_IDX;
00364
00365
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
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
00391
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
00401 sta_mgmt_entry_init(sta->linked_sta);
00402
00403
00404 co_list_push_back(&sta_info_env.free_sta_list, (struct co_list_hdr*)sta->linked_sta);
00405 }
00406
00407
00408 sta_mgmt_entry_init(sta);
00409
00410
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
00436 key->hw_key_idx = hw_key_idx;
00437 key->cipher = param->cipher_suite;
00438 key->key_idx = param->key_idx;
00439
00440
00441 memset(key->rx_pn, 0, TID_MAX * sizeof(uint64_t));
00442
00443
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
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
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
00495 key->valid = false;
00496 sec->pairwise_key = NULL;
00497
00498
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
00510 while (!co_list_is_empty(&sta->tx_desc_post))
00511 {
00512
00513 struct txdesc *txdesc = (struct txdesc *)co_list_pick(&sta->tx_desc_post);
00514
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
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
00547 frame_desc->postponed = false;
00548
00549
00550
00551 txl_cntrl_push_int(txdesc, txdesc->host.tid);
00552
00553
00554 nb++;
00555 if ((limit) && (limit == nb))
00556 break;
00557 }
00558
00559 return nb;
00560 }
00561 #endif //(NX_TX_FRAME)
00562