• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  * 文 件 名   : hmac_roam_alg.c
15  * 生成日期   : 2015年3月18日
16  * 功能描述   : 漫游模块算法实现
17  */
18 
19 /*****************************************************************************
20   1 头文件包含
21 *****************************************************************************/
22 #include "hmac_roam_alg.h"
23 #include "oam_ext_if.h"
24 #include "mac_ie.h"
25 #include "mac_device_ext.h"
26 #include "mac_resource_ext.h"
27 #include "hmac_fsm.h"
28 #include "hmac_sme_sta.h"
29 #include "hmac_resource.h"
30 #include "hmac_device.h"
31 #include "hmac_scan.h"
32 #include "hmac_roam_main.h"
33 #include "hmac_mgmt_sta.h"
34 #include "hmac_blacklist.h"
35 #include "dmac_ext_if_hcm.h"
36 #include "hmac_feature_interface.h"
37 #include "hmac_11v.h"
38 
39 #ifdef __cplusplus
40 #if __cplusplus
41 extern "C" {
42 #endif
43 #endif
44 
45 #undef THIS_FILE_ID
46 #define THIS_FILE_ID DIAG_FILE_ID_WIFI_HOST_HMAC_ROAM_ALG_C
47 
48 #undef THIS_MOD_ID
49 #define THIS_MOD_ID DIAG_MOD_ID_WIFI_HOST
50 
51 /*****************************************************************************
52   2 全局变量定义
53 *****************************************************************************/
54 /*****************************************************************************
55   3 函数实现
56 *****************************************************************************/
57 /*****************************************************************************
58  功能描述  : roam alg初始化
59 *****************************************************************************/
hmac_roam_alg_init_etc(hmac_roam_info_stru * roam_info,osal_s8 c_current_rssi)60 osal_void hmac_roam_alg_init_etc(hmac_roam_info_stru *roam_info, osal_s8 c_current_rssi)
61 {
62     hmac_roam_alg_stru *roam_alg = OAL_PTR_NULL;
63 
64     if (roam_info == OAL_PTR_NULL) {
65         oam_error_log0(0, OAM_SF_ROAM, "{hmac_roam_alg_init_etc::param null.}");
66         return;
67     }
68     oam_warning_log1(0, OAM_SF_ROAM, "{hmac_roam_alg_init_etc c_current_rssi = %d.}", c_current_rssi);
69 
70     roam_alg = &(roam_info->alg);
71     if (c_current_rssi == ROAM_RSSI_LINKLOSS_TYPE) {
72         roam_info->st_static.trigger_linkloss_cnt++;
73     } else {
74         roam_info->st_static.trigger_rssi_cnt++;
75     }
76 
77     roam_alg->max_capacity       = 0;
78     roam_alg->max_capacity_bss  = OAL_PTR_NULL;
79     roam_alg->c_current_rssi        = c_current_rssi;
80     roam_alg->c_max_rssi            = 0;
81     roam_alg->another_bss_scaned = 0;
82     /* 首次关联时初始化 roam_alg->invalid_scan_cnt   = 0x0; */
83     roam_alg->max_rssi_bss      = OAL_PTR_NULL;
84 
85     return;
86 }
87 
88 /*****************************************************************************
89  功能描述  : 调整rssi增益
90 *****************************************************************************/
hmac_roam_alg_adjust_rssi_increase(hmac_roam_info_stru * roam_info,mac_bss_dscr_stru * bss_dscr)91 OAL_STATIC osal_s8 hmac_roam_alg_adjust_rssi_increase(hmac_roam_info_stru *roam_info,
92     mac_bss_dscr_stru *bss_dscr)
93 {
94     osal_s8  c_current_rssi;
95     osal_s8  c_target_rssi;
96     osal_u8 delta_rssi;
97     osal_u8 flag = OSAL_FALSE;
98 
99     if (bss_dscr->st_channel.band == WLAN_BAND_5G) {
100         delta_rssi = roam_info->config.delta_rssi_5g;
101     } else {
102         delta_rssi = roam_info->config.delta_rssi_2g;
103     }
104 
105     c_current_rssi = roam_info->alg.c_current_rssi;
106     c_target_rssi  = bss_dscr->c_rssi;
107 
108     if (delta_rssi < ROAM_RSSI_DIFF_4_DB) {
109         delta_rssi = ROAM_RSSI_DIFF_4_DB;
110     }
111 
112     if (c_current_rssi >= ROAM_RSSI_NE70_DB) {
113         flag = OSAL_TRUE;
114         goto out;
115     }
116 
117     if (delta_rssi >= ROAM_RSSI_DIFF_4_DB + 2) { /* 2DB */
118         /* 步进2DB至4DB */
119         delta_rssi -= 2;
120     }
121 
122     if (c_current_rssi >= ROAM_RSSI_NE75_DB) {
123         flag = OSAL_TRUE;
124         goto out;
125     }
126 
127     if (delta_rssi >= ROAM_RSSI_DIFF_4_DB + 2) { /* 2DB */
128         /* 步进2DB至4DB */
129         delta_rssi -= 2;
130     }
131 
132     if (c_current_rssi >= ROAM_RSSI_NE80_DB) {
133         flag = OSAL_TRUE;
134         goto out;
135     }
136 
137 out:
138     oam_warning_log4(0, OAM_SF_ROAM,
139         "{hmac_roam_alg_adjust_rssi_increase::flag[%d] target_rssi[%d], current_rssi[%d], delta_rssi[%d].}",
140         flag, c_target_rssi, c_current_rssi, (osal_s8)delta_rssi);
141     return flag == OSAL_TRUE ? (c_target_rssi - c_current_rssi - (osal_s8)delta_rssi) :
142         (c_target_rssi - c_current_rssi - ROAM_RSSI_DIFF_4_DB);
143 }
144 
145 /*****************************************************************************
146  功能描述  : 将bssid添加到列表中
147 *****************************************************************************/
hmac_roam_alg_add_bsslist(hmac_roam_bss_list_stru * roam_bss_list,osal_u8 * bssid,roam_blacklist_type_enum_uint8 list_type)148 OAL_STATIC osal_u32 hmac_roam_alg_add_bsslist(hmac_roam_bss_list_stru *roam_bss_list, osal_u8 *bssid,
149     roam_blacklist_type_enum_uint8 list_type)
150 {
151     hmac_roam_bss_info_stru *cur_bss = OAL_PTR_NULL;
152     osal_u8                mac_zero[WLAN_MAC_ADDR_LEN] = {0};
153     osal_u32               timeout, current_index;
154 
155     hmac_roam_bss_info_stru *oldest_bss = OAL_PTR_NULL;
156     hmac_roam_bss_info_stru *zero_bss   = OAL_PTR_NULL;
157     osal_u32 now = (osal_u32)oal_time_get_stamp_ms();
158 
159     unref_param(list_type);
160 
161     for (current_index = 0; current_index < ROAM_LIST_MAX; current_index++) {
162         cur_bss = &roam_bss_list->bss[current_index];
163         timeout = (osal_u32)cur_bss->timeout;
164         if (oal_compare_mac_addr(cur_bss->bssid, bssid) == 0) {
165             /* 优先查找已存在的记录,如果名单超时更新时间戳,否则更新count */
166             if (osal_get_runtime(cur_bss->time_stamp, now) > timeout) {
167                 cur_bss->time_stamp = now;
168                 cur_bss->count      = 1;
169                 return OAL_SUCC;
170             }
171             cur_bss->count++;
172             if (cur_bss->count == cur_bss->count_limit) {
173                 cur_bss->time_stamp = now;
174             }
175             return OAL_SUCC;
176         }
177 
178         /* 记录第一个空记录 */
179         if (zero_bss != OAL_PTR_NULL) {
180             continue;
181         }
182 
183         if (oal_compare_mac_addr(cur_bss->bssid, (const osal_u8 *)mac_zero) == 0) {
184             zero_bss = cur_bss;
185             continue;
186         }
187 
188         /* 记录一个非空最老记录 */
189         if (oldest_bss == OAL_PTR_NULL) {
190             oldest_bss = cur_bss;
191         } else if (osal_get_runtime(cur_bss->time_stamp, now) >
192             osal_get_runtime(oldest_bss->time_stamp, now)) {
193             oldest_bss = cur_bss;
194         }
195     }
196 
197     if (zero_bss == OAL_PTR_NULL) {
198         zero_bss = oldest_bss;
199     }
200 
201     if (zero_bss != OAL_PTR_NULL) {
202         oal_set_mac_addr(zero_bss->bssid, bssid);
203         zero_bss->time_stamp = now;
204         zero_bss->count      = 1;
205         return OAL_SUCC;
206     }
207     return OAL_FAIL;
208 }
209 
210 /*****************************************************************************
211  功能描述  : 检查列表中是否存在该bssid
212 *****************************************************************************/
hmac_roam_alg_find_in_bsslist(hmac_roam_bss_list_stru * roam_bss_list,osal_u8 * bssid)213 OAL_STATIC oal_bool_enum_uint8 hmac_roam_alg_find_in_bsslist(hmac_roam_bss_list_stru *roam_bss_list,
214     osal_u8 *bssid)
215 {
216     hmac_roam_bss_info_stru    *cur_bss = OAL_PTR_NULL;
217     osal_u32                  current_index;
218     osal_u32                  now;
219     osal_u32                  timeout;
220     osal_u32                  delta_time;
221     osal_u16                  count_limit;
222 
223     now = (osal_u32)oal_time_get_stamp_ms();
224 
225     for (current_index = 0; current_index < ROAM_LIST_MAX; current_index++) {
226         cur_bss = &roam_bss_list->bss[current_index];
227         timeout     = cur_bss->timeout;
228         count_limit =  cur_bss->count_limit;
229 
230         if (oal_compare_mac_addr(cur_bss->bssid, bssid) == 0) {
231             /* 如果在超时时间内出现count_limit次以上记录 */
232             delta_time = osal_get_runtime(cur_bss->time_stamp, now);
233             if ((delta_time <= timeout) && (cur_bss->count >= count_limit)) {
234                 return OAL_TRUE;
235             }
236             return OAL_FALSE;
237         }
238     }
239 
240     return OAL_FALSE;
241 }
242 
243 /*****************************************************************************
244  功能描述  : 将bssid添加到黑名单列表中
245 *****************************************************************************/
hmac_roam_alg_add_blacklist_etc(hmac_roam_info_stru * roam_info,osal_u8 * bssid,roam_blacklist_type_enum_uint8 list_type)246 osal_u32 hmac_roam_alg_add_blacklist_etc(hmac_roam_info_stru *roam_info, osal_u8 *bssid,
247     roam_blacklist_type_enum_uint8 list_type)
248 {
249     osal_u32 ul_ret;
250     if ((roam_info == OAL_PTR_NULL) || (bssid == OAL_PTR_NULL)) {
251         return OAL_ERR_CODE_PTR_NULL;
252     }
253 
254     ul_ret = hmac_roam_alg_add_bsslist(&roam_info->alg.blacklist, bssid, list_type);
255     if (ul_ret != OAL_SUCC) {
256         oam_error_log1(0, OAM_SF_ROAM, "{hmac_roam_alg_add_blacklist_etc::hmac_roam_alg_add_list failed[%d].}", ul_ret);
257         return ul_ret;
258     }
259 
260     oam_warning_log4(0, OAM_SF_ROAM, "{hmac_roam_alg_add_blacklist_etc:: bss[%02x:%02x:%02x:%02x:XX:XX]}",
261         bssid[0], bssid[1], bssid[2], bssid[3]); /* mac地址0/1/2/3 */
262     return OAL_SUCC;
263 }
264 
265 /*****************************************************************************
266  功能描述  : 检查黑名单列表中是否存在该bssid
267 *****************************************************************************/
hmac_roam_alg_find_in_blacklist_etc(hmac_roam_info_stru * roam_info,osal_u8 * bssid)268 oal_bool_enum_uint8 hmac_roam_alg_find_in_blacklist_etc(hmac_roam_info_stru *roam_info, osal_u8 *bssid)
269 {
270     if ((roam_info == OAL_PTR_NULL) || (bssid == OAL_PTR_NULL)) {
271         return OAL_FALSE;
272     }
273 
274     return hmac_roam_alg_find_in_bsslist(&roam_info->alg.blacklist, bssid);
275 }
276 
277 /*****************************************************************************
278  功能描述  : 将bssid添加到历史优选AP列表中
279 *****************************************************************************/
hmac_roam_alg_add_history_etc(hmac_roam_info_stru * roam_info,osal_u8 * bssid)280 osal_u32 hmac_roam_alg_add_history_etc(hmac_roam_info_stru *roam_info, osal_u8 *bssid)
281 {
282     osal_u32 ul_ret;
283 
284     if ((roam_info == OAL_PTR_NULL) || (bssid == OAL_PTR_NULL)) {
285         return OAL_ERR_CODE_PTR_NULL;
286     }
287 
288     ul_ret = hmac_roam_alg_add_bsslist(&roam_info->alg.history, bssid, ROAM_BLACKLIST_TYPE_NORMAL_AP);
289     if (ul_ret != OAL_SUCC) {
290         oam_error_log1(0, OAM_SF_ROAM, "{hmac_roam_alg_add_history_etc::hmac_roam_alg_add_list failed[%d].}", ul_ret);
291         return ul_ret;
292     }
293 
294     return OAL_SUCC;
295 }
296 
hmac_roam_alg_fill_channel_list(mac_scan_req_stru * scan_params,osal_u8 index,osal_u8 chan_number,osal_u8 band,osal_u8 chan_idx)297 OAL_STATIC osal_void hmac_roam_alg_fill_channel_list(mac_scan_req_stru *scan_params, osal_u8 index,
298     osal_u8 chan_number, osal_u8 band, osal_u8 chan_idx)
299 {
300     scan_params->channel_list[index].chan_number = chan_number;
301     scan_params->channel_list[index].band        = band;
302     scan_params->channel_list[index].chan_idx    = chan_idx;
303 }
304 
hmac_roam_alg_scan_orthogonal(const hmac_roam_info_stru * roam_info,mac_scan_req_stru * scan_params)305 OAL_STATIC osal_void hmac_roam_alg_scan_orthogonal(const hmac_roam_info_stru *roam_info,
306     mac_scan_req_stru *scan_params)
307 {
308     osal_u32 ret;
309     osal_u8 chan_idx;
310     osal_u8 chan_number;
311 
312     switch (roam_info->config.scan_orthogonal) {
313         case ROAM_SCAN_CHANNEL_ORG_3:
314             hmac_roam_alg_fill_channel_list(scan_params, 0, 1, WLAN_BAND_2G, 0);
315 
316             hmac_roam_alg_fill_channel_list(scan_params, 1, 6, WLAN_BAND_2G, 5); /* 6信道  5信道索引号 */
317 
318             hmac_roam_alg_fill_channel_list(scan_params, 2, 11, WLAN_BAND_2G, 10); /* 元素2 11信道 10信道索引号 */
319 
320             scan_params->channel_nums = 3; /* 扫描信道个数为3 */
321             break;
322         case ROAM_SCAN_CHANNEL_ORG_4:
323             hmac_roam_alg_fill_channel_list(scan_params, 0, 1, WLAN_BAND_2G, 0);
324 
325             hmac_roam_alg_fill_channel_list(scan_params, 1, 5, WLAN_BAND_2G, 4); /* 5信道 4信道索引号 */
326 
327             hmac_roam_alg_fill_channel_list(scan_params, 2, 7, WLAN_BAND_2G, 6); /* 数组元素2,7信道 6信道索引号 */
328 
329             hmac_roam_alg_fill_channel_list(scan_params, 3, 13, WLAN_BAND_2G, 12); /* 元素3,13信道 12信道索引号 */
330 
331             scan_params->channel_nums = 4; /* 扫描信道个数为4 */
332             break;
333         default:
334             for (chan_idx = 0; chan_idx < MAC_CHANNEL_FREQ_2_BUTT; chan_idx++) {
335                 ret = hmac_is_channel_idx_valid_etc(WLAN_BAND_2G, chan_idx);
336                 if (ret != OAL_SUCC) {
337                     continue;
338                 }
339                 hmac_get_channel_num_from_idx_etc(WLAN_BAND_2G, chan_idx, &chan_number);
340                 hmac_roam_alg_fill_channel_list(scan_params, scan_params->channel_nums, chan_number,
341                     WLAN_BAND_2G, chan_idx);
342                 scan_params->channel_nums++;
343             }
344             break;
345     }
346 }
347 
hmac_roam_alg_scan_channel_init_etc(hmac_roam_info_stru * roam_info,mac_scan_req_stru * scan_params)348 osal_u32 hmac_roam_alg_scan_channel_init_etc(hmac_roam_info_stru *roam_info, mac_scan_req_stru *scan_params)
349 {
350     hmac_vap_stru      *hmac_vap = OAL_PTR_NULL;
351     mac_channel_stru   *channel  = OAL_PTR_NULL;
352 #ifdef _PRE_WLAN_SUPPORT_5G
353     osal_u32          ul_ret;
354     osal_u8           chan_idx, chan_number;
355 #endif
356     osal_void *fhook = hmac_get_feature_fhook(HMAC_FHOOK_11V_SET_SCAN_PARAMS);
357 
358     if ((roam_info == OAL_PTR_NULL) || (scan_params == OAL_PTR_NULL)) {
359         oam_error_log0(0, OAM_SF_ROAM, "{hmac_roam_alg_scan_channel_init_etc::param null.}");
360         return OAL_ERR_CODE_PTR_NULL;
361     }
362 
363     hmac_vap  = roam_info->hmac_vap;
364 
365     channel = &(hmac_vap->channel);
366     scan_params->channel_nums  = 0;
367 
368     if (roam_info->config.scan_orthogonal == ROAM_SCAN_CHANNEL_ORG_1) {
369         oam_info_log3(0, OAM_SF_ROAM, "{scan one channel: ChanNum[%d], Band[%d], ChanIdx[%d]}",
370             channel->chan_number, channel->band, channel->chan_idx);
371 
372         if (roam_info->roam_trigger != ROAM_TRIGGER_11V) {
373             hmac_roam_alg_fill_channel_list(scan_params, 0, channel->chan_number, channel->band, channel->chan_idx);
374             scan_params->channel_nums = 1;
375             return OAL_SUCC;
376         }
377 
378         if (fhook != OSAL_NULL) {
379             ((hmac_11v_set_scan_params_cb)fhook)(scan_params, roam_info);
380         }
381         return OAL_SUCC;
382     }
383 
384     if ((roam_info->config.scan_band & ROAM_BAND_2G_BIT) != 0) {
385         hmac_roam_alg_scan_orthogonal(roam_info, scan_params);
386     }
387 #ifdef _PRE_WLAN_SUPPORT_5G
388     if ((roam_info->config.scan_band & ROAM_BAND_5G_BIT) != 0) {
389         for (chan_idx = 0; chan_idx < MAC_CHANNEL_FREQ_5_BUTT; chan_idx++) {
390             ul_ret = hmac_is_channel_idx_valid_etc(WLAN_BAND_5G, chan_idx);
391             if (ul_ret != OAL_SUCC) {
392                 continue;
393             }
394             hmac_get_channel_num_from_idx_etc(WLAN_BAND_5G, chan_idx, &chan_number);
395             hmac_roam_alg_fill_channel_list(scan_params, scan_params->channel_nums, chan_number,
396                 WLAN_BAND_5G, chan_idx);
397             scan_params->channel_nums++;
398         }
399     }
400 #endif
401     return OAL_SUCC;
402 }
403 
hmac_roam_alg_get_capacity_by_rssi(wlan_protocol_enum_uint8 protocol,wlan_bw_cap_enum_uint8 bw_cap,osal_s8 c_rssi)404 OAL_STATIC osal_u32 hmac_roam_alg_get_capacity_by_rssi(wlan_protocol_enum_uint8 protocol,
405     wlan_bw_cap_enum_uint8 bw_cap, osal_s8 c_rssi)
406 {
407     hmac_roam_rssi_capacity_stru *rssi_table = OAL_PTR_NULL;
408     osal_u8 index;
409     hmac_roam_rssi_capacity_stru rssi_tab_11b[ROAM_RSSI_LEVEL] = { {-88, 0, 81}, {-92, 0, 49}, {-94, 0, 9} };
410     hmac_roam_rssi_capacity_stru rssi_tab_11g_ofdm[ROAM_RSSI_LEVEL] = { {-75, 0, 293}, {-82, 0, 173}, {-90, 0, 54} };
411     hmac_roam_rssi_capacity_stru rssi_tab_11a_ofdm[ROAM_RSSI_LEVEL] = { {-75, 0, 293}, {-82, 0, 173}, {-90, 0, 54} };
412     hmac_roam_rssi_capacity_stru rssi_tab_ht20_ofdm[ROAM_RSSI_LEVEL] = { {-72, 0, 588}, {-80, 0, 353}, {-90, 0, 58} };
413     hmac_roam_rssi_capacity_stru rssi_tab_ht40_ofdm[ROAM_RSSI_LEVEL] = { {-75, 0, 1281}, {-77, 0, 705},
414         {-87, 0, 116} };
415     hmac_roam_rssi_capacity_stru rssi_tab_vht80_ofdm[ROAM_RSSI_LEVEL] = { {-72, 0, 2562}, {-74, 0, 1410},
416         {-84, 0, 232} };
417 
418     switch (protocol) {
419         case WLAN_LEGACY_11A_MODE:
420             rssi_table = rssi_tab_11a_ofdm;
421             break;
422 
423         case WLAN_LEGACY_11B_MODE:
424             rssi_table = rssi_tab_11b;
425             break;
426 
427         case WLAN_LEGACY_11G_MODE:
428         case WLAN_MIXED_ONE_11G_MODE:
429         case WLAN_MIXED_TWO_11G_MODE:
430             rssi_table = rssi_tab_11g_ofdm;
431             break;
432 
433         case WLAN_HT_MODE:
434         case WLAN_VHT_MODE:
435             if (bw_cap == WLAN_BW_CAP_20M) {
436                 rssi_table = rssi_tab_ht20_ofdm;
437             } else if (bw_cap == WLAN_BW_CAP_40M) {
438                 rssi_table = rssi_tab_ht40_ofdm;
439             } else {
440                 rssi_table = rssi_tab_vht80_ofdm;
441             }
442             break;
443 
444         default:
445             break;
446     }
447 
448     if (rssi_table == OAL_PTR_NULL) {
449         return 0;
450     }
451 
452     for (index = 0; index < ROAM_RSSI_LEVEL; index++) {
453         if (rssi_table[index].c_rssi <= c_rssi) {
454             /* capacity_kbps的单位是100Kb,此处乘以100,单位换算为kb */
455             return ((osal_u32)rssi_table[index].capacity_kbps * 100);
456         }
457     }
458 
459     return 0;
460 }
461 
hmac_roam_alg_calc_avail_channel_capacity(mac_bss_dscr_stru * bss_dscr)462 OAL_STATIC osal_u32 hmac_roam_alg_calc_avail_channel_capacity(mac_bss_dscr_stru *bss_dscr)
463 {
464     osal_u32                 capacity;
465     osal_u32                 avail_channel_cap;
466     osal_u32                 ul_ret;
467     osal_u8                  channel_utilization;
468     osal_u8                 *obss_ie = OAL_PTR_NULL;
469     osal_u8                  ie_offset;
470     wlan_protocol_enum_uint8   protocol;
471 
472     ul_ret = hmac_sta_get_user_protocol_etc(bss_dscr, &protocol);
473     if (ul_ret != OAL_SUCC) {
474         return 0;
475     }
476     /***************************************************************************
477         ------------------------------------------------------------------------
478         |EID |Len |StationCount |ChannelUtilization |AvailableAdmissionCapacity|
479         ------------------------------------------------------------------------
480         |1   |1   |2            |1                  |2                         |
481         ------------------------------------------------------------------------
482         ***************************************************************************/
483     ie_offset = MAC_80211_FRAME_LEN + MAC_TIME_STAMP_LEN + MAC_BEACON_INTERVAL_LEN + MAC_CAP_INFO_LEN;
484     obss_ie = mac_find_ie_etc(MAC_EID_QBSS_LOAD, (osal_u8 *)(bss_dscr->mgmt_buff + ie_offset),
485         (osal_s32)(bss_dscr->mgmt_len - ie_offset));
486     /* 长度要到达ChannelUtilization这个域,至少为3 */
487     if (obss_ie && (obss_ie[1] >= 3)) {
488         channel_utilization = *(obss_ie + 4); /* +4:得到channel_utilization的初始地址 */
489     } else {
490         return 0;
491     }
492 
493     capacity = hmac_roam_alg_get_capacity_by_rssi(protocol, bss_dscr->bw_cap, bss_dscr->c_rssi);
494 
495     /* 文档规定信道利用率计算方法:normalized to 255 */
496     avail_channel_cap = capacity * (255 - channel_utilization) / 255 / ROAM_CONCURRENT_USER_NUMBER;
497 
498     return avail_channel_cap;
499 }
500 
501 /*****************************************************************************
502  功能描述 : 触发强信号漫游前,校验pmf能力位
503 *****************************************************************************/
hmac_roam_alg_bss_pmf_capa_check(hmac_vap_stru * hmac_vap,mac_bss_dscr_stru * bss_dscr)504 OAL_STATIC osal_u32 hmac_roam_alg_bss_pmf_capa_check(hmac_vap_stru *hmac_vap, mac_bss_dscr_stru *bss_dscr)
505 {
506 #ifdef _PRE_WLAN_FEATURE_PMF
507     osal_u16 rsn_cap_info = 0;
508     osal_bool pmf_cap;
509     osal_bool pmf_require;
510 
511     if (bss_dscr->rsn_ie != OSAL_NULL) {
512         /* 获取目的AP的RSN CAP信息 */
513         rsn_cap_info = hmac_get_rsn_capability_etc(bss_dscr->rsn_ie);
514     }
515 
516     /* 漫游时使用上次pmf能力位 并判断与漫游的目的ap能力位是否匹配 */
517     pmf_cap = mac_mib_get_dot11_rsnamfpc(hmac_vap);
518     pmf_require = mac_mib_get_dot11_rsnamfpr(hmac_vap);
519     if ((pmf_require == OSAL_TRUE) && ((rsn_cap_info & BIT7) == 0)) {      /* 本地强制,对端没有MFP能力 */
520         oam_warning_log0(0, OAM_SF_CFG, "{hmac_roam_alg_bss_pmf_capa_check:: vap require pmf but ap don't have}");
521         return OAL_FAIL;
522     }
523     if ((pmf_cap == OSAL_FALSE) && ((rsn_cap_info & BIT6) != 0)) {    /* 对端强制,本地没有MFP能力 */
524         oam_warning_log0(0, OAM_SF_CFG, "{hmac_roam_alg_bss_pmf_capa_check:: vap no pmf cap and ap required}");
525         return OAL_FAIL;
526     }
527 #endif
528 
529     return OAL_SUCC;
530 }
531 
hmac_roam_alg_bss_in_ess_etc(hmac_roam_info_stru * roam_info,mac_bss_dscr_stru * bss_dscr)532 osal_u32 hmac_roam_alg_bss_in_ess_etc(hmac_roam_info_stru *roam_info, mac_bss_dscr_stru *bss_dscr)
533 {
534     hmac_vap_stru              *hmac_vap = OAL_PTR_NULL;
535     hmac_roam_alg_stru         *roam_alg = OAL_PTR_NULL;
536     mac_cfg_ssid_param_stru     cfg_ssid;
537     osal_u8                     stru_len;
538     osal_u32                    scan_expire_time, curr_time;
539 
540     if ((roam_info == OAL_PTR_NULL) || (bss_dscr == OAL_PTR_NULL)) {
541         oam_error_log0(0, OAM_SF_ROAM, "{hmac_roam_alg_bss_in_ess_etc::param null.}");
542         return OAL_ERR_CODE_PTR_NULL;
543     }
544 
545     hmac_vap = roam_info->hmac_vap;
546     if (hmac_vap == OAL_PTR_NULL) {
547         return OAL_ERR_CODE_ROAM_INVALID_VAP;
548     }
549 
550     hmac_mib_get_ssid_etc(hmac_vap, &stru_len, (osal_u8 *)(&cfg_ssid));
551 
552     if ((osal_strlen(bss_dscr->ac_ssid) != cfg_ssid.ssid_len) ||
553         (osal_memcmp(cfg_ssid.ac_ssid, bss_dscr->ac_ssid, cfg_ssid.ssid_len) != 0)) {
554         return OAL_SUCC;
555     }
556 
557     /* 挑选 scan_expire_time 时间以内的有效bss */
558     scan_expire_time = (osal_u32)mac_is_dfs_channel(WLAN_BAND_5G, bss_dscr->st_channel.chan_number) == OAL_TRUE ?
559         HMAC_SCAN_MAX_VALID_SCANNED_DFS_EXPIRE : HMAC_SCAN_MAX_VALID_SCANNED_BSS_EXPIRE;
560     curr_time = (osal_u32)oal_time_get_stamp_ms();
561     if (oal_time_after((osal_ulong)curr_time, (osal_ulong)(bss_dscr->timestamp + scan_expire_time)) != 0) {
562         oam_warning_log4(0, OAM_SF_ROAM, "{hmac_roam_alg_bss_in_ess_etc:: bss[%02x:%02x:%02x:%02x:XX:XX]}",
563             bss_dscr->bssid[0], bss_dscr->bssid[1], bss_dscr->bssid[2], bss_dscr->bssid[3]); /* mac地址0/1/2/3 */
564         oam_warning_log2(0, OAM_SF_ROAM, "{hmac_roam_alg_bss_in_ess_etc::expire scan time %d ms, diff_time=%d}",
565             scan_expire_time, curr_time - bss_dscr->timestamp);
566         return OAL_SUCC;
567     }
568 
569     /* pmf能力位校验不通过的,不漫游 */
570     if (hmac_roam_alg_bss_pmf_capa_check(hmac_vap, bss_dscr) != OAL_SUCC) {
571         return OAL_SUCC;
572     }
573 
574     roam_alg = &(roam_info->alg);
575     /* 是否扫描到了当前关联的 bss, 仅置位,不过滤 */
576     if (oal_compare_mac_addr(hmac_vap->bssid, bss_dscr->bssid) != 0) {
577         roam_alg->another_bss_scaned = 1;
578 
579         /* Roaming Scenario Recognition
580          * dense AP standard: RSSI>=-60dB, candidate num>=5;
581          *                    RSSI<-60dB && RSSI >=-75dB, candidate num>=10;
582          */
583         roam_alg->candidate_bss_num++;
584         if (bss_dscr->c_rssi >= roam_info->config.c_candidate_good_rssi) {
585             roam_alg->candidate_good_rssi_num++;
586         } else if ((bss_dscr->c_rssi < roam_info->config.c_candidate_good_rssi) &&
587             bss_dscr->c_rssi >= ROAM_RSSI_NE75_DB) {
588             roam_alg->candidate_weak_rssi_num++;
589         }
590 
591         if (bss_dscr->c_rssi > roam_alg->c_max_rssi) {
592             roam_alg->c_max_rssi = bss_dscr->c_rssi;
593         }
594     } else {
595         roam_alg->c_current_rssi = bss_dscr->c_rssi;
596     }
597 
598     return OAL_SUCC;
599 }
600 
601 /*****************************************************************************
602  功能描述 : 校验加密相关 和 rssi
603 *****************************************************************************/
hmac_roam_alg_bss_check_privacy_and_rssi(hmac_roam_info_stru * roam_info,mac_bss_dscr_stru * bss_dscr,hmac_vap_stru * hmac_vap,hmac_roam_alg_stru * roam_alg)604 OAL_STATIC osal_u32 hmac_roam_alg_bss_check_privacy_and_rssi(hmac_roam_info_stru *roam_info,
605     mac_bss_dscr_stru *bss_dscr, hmac_vap_stru *hmac_vap, hmac_roam_alg_stru *roam_alg)
606 {
607     osal_u32 avail_channel_cap;
608     osal_s8 tmp_rssi;
609     osal_u8 *pmkid = OAL_PTR_NULL;
610     osal_s8 delta_rssi;
611     mac_cap_info_stru *cap_info = OAL_PTR_NULL;
612 
613     if (roam_info->current_bss_ignore == OAL_FALSE) {
614         /* 排除当前bss的rssi值计算,本地已经保存了dmac上报的rssi */
615         if (oal_compare_mac_addr(hmac_vap->bssid, bss_dscr->bssid) == 0) {
616             return OAL_ERR_CODE_ROAM_NO_VALID_BSS;
617         }
618     }
619 
620     /* wep的bss直接过滤掉 */
621     cap_info = (mac_cap_info_stru *)&bss_dscr->us_cap_info;
622     if ((bss_dscr->rsn_ie == OAL_PTR_NULL) && (bss_dscr->wpa_ie == OAL_PTR_NULL) &&
623         (cap_info->privacy != 0)) {
624         return OAL_ERR_CODE_ROAM_NO_VALID_BSS;
625     }
626 
627     /*  open加密方式到wpa/wpa2直接过滤掉 */
628     if ((cap_info->privacy == 0) != (mac_mib_get_privacyinvoked(hmac_vap) != OAL_TRUE)) {
629         return OAL_ERR_CODE_ROAM_NO_VALID_BSS;
630     }
631 
632     /* c_current_rssi为0时,表示linkloss上报的触发,不需要考虑rssi增益 */
633     delta_rssi = hmac_roam_alg_adjust_rssi_increase(roam_info, bss_dscr);
634     if (delta_rssi <= 0) {
635         return OAL_ERR_CODE_ROAM_NO_VALID_BSS;
636     }
637 
638     avail_channel_cap = hmac_roam_alg_calc_avail_channel_capacity(bss_dscr);
639     if ((avail_channel_cap != 0) && ((roam_alg->max_capacity_bss == OAL_PTR_NULL) ||
640         (avail_channel_cap > roam_alg->max_capacity))) {
641         /* 暂时不考虑容量 */
642     }
643 
644     tmp_rssi = bss_dscr->c_rssi;
645     /* 对于已存在pmk缓存的bss进行加分处理 */
646     pmkid = hmac_vap_get_pmksa_etc(hmac_vap, bss_dscr->bssid);
647     if (pmkid != OAL_PTR_NULL) {
648         tmp_rssi += ROAM_RSSI_DIFF_4_DB;
649     }
650 
651     if (bss_dscr->st_channel.band == WLAN_BAND_5G) {
652         tmp_rssi += ROAM_RSSI_DIFF_4_DB; /* 5G AP have 4dB weight for higher priority */
653     }
654 
655     if ((roam_alg->max_rssi_bss == OAL_PTR_NULL) || (tmp_rssi > roam_alg->c_max_rssi)) {
656         roam_alg->c_max_rssi = tmp_rssi;
657         roam_alg->max_rssi_bss = bss_dscr;
658     }
659 
660     return OAL_SUCC;
661 }
662 
663 /*****************************************************************************
664  功能描述  : 检查
665 *****************************************************************************/
hmac_roam_alg_bss_check_etc(hmac_roam_info_stru * roam_info,mac_bss_dscr_stru * bss_dscr)666 osal_u32 hmac_roam_alg_bss_check_etc(hmac_roam_info_stru *roam_info, mac_bss_dscr_stru *bss_dscr)
667 {
668     hmac_vap_stru *hmac_vap = OAL_PTR_NULL;
669     hmac_roam_alg_stru *roam_alg = OAL_PTR_NULL;
670     mac_cfg_ssid_param_stru cfg_ssid;
671     osal_u32 ret;
672     osal_u8 stru_len;
673     osal_void *fhook;
674 
675     if ((roam_info == OAL_PTR_NULL) || (bss_dscr == OAL_PTR_NULL)) {
676         oam_error_log0(0, OAM_SF_ROAM, "{hmac_roam_alg_bss_check_etc::param null.}");
677         return OAL_ERR_CODE_PTR_NULL;
678     }
679 
680     hmac_vap = roam_info->hmac_vap;
681     if (hmac_vap == OAL_PTR_NULL) {
682         return OAL_ERR_CODE_ROAM_INVALID_VAP;
683     }
684 
685     hmac_mib_get_ssid_etc(hmac_vap, &stru_len, (osal_u8 *)(&cfg_ssid));
686 
687     if ((osal_strlen(bss_dscr->ac_ssid) != cfg_ssid.ssid_len) ||
688         (osal_memcmp(cfg_ssid.ac_ssid, bss_dscr->ac_ssid, cfg_ssid.ssid_len) != 0)) {
689         return OAL_ERR_CODE_ROAM_NO_VALID_BSS;
690     }
691     roam_alg = &(roam_info->alg);
692 
693     if (roam_info->current_bss_ignore == OAL_FALSE) {
694         if (oal_time_after((osal_ulong)oal_time_get_stamp_ms(),
695             (osal_ulong)(bss_dscr->timestamp + HMAC_SCAN_MAX_VALID_SCANNED_BSS_EXPIRE)) != 0) {
696             return OAL_ERR_CODE_ROAM_NO_VALID_BSS;
697         }
698     }
699 
700     /* 检查黑名单 */
701     ret = hmac_roam_alg_find_in_blacklist_etc(roam_info, bss_dscr->bssid);
702     if (ret == OAL_TRUE) {
703         oam_warning_log4(0, OAM_SF_ROAM, "{hmac_roam_alg_bss_check_etc:: [%02X:%02X:%02X:%02X:XX:XX] in blacklist!}",
704             /* 打印mac的第0位,第1位,第2位,第3位 */
705             bss_dscr->bssid[0], bss_dscr->bssid[1], bss_dscr->bssid[2], bss_dscr->bssid[3]);
706         return OAL_ERR_CODE_ROAM_NO_VALID_BSS;
707     }
708 
709     /* check bssid blacklist from Framework setting */
710     fhook = hmac_get_feature_fhook(HMAC_FHOOK_BLACKLIST_FILTER_ETC);
711     if (fhook != OSAL_NULL) {
712         ret = ((hmac_blacklist_filter_etc_cb)fhook)(hmac_vap, bss_dscr->bssid);
713         if (ret == OAL_TRUE) {
714             return OAL_ERR_CODE_ROAM_NO_VALID_BSS;
715         }
716     }
717 
718     return hmac_roam_alg_bss_check_privacy_and_rssi(roam_info, bss_dscr, hmac_vap, roam_alg);
719 }
720 
hmac_roam_alg_need_to_stop_roam_trigger_etc(hmac_roam_info_stru * roam_info)721 oal_bool_enum_uint8 hmac_roam_alg_need_to_stop_roam_trigger_etc(hmac_roam_info_stru *roam_info)
722 {
723     hmac_vap_stru              *hmac_vap = OAL_PTR_NULL;
724     hmac_roam_alg_stru         *roam_alg = OAL_PTR_NULL;
725 
726     if (roam_info == OAL_PTR_NULL) {
727         return OAL_FALSE;
728     }
729 
730     hmac_vap = roam_info->hmac_vap;
731     if (hmac_vap == OAL_PTR_NULL) {
732         return OAL_FALSE;
733     }
734 
735     roam_alg  = &(roam_info->alg);
736 
737     if (roam_alg->another_bss_scaned == OSAL_TRUE) {
738         roam_alg->invalid_scan_cnt = 0xff;
739         return OAL_FALSE;
740     }
741 
742     if (roam_alg->invalid_scan_cnt == 0xff) {
743         return OAL_FALSE;
744     }
745 
746     if (roam_alg->invalid_scan_cnt++ > 4) { /* 最大次数为4 */
747         roam_alg->invalid_scan_cnt = 0xff;
748         return OAL_TRUE;
749     }
750 
751     return OAL_FALSE;
752 }
753 
hmac_roam_alg_select_bss_etc(hmac_roam_info_stru * roam_info)754 mac_bss_dscr_stru *hmac_roam_alg_select_bss_etc(hmac_roam_info_stru *roam_info)
755 {
756     hmac_vap_stru              *hmac_vap = OAL_PTR_NULL;
757     mac_bss_dscr_stru          *bss_dscr = OAL_PTR_NULL;
758     hmac_roam_alg_stru         *roam_alg = OAL_PTR_NULL;
759     osal_s8                    c_delta_rssi;
760     osal_s8                    c_max_rssi = 0;
761 
762     if (roam_info == OAL_PTR_NULL) {
763         return OAL_PTR_NULL;
764     }
765 
766     hmac_vap = roam_info->hmac_vap;
767     if (hmac_vap == OAL_PTR_NULL) {
768         return OAL_PTR_NULL;
769     }
770 
771     roam_alg = &(roam_info->alg);
772 
773     /* 取得最大 rssi 的 bss */
774     bss_dscr = roam_alg->max_rssi_bss;
775 
776     if ((roam_alg->max_capacity_bss != OAL_PTR_NULL) &&
777         (roam_alg->max_capacity >= ROAM_THROUGHPUT_THRESHOLD)) {
778         /* 取得最大 capacity 的 bss */
779         bss_dscr = roam_alg->max_capacity_bss;
780     }
781 
782     if (bss_dscr == OAL_PTR_NULL) {
783         /* should not be here */
784         return OAL_PTR_NULL;
785     }
786 
787     if (roam_info->current_bss_ignore == OAL_FALSE) {
788         /* 过滤当前关联的 bss */
789         if (oal_compare_mac_addr(hmac_vap->bssid, bss_dscr->bssid) == 0) {
790             return OAL_PTR_NULL;
791         }
792     }
793 
794     /* rssi增益处理 */
795     c_delta_rssi = hmac_roam_alg_adjust_rssi_increase(roam_info, bss_dscr);
796     if (c_delta_rssi <= 0) {
797         return OAL_PTR_NULL;
798     }
799     c_max_rssi = roam_alg->c_max_rssi;
800 #ifdef _PRE_WLAN_SUPPORT_5G
801     if (bss_dscr->st_channel.band == WLAN_BAND_5G) {
802         c_max_rssi = roam_alg->c_max_rssi - ROAM_RSSI_DIFF_4_DB;
803     }
804 #endif
805     oam_warning_log2(0, OAM_SF_ROAM, "hmac_roam_alg_select_bss:roam_to candidate AP, band=%d(0:2.4G,1:5G) max_rssi=%d",
806         bss_dscr->st_channel.band, c_max_rssi);
807     oam_warning_log4(0, OAM_SF_ROAM, "{hmac_roam_alg_select_bss::[%02X:%02X:%02X:%02X:XX:XX]}",
808         /* 0:1:2:3:数组下标 */
809         bss_dscr->bssid[0], bss_dscr->bssid[1], bss_dscr->bssid[2], bss_dscr->bssid[3]);
810 
811     return bss_dscr;
812 }
813 
814 #ifdef __cplusplus
815 #if __cplusplus
816 }
817 #endif
818 #endif
819