1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 /* ****************************************************************************
20 1 头文件包含
21 **************************************************************************** */
22 #include "oal_net.h"
23 #include "hmac_tx_data.h"
24 #include "mac_frame.h"
25 #include "mac_data.h"
26 #include "hmac_frag.h"
27 #include "hmac_ext_if.h"
28 #ifdef _PRE_WLAN_FEATURE_WAPI
29 #include "hmac_wapi.h"
30 #endif
31 #ifdef _PRE_WLAN_FEATURE_TX_CLASSIFY_LAN_TO_WLAN
32 #include "hmac_traffic_classify.h"
33 #endif
34 #include "hmac_crypto_tkip.h"
35 #include "hmac_device.h"
36 #include "hcc_hmac_if.h"
37 #include "wal_customize.h"
38 #ifdef _PRE_WLAN_FEATURE_EDCA_OPT_AP
39 #include "hmac_edca_opt.h"
40 #endif
41 #ifdef __cplusplus
42 #if __cplusplus
43 extern "C" {
44 #endif
45 #endif
46
47 /* ****************************************************************************
48 2 全局变量定义
49 **************************************************************************** */
50 #if (_PRE_MULTI_CORE_MODE_OFFLOAD_DMAC != _PRE_MULTI_CORE_MODE)
51 static hi_u16 g_us_noqos_frag_seqnum = 0; /* 保存非qos分片帧seqnum */
52 #endif
53
54 /* ****************************************************************************
55 3 函数实现
56 **************************************************************************** */
57 #ifdef _PRE_WLAN_FEATURE_SMP_SUPPORT
58 hi_u32 hmac_tx_data(hmac_vap_stru *hmac_vap, oal_netbuf_stru *netbuf);
59 #endif
60 /* ****************************************************************************
61 函 数 名 : free_netbuf_list
62 功能描述 : 释放一个netbuf链,此链中的skb或者都来自lan,或者都来自wlan
63 输入参数 : pst_buf-SKB结构体单向链表,最后一个next指针务必为NULL,否则会出异常
64 输出参数 :
65 返 回 值 : 释放的buf数目
66 调用函数 :
67 被调函数 :
68
69 修改历史 :
70 1.日 期 : 2012年11月14日
71 作 者 : HiSilicon
72 修改内容 : 新生成函数
73
74 **************************************************************************** */
hmac_free_netbuf_list(oal_netbuf_stru * netbuf)75 hi_u16 hmac_free_netbuf_list(oal_netbuf_stru *netbuf)
76 {
77 oal_netbuf_stru *buf_tmp = HI_NULL;
78 hmac_tx_ctl_stru *tx_cb = HI_NULL;
79 hi_u16 us_buf_num = 0;
80
81 if (netbuf != HI_NULL) {
82 while (netbuf != HI_NULL) {
83 buf_tmp = oal_netbuf_list_next(netbuf);
84 us_buf_num++;
85 set_oal_netbuf_next(netbuf, HI_NULL);
86 tx_cb = (hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf);
87 /* 如果frame_header部分是内存池申请的才从内存池释放,采用skb内部自身的,就不需要再释放 */
88 if ((tx_cb->mac_head_type == 0) && (tx_cb->frame_header != HI_NULL)) {
89 oal_free(tx_cb->frame_header);
90 tx_cb->frame_header = HI_NULL;
91 }
92
93 oal_netbuf_free(netbuf);
94
95 netbuf = buf_tmp;
96 }
97 } else {
98 oam_error_log0(0, OAM_SF_ANY, "{hmac_free_netbuf_list::pst_buf is null}");
99 }
100
101 return us_buf_num;
102 }
103
104 #ifdef _PRE_WLAN_FEATURE_MESH
105 /* ****************************************************************************
106 函 数 名 : hmac_tid_num_set
107 功能描述 : 根据优先级设置tid号
108 修改历史 :
109 1.日 期 : 2019年09月17日
110 作 者 : HiSilicon
111 修改内容 : 新生成函数
112 **************************************************************************** */
hmac_tid_num_set(hi_u32 buf_prio,hi_u8 * tid)113 hi_void hmac_tid_num_set(hi_u32 buf_prio, hi_u8 *tid)
114 {
115 switch (buf_prio) {
116 case 0: /* 0:优先级 */
117 *tid = WLAN_TIDNO_BEST_EFFORT;
118 break;
119 case 1: /* 1:优先级 */
120 *tid = WLAN_TIDNO_BACKGROUND;
121 break;
122 case 2: /* 2:优先级 */
123 *tid = WLAN_TIDNO_VIDEO;
124 break;
125 default:
126 *tid = WLAN_TIDNO_VOICE;
127 break;
128 }
129 }
130 #endif
131
132 #ifdef _PRE_WLAN_FEATURE_CLASSIFY
133 /* ****************************************************************************
134 功能描述 : 从lan过来的IP报文业务识别
135 **************************************************************************** */
hmac_tx_classify_ipv4_data(hmac_tx_ctl_stru * tx_ctl,mac_ether_header_stru * ether_header,hi_u8 * puc_tid)136 static hi_void hmac_tx_classify_ipv4_data(hmac_tx_ctl_stru *tx_ctl, mac_ether_header_stru *ether_header, hi_u8 *puc_tid)
137 {
138 mac_ip_header_stru *ip = HI_NULL;
139 hi_u8 tid;
140 #ifdef _PRE_WLAN_FEATURE_SCHEDULE
141 mac_tcp_header_stru *tcp = HI_NULL;
142 #endif
143
144 #if defined(_PRE_WLAN_FEATURE_EDCA_OPT_AP) || defined(_PRE_WLAN_FEATURE_TX_CLASSIFY_LAN_TO_WLAN)
145 hmac_vap_stru *hmac_vap = hmac_vap_get_vap_stru(tx_ctl->tx_vap_index);
146 if (hmac_vap == HI_NULL) {
147 oam_warning_log1(0, OAM_SF_TX, "{hmac_tx_classify_ipv4_data::get hmac_vap[%d] fail.}", tx_ctl->tx_vap_index);
148 return;
149 }
150 #endif
151 /* 从IP TOS字段寻找优先级 */
152 /* ----------------------------------------------------------------------
153 tos位定义
154 ----------------------------------------------------------------------
155 | bit7~bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
156 | 包优先级 | 时延 | 吞吐量 | 可靠性 | 传输成本 | 保留 |
157 ---------------------------------------------------------------------- */
158 ip = (mac_ip_header_stru *)(ether_header + 1); /* 偏移一个以太网头,取ip头 */
159 tid = ip->tos >> WLAN_IP_PRI_SHIFT;
160 #ifdef _PRE_WLAN_FEATURE_TX_CLASSIFY_LAN_TO_WLAN
161 if (hmac_vap->tx_traffic_classify_flag == HI_SWITCH_ON) {
162 if (tid != 0) {
163 return;
164 }
165 hmac_tx_traffic_classify(tx_ctl, ip, &tid);
166 }
167 #endif /* _PRE_WLAN_FEATURE_TX_CLASSIFY_LAN_TO_WLAN */
168
169 /* 如果是DHCP帧,则进入VO队列发送 */
170 if (mac_is_dhcp_port(ip)) {
171 tid = WLAN_DATA_VIP_TID;
172 tx_ctl->is_vipframe = HI_TRUE;
173 tx_ctl->is_needretry = HI_TRUE;
174 } else if (ip->protocol == MAC_ICMP_PROTOCAL) {
175 tx_ctl->high_prio_sch = HI_TRUE;
176 /* 对于ping包采取软件重传策略 */
177 tx_ctl->is_needretry = HI_TRUE;
178 #ifdef _PRE_WLAN_FEATURE_SCHEDULE
179 } else if (ip->protocol == MAC_TCP_PROTOCAL) {
180 /* 对于chariot信令报文进行特殊处理,防止断流 */
181 tcp = (mac_tcp_header_stru *)(ip + 1);
182 if ((oal_ntoh_16(tcp->us_dport) == MAC_CHARIOT_NETIF_PORT) ||
183 (oal_ntoh_16(tcp->us_sport) == MAC_CHARIOT_NETIF_PORT)) {
184 tid = WLAN_DATA_VIP_TID;
185 tx_ctl->is_vipframe = HI_TRUE;
186 tx_ctl->is_needretry = HI_TRUE;
187 }
188 #endif
189 }
190
191 #ifdef _PRE_WLAN_FEATURE_EDCA_OPT_AP
192 /* EDCA AP优化统计量刷新 */
193 hmac_edca_opt_tx_pkts_stat(tx_ctl, tid, ip);
194 #endif
195 *puc_tid = tid;
196 }
197
198 /* ****************************************************************************
199 功能描述 : 从lan过来的IPV6报文业务识别
200 **************************************************************************** */
hmac_tx_classify_ipv6_data(hmac_tx_ctl_stru * tx_ctl,mac_ether_header_stru * ether_header,hi_u32 buf_prio,hi_u8 * puc_tid)201 static hi_void hmac_tx_classify_ipv6_data(hmac_tx_ctl_stru *tx_ctl, mac_ether_header_stru *ether_header,
202 hi_u32 buf_prio, hi_u8 *puc_tid)
203 {
204 hi_u32 ipv6_hdr;
205 hi_u32 pri;
206 hi_u8 tid;
207
208 #if defined(_PRE_WLAN_FEATURE_MESH)
209 hmac_vap_stru *hmac_vap = hmac_vap_get_vap_stru(tx_ctl->tx_vap_index);
210 if (hmac_vap == HI_NULL) {
211 oam_warning_log1(0, OAM_SF_TX, "{hmac_tx_classify_ipv6_data::get hmac_vap[%d] fail.}", tx_ctl->tx_vap_index);
212 return;
213 }
214 #else
215 hi_unref_param(buf_prio);
216 #endif
217 /* 从IPv6 traffic class字段获取优先级 */
218 /* ----------------------------------------------------------------------
219 IPv6包头 前32为定义
220 -----------------------------------------------------------------------
221 | 版本号 | traffic class | 流量标识 |
222 | 4bit | 8bit(同ipv4 tos)| 20bit |
223 ----------------------------------------------------------------------- */
224 ipv6_hdr = *((hi_u32 *)(ether_header + 1)); /* 偏移一个以太网头,取ip头 */
225 pri = (oal_net2host_long(ipv6_hdr) & WLAN_IPV6_PRIORITY_MASK) >> WLAN_IPV6_PRIORITY_SHIFT;
226 tid = (hi_u8)(pri >> WLAN_IP_PRI_SHIFT);
227 /* 如果是ND DHCPV6帧,则进入VO队列发送 */
228 if (mac_is_nd((oal_ipv6hdr_stru *)(ether_header + 1)) || mac_is_dhcp6((oal_ipv6hdr_stru *)(ether_header + 1))) {
229 tid = WLAN_DATA_VIP_TID;
230 tx_ctl->is_vipframe = HI_TRUE;
231 tx_ctl->is_needretry = HI_TRUE;
232 } else { /* 规避编程规范K&R检查 else与if拆分 */
233 #ifdef _PRE_WLAN_FEATURE_MESH
234 if (mac_is_rpl((oal_ipv6hdr_stru *)(ether_header + 1))) {
235 oam_warning_log0(0, OAM_SF_TX, "{hmac_tx_classify_ipv6_data::ETHER_TYPE_RPL.}");
236 tid = WLAN_DATA_VIP_TID;
237 tx_ctl->is_vipframe = HI_TRUE;
238 tx_ctl->is_needretry = HI_TRUE;
239 } else if (hmac_vap->base_vap->vap_mode == WLAN_VAP_MODE_MESH) {
240 /* 打桩,当有包头压缩时用pbuf flag判断 */
241 /*
242 uc_pbuf_flags:
243 |BIT1 |BIT0 |
244 |Ctrl PKT |Compressed 6lo |
245 */
246 if (tx_ctl->pbuf_flags & BIT1) {
247 tid = WLAN_DATA_VIP_TID;
248 tx_ctl->is_vipframe = HI_TRUE;
249 } else {
250 /* 优先级:0-3,超出3统一认为与3一致 */
251 hmac_tid_num_set(buf_prio, &tid);
252 }
253 }
254 #endif
255 }
256 *puc_tid = tid;
257 }
258
259 /* ****************************************************************************
260 功能描述 : 从lan过来报文的业务识别
261 修改历史 :
262 1.日 期 : 2013年10月10日
263 作 者 : HiSilicon
264 修改内容 : 新生成函数
265 2.日 期 : 2015年11月23日
266 作 者 : HiSilicon
267 修改内容 : 函数算法增量
268 **************************************************************************** */
hmac_tx_classify_lan_to_wlan(oal_netbuf_stru * netbuf,hi_u8 * puc_tid)269 static hi_void hmac_tx_classify_lan_to_wlan(oal_netbuf_stru *netbuf, hi_u8 *puc_tid)
270 {
271 mac_ether_header_stru *ether_header = HI_NULL;
272 hmac_tx_ctl_stru *tx_ctl = (hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf);
273 hi_u32 buf_prio = oal_netbuf_priority(netbuf);
274 hi_u8 tid = 0;
275
276 /* 获取以太网头 */
277 ether_header = (mac_ether_header_stru *)oal_netbuf_data(netbuf);
278 /* 大函数整改更换为if else语句 */
279 if (ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_IP)) {
280 /* ipv4报文处理 */
281 hmac_tx_classify_ipv4_data(tx_ctl, ether_header, &tid);
282 } else if (ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_IPV6)) {
283 /* ipv6报文处理 */
284 hmac_tx_classify_ipv6_data(tx_ctl, ether_header, buf_prio, &tid);
285 } else if (ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_PAE)) {
286 /* 如果是EAPOL帧,则进入VO队列发送 */
287 tid = WLAN_DATA_VIP_TID;
288 tx_ctl->is_vipframe = HI_TRUE;
289 tx_ctl->is_needretry = HI_TRUE;
290 /* 如果是4 次握手设置单播密钥,则设置tx cb 中bit_is_eapol_key_ptk 置一,dmac 发送不加密 */
291 if (mac_is_eapol_key_ptk((mac_eapol_header_stru *)(ether_header + 1))) {
292 tx_ctl->is_eapol_key_ptk = HI_TRUE;
293 }
294 } else if (ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_TDLS)) {
295 /* TDLS帧处理,建链保护,入高优先级TID队列 */
296 tid = WLAN_DATA_VIP_TID;
297 oam_info_log1(0, OAM_SF_TX, "{hmac_tx_classify_lan_to_wlan::TDLS tid=%d.}", tid);
298 } else if ((ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_PPP_DISC)) ||
299 (ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_PPP_SES)) ||
300 (ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_WAI))) {
301 /* PPPOE帧处理,建链保护(发现阶段, 会话阶段),入高优先级TID队列 */
302 tid = WLAN_DATA_VIP_TID;
303 tx_ctl->is_vipframe = HI_TRUE;
304 tx_ctl->is_needretry = HI_TRUE;
305 oam_info_log2(0, 0, "{hmac_tx_classify_lan_to_wlan::type=%d, tid=%d.}", ether_header->us_ether_type, tid);
306 } else if (ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_ARP)) {
307 /* 如果是ARP帧,则进入VO队列发送 */
308 tid = WLAN_DATA_VIP_TID;
309 tx_ctl->is_vipframe = HI_TRUE;
310 } else if (ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_VLAN)) {
311 /* 获取vlan tag的优先级 */
312 oal_vlan_ethhdr_stru *vlan_ethhdr = (oal_vlan_ethhdr_stru *)oal_netbuf_data(netbuf);
313 /* ------------------------------------------------------------------
314 802.1Q(VLAN) TCI(tag control information)位定义
315 -------------------------------------------------------------------
316 |Priority | DEI | Vlan Identifier |
317 | 3bit | 1bit | 12bit |
318 ------------------------------------------------------------------ */
319 hi_u16 vlan_tci = oal_net2host_short(vlan_ethhdr->h_vlan_tci);
320 tid = vlan_tci >> OAL_VLAN_PRIO_SHIFT; /* 右移13位,提取高3位优先级 */
321 oam_info_log1(0, OAM_SF_TX, "{hmac_tx_classify_lan_to_wlan::VLAN tid=%d.}", tid);
322 } else { /* 规避编程规范K&R检查 else与if拆分 */
323 #ifdef _PRE_WLAN_FEATURE_MESH
324 if (ether_header->us_ether_type == oal_host2net_short(ETHER_TYPE_6LO)) {
325 if (tx_ctl->pbuf_flags & BIT0) {
326 /* 优先级:0-3,超出3统一认为与3一致 */
327 hmac_tid_num_set(buf_prio, &tid);
328 }
329 }
330 #endif
331 }
332 /* 出参赋值 */
333 *puc_tid = tid;
334 }
335
336 /* ****************************************************************************
337 函 数 名 : hmac_tx_update_tid
338 功能描述 : 根据算法需求,tid = 1, 3, 5, 7的,分别更新为0, 2, 4, 6
339 如果WMM功能关闭,直接填为DMAC_WMM_SWITCH_TID
340 输入参数 : puc_tid 注意,此参数为入出参
341 输出参数 : puc_tid
342 返 回 值 :
343 调用函数 :
344 被调函数 :
345
346 修改历史 :
347 1.日 期 : 2014年3月14日
348 作 者 : HiSilicon
349 修改内容 : 新生成函数
350 **************************************************************************** */
hmac_tx_update_tid(hi_u8 wmm,hi_u8 * puc_tid)351 static inline hi_void hmac_tx_update_tid(hi_u8 wmm, hi_u8 *puc_tid)
352 {
353 if (oal_likely(wmm == HI_TRUE)) { /* wmm使能 */
354 *puc_tid = (*puc_tid < WLAN_TIDNO_BUTT) ? wlan_tos_to_tid(*puc_tid) : WLAN_TIDNO_BCAST;
355 } else {
356 /* wmm不使能 */
357 *puc_tid = MAC_WMM_SWITCH_TID;
358 }
359 }
360
361 /* ****************************************************************************
362 函 数 名 : hmac_tx_wmm_acm
363 功能描述 : 根据热点配置ACM,重新选择队列
364 输入参数 :
365 输出参数 :
366 返 回 值 :
367 调用函数 :
368 被调函数 :
369
370 修改历史 :
371 1.日 期 : 2015年11月25日
372 作 者 : HiSilicon
373 修改内容 : 新生成函数
374 **************************************************************************** */
hmac_tx_wmm_acm(hi_u8 wmm,const hmac_vap_stru * hmac_vap,hi_u8 * puc_tid)375 hi_u8 hmac_tx_wmm_acm(hi_u8 wmm, const hmac_vap_stru *hmac_vap, hi_u8 *puc_tid)
376 {
377 hi_u8 ac;
378 hi_u8 ac_new;
379
380 if ((hmac_vap == HI_NULL) || (hmac_vap->base_vap->mib_info == HI_NULL) || (puc_tid == HI_NULL)) {
381 return HI_FALSE;
382 }
383
384 if (wmm == HI_FALSE) {
385 return HI_FALSE;
386 }
387
388 ac = wlan_wme_tid_to_ac(*puc_tid);
389 ac_new = ac;
390 while ((ac_new != WLAN_WME_AC_BK) &&
391 (hmac_vap->base_vap->mib_info->wlan_mib_qap_edac[ac_new].dot11_qapedca_table_mandatory == HI_TRUE)) {
392 switch (ac_new) {
393 case WLAN_WME_AC_VO:
394 ac_new = WLAN_WME_AC_VI;
395 break;
396
397 case WLAN_WME_AC_VI:
398 ac_new = WLAN_WME_AC_BE;
399 break;
400
401 default:
402 ac_new = WLAN_WME_AC_BK;
403 break;
404 }
405 }
406
407 if (ac_new != ac) {
408 *puc_tid = wlan_wme_ac_to_tid(ac_new);
409 }
410
411 return HI_TRUE;
412 }
413
414 /* ****************************************************************************
415 函 数 名 : hmac_tx_classify
416 功能描述 : 以太网包 业务识别
417 输入参数 : 无
418 输出参数 : 无
419 返 回 值 :
420 调用函数 :
421 被调函数 :
422
423 修改历史 :
424 1.日 期 : 2013年5月2日
425 作 者 : HiSilicon
426 修改内容 : 新生成函数
427
428 2.日 期 : 2013年10月10日
429 作 者 : HiSilicon
430 修改内容 : 增加wlan to wlan分支处理
431
432 **************************************************************************** */
hmac_tx_classify(const hmac_vap_stru * hmac_vap,const mac_user_stru * user,oal_netbuf_stru * netbuf)433 static hi_void hmac_tx_classify(const hmac_vap_stru *hmac_vap, const mac_user_stru *user, oal_netbuf_stru *netbuf)
434 {
435 hi_u8 tid = 0;
436 hi_u8 ret;
437 hmac_tx_ctl_stru *tx_ctl = HI_NULL;
438 mac_device_stru *mac_dev = HI_NULL;
439
440 hmac_tx_classify_lan_to_wlan(netbuf, &tid);
441
442 /* 非QoS站点,直接返回 */
443 if (oal_unlikely(user->cap_info.qos != HI_TRUE)) {
444 /* ROM化防止换行 */
445 oam_info_log0(hmac_vap->base_vap->vap_id, OAM_SF_TX, "{hmac_tx_classify::user is a none QoS station.}");
446 return;
447 }
448
449 mac_dev = mac_res_get_dev();
450 ret = hmac_tx_wmm_acm(mac_dev->wmm, hmac_vap, &tid);
451 if (ret != HI_TRUE) {
452 oam_info_log0(hmac_vap->base_vap->vap_id, OAM_SF_TX, "hmac_tx_wmm_acm return NON SUCCESS. ");
453 }
454
455 tx_ctl = (hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf);
456 if ((tx_ctl->is_vipframe != HI_TRUE) || (mac_dev->wmm == HI_FALSE)) {
457 hmac_tx_update_tid(mac_dev->wmm, &tid);
458 }
459
460 /* 设置ac和tid到cb字段 */
461 tx_ctl->tid = tid;
462 tx_ctl->ac = wlan_wme_tid_to_ac(tid);
463 /* VO/VI队列中数据帧设置成需要重传 */
464 if (tx_ctl->ac == WLAN_WME_AC_VI || tx_ctl->ac == WLAN_WME_AC_VO) {
465 tx_ctl->is_needretry = HI_TRUE;
466 }
467
468 return;
469 }
470 #endif
471
472 /* ****************************************************************************
473 函 数 名 : hmac_tx_filter_security
474 功能描述 : 针对来自以太网的数据帧做安全过滤
475 输入参数 : hmac_vap_stru *pst_hmac_vap
476 oal_netbuf_stru *pst_buf
477 hmac_user_stru *pst_hmac_user
478 hmac_tx_ctl_stru *pst_tx_ctl
479 输出参数 : HI_TRUE
480 返 回 值 : hi_u32
481 调用函数 :
482 被调函数 :
483
484 修改历史 :
485 1.日 期 : 2013年9月12日
486 作 者 : HiSilicon
487 修改内容 : 新生成函数
488
489 **************************************************************************** */
hmac_tx_filter_security(const hmac_vap_stru * hmac_vap,const oal_netbuf_stru * netbuf,const hmac_user_stru * hmac_user)490 static hi_u32 hmac_tx_filter_security(const hmac_vap_stru *hmac_vap, const oal_netbuf_stru *netbuf,
491 const hmac_user_stru *hmac_user)
492 {
493 mac_ether_header_stru *ether_header = HI_NULL;
494 mac_user_stru *mac_user = HI_NULL;
495 mac_vap_stru *mac_vap = HI_NULL;
496 hi_u32 ret = HI_SUCCESS;
497
498 mac_vap = hmac_vap->base_vap;
499 mac_user = hmac_user->base_user;
500
501 if (mac_vap->mib_info->wlan_mib_privacy.dot11_rsna_activated == HI_TRUE) { /* 判断是否使能WPA/WPA2 */
502 if (mac_user->port_valid != HI_TRUE) { /* 判断端口是否打开 */
503 /* 获取以太网头 */
504 ether_header = (mac_ether_header_stru *)oal_netbuf_data(netbuf);
505 /* 发送数据时,针对非EAPOL 的数据帧做过滤 */
506 if (hi_swap_byteorder_16(ETHER_TYPE_PAE) != ether_header->us_ether_type) {
507 oam_info_log2(0, OAM_SF_TX, "{hmac_tx_filter_security::TYPE 0x%04x, 0x%04x.}",
508 hi_swap_byteorder_16(ether_header->us_ether_type), ETHER_TYPE_PAE);
509 ret = HI_FAIL;
510 }
511 }
512 }
513
514 return ret;
515 }
516
517 /* ****************************************************************************
518 函 数 名 : hmac_tx_ba_setup
519 功能描述 : 自动触发BA会话的建立
520 输入参数 : 无
521 输出参数 : 无
522 返 回 值 :
523 调用函数 :
524 被调函数 :
525
526 修改历史 :
527 1.日 期 : 2013年4月25日
528 作 者 : HiSilicon
529 修改内容 : 新生成函数
530
531 **************************************************************************** */
hmac_tx_ba_setup(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,hi_u8 tidno)532 hi_void hmac_tx_ba_setup(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, hi_u8 tidno)
533 {
534 mac_action_mgmt_args_stru action_args; /* 用于填写ACTION帧的参数 */
535 hi_u8 ampdu_support;
536 hi_u32 ret = HI_SUCCESS;
537
538 /* 建立BA会话,是否需要判断VAP的AMPDU的支持情况,因为需要实现建立BA会话时,一定发AMPDU */
539 ampdu_support = hmac_user_xht_support(hmac_user);
540 if (ampdu_support) {
541 /*
542 建立BA会话时,st_action_args结构各个成员意义如下
543 (1)uc_category:action的类别
544 (2)uc_action:BA action下的类别
545 (3)ul_arg1:BA会话对应的TID
546 (4)ul_arg2:BUFFER SIZE大小
547 (5)ul_arg3:BA会话的确认策略
548 (6)ul_arg4:TIMEOUT时间
549 */
550 action_args.category = MAC_ACTION_CATEGORY_BA;
551 action_args.action = MAC_BA_ACTION_ADDBA_REQ;
552 action_args.arg1 = tidno; /* 该数据帧对应的TID号 */
553 action_args.arg2 = (hi_u32)hmac_vap->max_ampdu_num; /* ADDBA_REQ中,buffer_size的默认大小 */
554 action_args.arg3 = MAC_BA_POLICY_IMMEDIATE; /* BA会话的确认策略 */
555 action_args.arg4 = 0; /* BA会话的超时时间设置为0 */
556 oam_warning_log1(0, OAM_SF_TX, "hisi_customize_wifi::[ba buffer size:%d]", action_args.arg2);
557 /* 建立BA会话 */
558 ret = hmac_mgmt_tx_action(hmac_vap, hmac_user, &action_args);
559 } else {
560 if (hmac_user->ast_tid_info[tidno].ba_tx_info != HI_NULL) {
561 action_args.category = MAC_ACTION_CATEGORY_BA;
562 action_args.action = MAC_BA_ACTION_DELBA;
563 action_args.arg1 = tidno; /* 该数据帧对应的TID号 */
564 action_args.arg2 = MAC_ORIGINATOR_DELBA; /* 发送端删除ba */
565 action_args.arg3 = MAC_UNSPEC_REASON; /* BA会话删除原因 */
566 action_args.puc_arg5 = hmac_user->base_user->user_mac_addr; /* 用户mac地址 */
567 /* 删除BA会话 */
568 ret = hmac_mgmt_tx_action(hmac_vap, hmac_user, &action_args);
569 }
570 }
571
572 if (ret != HI_SUCCESS) {
573 oam_warning_log0(0, OAM_SF_TX, "hmac_mgmt_tx_action return NON SUCCESS. ");
574 }
575 }
576
hmac_check_if_mgmt_tx_action(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,hi_u8 tidno)577 hi_void hmac_check_if_mgmt_tx_action(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, hi_u8 tidno)
578 {
579 if (hmac_vap->ampdu_tx_on_switch == HI_FALSE) {
580 mac_action_mgmt_args_stru action_args = {0}; /* 用于填写ACTION帧的参数 */
581 action_args.category = MAC_ACTION_CATEGORY_BA;
582 action_args.action = MAC_BA_ACTION_DELBA;
583 action_args.arg1 = tidno;
584 action_args.arg2 = MAC_ORIGINATOR_DELBA;
585 action_args.arg3 = MAC_UNSPEC_REASON;
586 action_args.puc_arg5 = hmac_user->base_user->user_mac_addr;
587
588 if (hmac_mgmt_tx_action(hmac_vap, hmac_user, &action_args) != HI_SUCCESS) {
589 oam_warning_log0(hmac_vap->base_vap->vap_id, OAM_SF_CFG, "hmac_mgmt_tx_action return NON SUCCESS. ");
590 }
591 }
592 }
593 /* ****************************************************************************
594 函 数 名 : hmac_tx_ba_check
595 功能描述 : 判断是否需要建立BA会话
596 输入参数 : 无
597 输出参数 : 无
598 返 回 值 : HI_TRUE代表需要建立BA会话
599 调用函数 :
600 被调函数 :
601
602 修改历史 :
603 1.日 期 : 2015年6月24日
604 作 者 : HiSilicon
605 修改内容 : 新生成函数
606
607 修改历史 :
608 2.日 期 : 2015年7月24日
609 作 者 : HiSilicon
610 修改内容 : 新生成函数
611
612 **************************************************************************** */
hmac_tid_need_ba_session(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,hi_u8 tidno,const oal_netbuf_stru * netbuf)613 hi_u8 hmac_tid_need_ba_session(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user, hi_u8 tidno,
614 const oal_netbuf_stru *netbuf)
615 {
616 if ((hmac_vap == HI_NULL) || (hmac_user == HI_NULL) || (netbuf == HI_NULL) || (hmac_user->base_user == HI_NULL)) {
617 return HI_FALSE;
618 }
619
620 if (hmac_vap_ba_is_setup(hmac_user, tidno) == HI_TRUE) {
621 hmac_check_if_mgmt_tx_action(hmac_vap, hmac_user, tidno);
622 return HI_FALSE;
623 }
624
625 /* 配置命令不允许建立聚合时返回 */
626 /* 窄带不建立聚合 */
627 /* 针对VO业务, 根据VAP标志位确定是否建立BA会话 */
628 /* 判断HMAC VAP的是否支持聚合 */
629 if ((hmac_vap->ampdu_tx_on_switch == HI_FALSE) || (hmac_user_xht_support(hmac_user) == HI_FALSE) ||
630 ((wlan_wme_tid_to_ac(tidno) == WLAN_WME_AC_VO) && (hmac_vap->base_vap->voice_aggr == HI_FALSE)) ||
631 (!((hmac_vap->tx_aggr_on) || (hmac_vap->base_vap->cap_flag.rifs_tx_on)))) {
632 return HI_FALSE;
633 }
634
635 #ifdef _PRE_WLAN_FEATURE_AMPDU_VAP
636 if (hmac_vap->tx_ba_session_num >= WLAN_MAX_TX_BA) {
637 return HI_FALSE;
638 }
639 #else
640 hmac_device_stru *hmac_dev = hmac_get_device_stru();
641 if (hmac_dev->tx_ba_session_num >= WLAN_MAX_TX_BA) {
642 return HI_FALSE;
643 }
644 #endif
645
646 /* 需要先发送5个单播帧,再进行BA会话的建立 */
647 if ((hmac_user->base_user->cap_info.qos) && (hmac_user->ast_tid_info[tidno].ba_flag < DMAC_UCAST_TX_COMP_TIMES)) {
648 hmac_user->ast_tid_info[tidno].ba_flag++;
649 return HI_FALSE;
650 } else if (hmac_user->base_user->cap_info.qos == HI_FALSE) {
651 /* 针对关闭WMM,非QOS帧处理 */
652 return HI_FALSE;
653 }
654
655 /* tx ba尝试次数超过最大值 则不允许再次建立BA */
656 if ((hmac_user->ast_tid_info[tidno].ba_tx_info == HI_NULL) &&
657 (hmac_user->ast_tid_info[tidno].tx_ba_attemps < HMAC_ADDBA_EXCHANGE_ATTEMPTS)) {
658 hmac_user->ast_tid_info[tidno].tx_ba_attemps++;
659 } else {
660 return HI_FALSE;
661 }
662
663 return HI_TRUE;
664 }
665
666 /* ****************************************************************************
667 函 数 名 : hmac_tx_ucast_process
668 功能描述 : 单播处理
669 输入参数 : pst_vap VAP结构体; pst_buf netbuf结构体;pst_user 用户结构体
670 输出参数 :
671 返 回 值 :
672 调用函数 : hmac_tx_mpdu_process_ap
673 被调函数 :
674
675 修改历史 :
676 1.日 期 : 2012年11月14日
677 作 者 : HiSilicon
678 修改内容 : 新生成函数
679 2.日 期 : 2013年09月12日
680 作 者 : HiSilicon
681 修改内容 : 修改函数,增加安全过滤
682
683 **************************************************************************** */
hmac_tx_ucast_process(hmac_vap_stru * hmac_vap,oal_netbuf_stru * netbuf,hmac_user_stru * hmac_user,const hmac_tx_ctl_stru * tx_ctl)684 hmac_tx_return_type_enum_uint8 hmac_tx_ucast_process(hmac_vap_stru *hmac_vap, oal_netbuf_stru *netbuf,
685 hmac_user_stru *hmac_user, const hmac_tx_ctl_stru *tx_ctl)
686 {
687 hmac_tx_return_type_enum_uint8 ret = HMAC_TX_PASS;
688
689 /* 安全过滤 */
690 #if defined(_PRE_WLAN_FEATURE_WPA) || defined(_PRE_WLAN_FEATURE_WPA2)
691 if (oal_unlikely(hmac_tx_filter_security(hmac_vap, netbuf, hmac_user) != HI_SUCCESS)) {
692 return HMAC_TX_DROP_SECURITY_FILTER;
693 }
694 #endif
695
696 /* 以太网业务识别 */
697 #ifdef _PRE_WLAN_FEATURE_CLASSIFY
698 hmac_tx_classify(hmac_vap, hmac_user->base_user, netbuf);
699 #endif
700
701 /* 如果是EAPOL、DHCP帧,则不允许主动建立BA会话 */
702 if (tx_ctl->is_vipframe == HI_FALSE) {
703 #ifdef _PRE_WLAN_FEATURE_AMPDU
704 if (hmac_tid_need_ba_session(hmac_vap, hmac_user, tx_ctl->tid, netbuf) == HI_TRUE) {
705 /* 自动触发建立BA会话,设置AMPDU聚合参数信息在DMAC模块的处理addba rsp帧的时刻后面 */
706 hmac_tx_ba_setup(hmac_vap, hmac_user, tx_ctl->tid);
707 }
708 #endif
709 }
710
711 return ret;
712 }
713
714 /* ****************************************************************************
715 函 数 名 : hmac_tx_is_need_frag
716 功能描述 : 检查该报文是否需要分片
717 输入参数 : 无
718 输出参数 : 无
719 返 回 值 :
720 调用函数 :
721 被调函数 :
722
723 修改历史 :
724 1.日 期 : 2014年2月18日
725 作 者 : HiSilicon
726 修改内容 : 新生成函数
727
728 **************************************************************************** */
hmac_tx_is_need_frag(const hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user,const oal_netbuf_stru * netbuf,const hmac_tx_ctl_stru * tx_ctl)729 static hi_u8 hmac_tx_is_need_frag(const hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user,
730 const oal_netbuf_stru *netbuf, const hmac_tx_ctl_stru *tx_ctl)
731 {
732 hi_u32 threshold;
733 hi_u32 last_frag;
734 hi_u32 netbuf_len;
735 /* 判断报文是否需要进行分片 */
736 /* 1、长度大于门限 */
737 /* 2、是legac协议模式 */
738 /* 3、不是广播帧 */
739 /* 4、不是聚合帧 */
740 /* 6、DHCP帧不进行分片 */
741 /* 7、mesh不分片 */
742 if (tx_ctl->is_vipframe == HI_TRUE) {
743 return HI_FALSE;
744 }
745
746 #ifdef _PRE_WLAN_FEATURE_MESH
747 if (hmac_vap->base_vap->vap_mode == WLAN_VAP_MODE_MESH) {
748 return HI_FALSE;
749 }
750 #endif
751
752 threshold = hmac_vap->base_vap->mib_info->wlan_mib_operation.dot11_fragmentation_threshold;
753 threshold = (threshold & (~(BIT0 | BIT1))) + 2; /* 加2 */
754 /* 规避1151硬件bug,调整分片门限:TKIP加密时,当最后一个分片的payload长度
755 小于等于8时,无法进行加密 */
756 if (WLAN_80211_CIPHER_SUITE_TKIP == hmac_user->base_user->key_info.cipher_type) {
757 last_frag = (oal_netbuf_len(netbuf) + 8) % (threshold - tx_ctl->frame_header_length - /* 加8 */
758 (WEP_IV_FIELD_SIZE + EXT_IV_FIELD_SIZE));
759 if ((last_frag > 0) && (last_frag <= 8)) { /* 8 边界 */
760 threshold = threshold + 8; /* 自增 8 */
761 }
762 }
763
764 netbuf_len =
765 (tx_ctl->mac_head_type == 1) ? oal_netbuf_len(netbuf) : (oal_netbuf_len(netbuf) + tx_ctl->frame_header_length);
766
767 return (hi_u8)((netbuf_len > threshold) && (!tx_ctl->ismcast) && (!tx_ctl->is_amsdu) &&
768 (hmac_user->base_user->cur_protocol_mode < WLAN_HT_MODE || hmac_vap->base_vap->protocol < WLAN_HT_MODE) &&
769 (HI_FALSE == hmac_vap_ba_is_setup(hmac_user, tx_ctl->tid)));
770 }
771
772 /* ****************************************************************************
773 函 数 名 : hmac_tx_set_frame_ctrl
774 功能描述 : 设置帧控制
775 输入参数 : ul_qos 是否是QOS站点 pst_tx_ctl CB字段 pst_hdr 802.11头
776 输出参数 :
777 返 回 值 :
778 调用函数 :
779 被调函数 :
780
781 修改历史 :
782 1.日 期 : 2012年11月14日
783 作 者 : HiSilicon
784 修改内容 : 新生成函数
785
786 **************************************************************************** */
hmac_tx_set_frame_ctrl(hi_u32 qos,const hmac_tx_ctl_stru * tx_ctl,mac_ieee80211_qos_frame_addr4_stru * hdr_addr4)787 static hi_void hmac_tx_set_frame_ctrl(hi_u32 qos, const hmac_tx_ctl_stru *tx_ctl,
788 mac_ieee80211_qos_frame_addr4_stru *hdr_addr4)
789 {
790 mac_ieee80211_qos_frame_stru *hdr = HI_NULL;
791 hi_u8 is_amsdu;
792 if (qos == HMAC_TX_BSS_QOS) {
793 if (tx_ctl->netbuf_num == 1) {
794 is_amsdu = HI_FALSE;
795 } else {
796 is_amsdu = tx_ctl->is_amsdu;
797 }
798
799 /* 设置帧控制字段 */
800 mac_hdr_set_frame_control((hi_u8 *)hdr_addr4, (WLAN_FC0_SUBTYPE_QOS | WLAN_FC0_TYPE_DATA));
801
802 /* 更新帧头长度 */
803 if (tx_ctl->use_4_addr == HI_FALSE) {
804 hdr = (mac_ieee80211_qos_frame_stru *)hdr_addr4;
805 /* 设置QOS控制字段 */
806 hdr->qc_tid = tx_ctl->tid;
807 hdr->qc_eosp = 0;
808 hdr->qc_ack_polocy = tx_ctl->ack_policy;
809 hdr->qc_amsdu = is_amsdu;
810 hdr->qos_control.qc_txop_limit = 0;
811 } else {
812 /* 设置QOS控制字段 */
813 hdr_addr4->qc_tid = tx_ctl->tid;
814 hdr_addr4->qc_eosp = 0;
815 hdr_addr4->qc_ack_polocy = tx_ctl->ack_policy;
816 hdr_addr4->qc_amsdu = is_amsdu;
817 hdr_addr4->qos_control.qc_txop_limit = 0;
818 }
819
820 /* 由DMAC考虑是否需要HTC */
821 } else {
822 /* 设置帧控制字段 */
823 mac_hdr_set_frame_control((hi_u8 *)hdr_addr4, WLAN_FC0_TYPE_DATA | WLAN_FC0_SUBTYPE_DATA);
824 }
825 }
826
827 /* ****************************************************************************
828 功能描述 : 3地址ap模式设置MAC头地址
829 **************************************************************************** */
hmac_tx_ap_set_addresses(const hmac_vap_stru * hmac_vap,const hmac_tx_ctl_stru * tx_ctl,mac_ieee80211_frame_addr4_stru * hdr,const hmac_set_addresses_info_stru * set_addresses_info)830 static hi_u32 hmac_tx_ap_set_addresses(const hmac_vap_stru *hmac_vap, const hmac_tx_ctl_stru *tx_ctl,
831 mac_ieee80211_frame_addr4_stru *hdr, const hmac_set_addresses_info_stru *set_addresses_info)
832 {
833 /* From DS标识位设置 */
834 mac_hdr_set_from_ds((hi_u8 *)hdr, 1);
835 /* to DS标识位设置 */
836 mac_hdr_set_to_ds((hi_u8 *)hdr, 0);
837 /* Set Address1 field in the WLAN Header with destination address */
838 if (memcpy_s(hdr->auc_address1, WLAN_MAC_ADDR_LEN, set_addresses_info->puc_daddr, WLAN_MAC_ADDR_LEN) != EOK) {
839 return HI_FAIL;
840 }
841 /* Set Address2 field in the WLAN Header with the BSSID */
842 if (memcpy_s(hdr->auc_address2, WLAN_MAC_ADDR_LEN, hmac_vap->base_vap->auc_bssid, WLAN_MAC_ADDR_LEN) != EOK) {
843 return HI_FAIL;
844 }
845 /* AMSDU情况,地址3填写BSSID */
846 if (tx_ctl->is_amsdu) {
847 /* Set Address3 field in the WLAN Header with the BSSID */
848 if (memcpy_s(hdr->auc_address3, WLAN_MAC_ADDR_LEN, hmac_vap->base_vap->auc_bssid, WLAN_MAC_ADDR_LEN) != EOK) {
849 return HI_FAIL;
850 }
851 } else {
852 /* Set Address3 field in the WLAN Header with the source address */
853 if (memcpy_s(hdr->auc_address3, WLAN_MAC_ADDR_LEN, set_addresses_info->puc_saddr, WLAN_MAC_ADDR_LEN) != EOK) {
854 return HI_FAIL;
855 }
856 }
857 return HI_SUCCESS;
858 }
859
860 #ifdef _PRE_WLAN_FEATURE_MESH
861 /* ****************************************************************************
862 功能描述 : 3地址mesh模式设置MAC头地址
863 **************************************************************************** */
hmac_tx_mesh_set_addresses(const hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user,const hmac_tx_ctl_stru * tx_ctl,mac_ieee80211_frame_addr4_stru * hdr,const hmac_set_addresses_info_stru * set_addresses_info)864 static hi_u32 hmac_tx_mesh_set_addresses(const hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user,
865 const hmac_tx_ctl_stru *tx_ctl, mac_ieee80211_frame_addr4_stru *hdr,
866 const hmac_set_addresses_info_stru *set_addresses_info)
867 {
868 if (hmac_user->base_user->is_mesh_user == HI_TRUE) {
869 /* From DS标识位设置 */
870 mac_hdr_set_from_ds((hi_u8 *)hdr, 0);
871 /* to DS标识位设置 */
872 mac_hdr_set_to_ds((hi_u8 *)hdr, 0);
873 /* Set Address3 field in the WLAN Header with the BSSID */
874 if (memcpy_s(hdr->auc_address3, WLAN_MAC_ADDR_LEN, hmac_vap->base_vap->auc_bssid, WLAN_MAC_ADDR_LEN) != EOK) {
875 return HI_FAIL;
876 }
877 /* AMSDU情况,地址2填写BSSID */
878 if (tx_ctl->is_amsdu) {
879 /* Set Address3 field in the WLAN Header with the BSSID */
880 if (memcpy_s(hdr->auc_address2, WLAN_MAC_ADDR_LEN, hmac_vap->base_vap->auc_bssid, WLAN_MAC_ADDR_LEN) !=
881 EOK) {
882 return HI_FAIL;
883 }
884 } else {
885 /* Set Address3 field in the WLAN Header with the source address */
886 if (memcpy_s(hdr->auc_address2, WLAN_MAC_ADDR_LEN, set_addresses_info->puc_saddr, WLAN_MAC_ADDR_LEN) !=
887 EOK) {
888 return HI_FAIL;
889 }
890 }
891 } else {
892 /* From DS标识位设置 */
893 mac_hdr_set_from_ds((hi_u8 *)hdr, 1);
894 /* to DS标识位设置 */
895 mac_hdr_set_to_ds((hi_u8 *)hdr, 0);
896 /* Set Address2 field in the WLAN Header with the BSSID */
897 if (memcpy_s(hdr->auc_address2, WLAN_MAC_ADDR_LEN, hmac_vap->base_vap->auc_bssid, WLAN_MAC_ADDR_LEN) != EOK) {
898 return HI_FAIL;
899 }
900 /* AMSDU情况,地址3填写BSSID */
901 if (tx_ctl->is_amsdu) {
902 /* Set Address3 field in the WLAN Header with the BSSID */
903 if (memcpy_s(hdr->auc_address3, WLAN_MAC_ADDR_LEN, hmac_vap->base_vap->auc_bssid, WLAN_MAC_ADDR_LEN) !=
904 EOK) {
905 return HI_FAIL;
906 }
907 } else {
908 /* Set Address3 field in the WLAN Header with the source address */
909 if (memcpy_s(hdr->auc_address3, WLAN_MAC_ADDR_LEN, set_addresses_info->puc_saddr, WLAN_MAC_ADDR_LEN) !=
910 EOK) {
911 return HI_FAIL;
912 }
913 }
914 }
915
916 /* Set Address1 field in the WLAN Header with destination address */
917 if (memcpy_s(hdr->auc_address1, WLAN_MAC_ADDR_LEN, set_addresses_info->puc_daddr, WLAN_MAC_ADDR_LEN) != EOK) {
918 return HI_FAIL;
919 }
920 return HI_SUCCESS;
921 }
922 #endif
923
924 /* ****************************************************************************
925 功能描述 : sta模式设置MAC头地址
926 **************************************************************************** */
hmac_tx_sta_set_addresses(const hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user,const hmac_tx_ctl_stru * tx_ctl,mac_ieee80211_frame_addr4_stru * hdr,const hmac_set_addresses_info_stru * set_addresses_info)927 static hi_u32 hmac_tx_sta_set_addresses(const hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user,
928 const hmac_tx_ctl_stru *tx_ctl, mac_ieee80211_frame_addr4_stru *hdr,
929 const hmac_set_addresses_info_stru *set_addresses_info)
930 {
931 /* From DS标识位设置 */
932 mac_hdr_set_from_ds((hi_u8 *)hdr, 0);
933 /* to DS标识位设置 */
934 mac_hdr_set_to_ds((hi_u8 *)hdr, 1);
935 /* Set Address1 field in the WLAN Header with BSSID */
936 if (memcpy_s(hdr->auc_address1, WLAN_MAC_ADDR_LEN,
937 hmac_user->base_user->user_mac_addr, WLAN_MAC_ADDR_LEN) != EOK) {
938 return HI_FAIL;
939 }
940 if (set_addresses_info->us_ether_type == hi_swap_byteorder_16(ETHER_LLTD_TYPE)) {
941 /* Set Address2 field in the WLAN Header with the source address */
942 if (memcpy_s(hdr->auc_address2, WLAN_MAC_ADDR_LEN, set_addresses_info->puc_saddr, WLAN_MAC_ADDR_LEN) != EOK) {
943 return HI_FAIL;
944 }
945 } else {
946 /* Set Address2 field in the WLAN Header with the source address */
947 if (memcpy_s(hdr->auc_address2, WLAN_MAC_ADDR_LEN,
948 hmac_vap->base_vap->mib_info->wlan_mib_sta_config.auc_dot11_station_id, WLAN_MAC_ADDR_LEN) != EOK) {
949 return HI_FAIL;
950 }
951 }
952 if (tx_ctl->is_amsdu) /* AMSDU情况,地址3填写BSSID */ {
953 /* Set Address3 field in the WLAN Header with the BSSID */
954 if (memcpy_s(hdr->auc_address3, WLAN_MAC_ADDR_LEN,
955 hmac_user->base_user->user_mac_addr, WLAN_MAC_ADDR_LEN) != EOK) {
956 return HI_FAIL;
957 }
958 } else {
959 /* Set Address3 field in the WLAN Header with the destination address */
960 if (memcpy_s(hdr->auc_address3, WLAN_MAC_ADDR_LEN, set_addresses_info->puc_daddr, WLAN_MAC_ADDR_LEN) != EOK) {
961 return HI_FAIL;
962 }
963 }
964 return HI_SUCCESS;
965 }
966
967 /* ****************************************************************************
968 功能描述 : 4地址wds模式设置MAC头地址
969 **************************************************************************** */
hmac_tx_wds_set_addresses(const hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user,const hmac_tx_ctl_stru * tx_ctl,mac_ieee80211_frame_addr4_stru * hdr,const hmac_set_addresses_info_stru * set_addresses_info)970 static hi_u32 hmac_tx_wds_set_addresses(const hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user,
971 const hmac_tx_ctl_stru *tx_ctl, mac_ieee80211_frame_addr4_stru *hdr,
972 const hmac_set_addresses_info_stru *set_addresses_info)
973 {
974 /* TO DS标识位设置 */
975 mac_hdr_set_to_ds((hi_u8 *)hdr, 1);
976 /* From DS标识位设置 */
977 mac_hdr_set_from_ds((hi_u8 *)hdr, 1);
978 /* 地址1是 RA */
979 if (memcpy_s(hdr->auc_address1, WLAN_MAC_ADDR_LEN,
980 hmac_user->base_user->user_mac_addr, WLAN_MAC_ADDR_LEN) != EOK) {
981 return HI_FAIL;
982 }
983 /* 地址2是 TA (当前只有BSSID) */
984 if (memcpy_s(hdr->auc_address2, WLAN_MAC_ADDR_LEN, hmac_vap->base_vap->auc_bssid, WLAN_MAC_ADDR_LEN) != EOK) {
985 return HI_FAIL;
986 }
987
988 /* AMSDU情况,地址3和地址4填写BSSID */
989 if (tx_ctl->is_amsdu) {
990 /* 地址3是 BSSID */
991 if (memcpy_s(hdr->auc_address3, WLAN_MAC_ADDR_LEN, hmac_vap->base_vap->auc_bssid, WLAN_MAC_ADDR_LEN) != EOK) {
992 return HI_FAIL;
993 }
994
995 /* 地址4也是 BSSID */
996 if (memcpy_s(hdr->auc_address4, WLAN_MAC_ADDR_LEN, hmac_vap->base_vap->auc_bssid, WLAN_MAC_ADDR_LEN) != EOK) {
997 return HI_FAIL;
998 }
999 } else {
1000 /* 地址3是 DA */
1001 if (memcpy_s(hdr->auc_address3, WLAN_MAC_ADDR_LEN, set_addresses_info->puc_daddr, WLAN_MAC_ADDR_LEN) != EOK) {
1002 return HI_FAIL;
1003 }
1004 /* 地址4是 SA */
1005 if (memcpy_s(hdr->auc_address4, WLAN_MAC_ADDR_LEN, set_addresses_info->puc_saddr, WLAN_MAC_ADDR_LEN) != EOK) {
1006 return HI_FAIL;
1007 }
1008 }
1009 return HI_SUCCESS;
1010 }
1011
1012 /* ****************************************************************************
1013 功能描述 : 设置帧地址控制
1014 修改历史 :
1015 1.日 期 : 2012年11月14日
1016 作 者 : HiSilicon
1017 修改内容 : 新生成函数
1018 **************************************************************************** */
hmac_tx_set_addresses(const hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user,const hmac_tx_ctl_stru * tx_ctl,mac_ieee80211_frame_addr4_stru * hdr,const hmac_set_addresses_info_stru * set_addresses_info)1019 static hi_u32 hmac_tx_set_addresses(const hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user,
1020 const hmac_tx_ctl_stru *tx_ctl, mac_ieee80211_frame_addr4_stru *hdr,
1021 const hmac_set_addresses_info_stru *set_addresses_info)
1022 {
1023 /* 分片号置成0,后续分片特性需要重新赋值 */
1024 hdr->frag_num = 0;
1025 hdr->seq_num = 0;
1026
1027 /* From AP */
1028 if ((hmac_vap->base_vap->vap_mode == WLAN_VAP_MODE_BSS_AP) && (!(tx_ctl->use_4_addr))) {
1029 return hmac_tx_ap_set_addresses(hmac_vap, tx_ctl, hdr, set_addresses_info);
1030 #ifdef _PRE_WLAN_FEATURE_MESH
1031 } else if ((hmac_vap->base_vap->vap_mode == WLAN_VAP_MODE_MESH) && (!(tx_ctl->use_4_addr))) {
1032 return hmac_tx_mesh_set_addresses(hmac_vap, hmac_user, tx_ctl, hdr, set_addresses_info);
1033 #endif
1034 } else if (hmac_vap->base_vap->vap_mode == WLAN_VAP_MODE_BSS_STA) {
1035 return hmac_tx_sta_set_addresses(hmac_vap, hmac_user, tx_ctl, hdr, set_addresses_info);
1036 } else { /* WDS */
1037 return hmac_tx_wds_set_addresses(hmac_vap, hmac_user, tx_ctl, hdr, set_addresses_info);
1038 }
1039 }
1040
1041 /* ****************************************************************************
1042 函 数 名 : hmac_tx_encap
1043 功能描述 : 802.11帧头封装 AP模式
1044 输入参数 : pst_vap-vap结构体
1045 pst_user-用户结构体
1046 pst_buf-BUF结构体
1047 输出参数 : pst_ret_hdr-返回的头部
1048 返 回 值 : HI_NULL 或者 802.11帧头指针
1049 调用函数 : AMSDU模块以及本文件
1050 被调函数 :
1051
1052 修改历史 :
1053 1.日 期 : 2012年11月14日
1054 作 者 : HiSilicon
1055 修改内容 : 新生成函数
1056
1057 **************************************************************************** */
1058 /* 编程规范规则5.1 避免函数过长,函数不超过50行(非空非注释),申请例外: 帧封装函数,功能聚合完整,不建议拆分 */
hmac_tx_encap(const hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user,oal_netbuf_stru * netbuf)1059 hi_u32 hmac_tx_encap(const hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user, oal_netbuf_stru *netbuf)
1060 {
1061 mac_ieee80211_qos_frame_addr4_stru *hdr = HI_NULL; /* 802.11头 */
1062 mac_ieee80211_qos_htc_frame_addr4_stru *hdr_max = HI_NULL; /* 最大的802.11头,申请空间使用 */
1063 hi_u32 qos = HMAC_TX_BSS_NOQOS;
1064 hi_u16 us_ether_type = 0;
1065 hi_u8 auc_saddr[ETHER_ADDR_LEN]; /* 原地址指针 */
1066 hi_u8 auc_daddr[ETHER_ADDR_LEN]; /* 目的地址指针 */
1067 hi_u32 ret;
1068 hmac_set_addresses_info_stru set_addresses_info;
1069
1070 /* 获取CB */
1071 hmac_tx_ctl_stru *tx_ctl = (hmac_tx_ctl_stru *)(oal_netbuf_cb(netbuf));
1072
1073 /* 增加长度校验 防止上层下发长度异常的报文 */
1074 if (oal_netbuf_len(netbuf) < sizeof(mac_ether_header_stru)) {
1075 oam_error_log1(0, 0, "{hmac_tx_encap::netbuff len is invalid: %d!}", oal_netbuf_len(netbuf));
1076 return HI_FAIL;
1077 }
1078 /* 获取以太网头, 原地址,目的地址, 以太网类型 */
1079 mac_ether_header_stru *ether_hdr = (mac_ether_header_stru *)oal_netbuf_data(netbuf);
1080 if (memcpy_s((hi_u8 *)auc_daddr, ETHER_ADDR_LEN, ether_hdr->auc_ether_dhost, ETHER_ADDR_LEN) != EOK) {
1081 return HI_FAIL;
1082 }
1083 if (memcpy_s((hi_u8 *)auc_saddr, ETHER_ADDR_LEN, ether_hdr->auc_ether_shost, ETHER_ADDR_LEN) != EOK) {
1084 return HI_FAIL;
1085 }
1086
1087 /* 如果skb中data指针前预留的空间大于802.11 mac head len,则不需要格外申请内存存放802.11头 */
1088 if (oal_netbuf_headroom(netbuf) >= MAC_80211_QOS_HTC_4ADDR_FRAME_LEN) {
1089 tx_ctl->mac_head_type = 1; /* 指示mac头部在skb中 */
1090 } else {
1091 /* 申请最大的80211头 */
1092 hdr_max = (mac_ieee80211_qos_htc_frame_addr4_stru *)oal_memalloc(MAC_80211_QOS_HTC_4ADDR_FRAME_LEN);
1093 if (oal_unlikely(hdr_max == HI_NULL)) {
1094 oam_error_log0(hmac_vap->base_vap->vap_id, OAM_SF_TX, "{hmac_tx_encap::pst_hdr null.}");
1095 return HI_ERR_CODE_PTR_NULL;
1096 }
1097
1098 hdr = (mac_ieee80211_qos_frame_addr4_stru *)hdr_max;
1099 tx_ctl->mac_head_type = 0; /* 指示mac头部不在skb中,申请了额外内存存放的 */
1100 }
1101
1102 /* 非amsdu帧 */
1103 if (tx_ctl->is_amsdu == HI_FALSE) {
1104 us_ether_type = ether_hdr->us_ether_type;
1105 } else {
1106 /* 如果是AMSDU的第一个子帧,需要从snap头中获取以太网类型,如果是以太网帧,可以
1107 直接从以太网头中获取 */
1108 mac_llc_snap_stru *snap_hdr = (mac_llc_snap_stru *)((hi_u8 *)ether_hdr + ETHER_HDR_LEN);
1109 us_ether_type = snap_hdr->us_ether_type;
1110 }
1111
1112 /* 非组播帧,获取用户的QOS能力位信息 */
1113 if (tx_ctl->ismcast == HI_FALSE) {
1114 /* 根据用户结构体的cap_info,判断是否是QOS站点 */
1115 qos = hmac_user->base_user->cap_info.qos;
1116 tx_ctl->is_qosdata = hmac_user->base_user->cap_info.qos;
1117 }
1118
1119 /* 对于LAN to WLAN的非AMSDU聚合帧,填充LLC SNAP头 */
1120 if (tx_ctl->is_amsdu == HI_FALSE) {
1121 mac_set_snap(netbuf, us_ether_type, (ETHER_HDR_LEN - SNAP_LLC_FRAME_LEN));
1122 /* 更新frame长度 */
1123 tx_ctl->us_mpdu_len = (hi_u16)oal_netbuf_len(netbuf);
1124
1125 /* 非amsdu聚合帧,记录mpdu字节数,不包括snap */
1126 tx_ctl->us_mpdu_bytes = (hi_u16)(tx_ctl->us_mpdu_len - SNAP_LLC_FRAME_LEN);
1127 }
1128
1129 tx_ctl->frame_header_length = hmac_get_frame_header_len(qos, tx_ctl);
1130
1131 /* mac头部在skb中时,netbuf的data指针指向mac头。但是mac_set_snap函数中已经将data指针指向了llc头。
1132 因此这里要重新push到mac头。 */
1133 if (tx_ctl->mac_head_type == 1) {
1134 oal_netbuf_push(netbuf, tx_ctl->frame_header_length);
1135 hdr = (mac_ieee80211_qos_frame_addr4_stru *)oal_netbuf_data(netbuf);
1136 }
1137
1138 /* 设置帧控制 */
1139 hmac_tx_set_frame_ctrl(qos, tx_ctl, hdr);
1140
1141 /* 设置地址 */
1142 set_addresses_info.puc_saddr = auc_saddr;
1143 set_addresses_info.puc_daddr = auc_daddr;
1144 set_addresses_info.us_ether_type = us_ether_type;
1145 ret = hmac_tx_set_addresses(hmac_vap, hmac_user, tx_ctl, (mac_ieee80211_frame_addr4_stru *)hdr,
1146 &set_addresses_info);
1147 if (oal_unlikely(ret != HI_SUCCESS)) {
1148 if (tx_ctl->mac_head_type == 0) {
1149 oal_free(hdr_max);
1150 }
1151 oam_error_log1(hmac_vap->base_vap->vap_id, OAM_SF_TX,
1152 "{hmac_tx_encap::hmac_tx_set_addresses failed[%d].}", ret);
1153 return ret;
1154 }
1155
1156 /* 挂接802.11头 */
1157 tx_ctl->frame_header = (mac_ieee80211_frame_stru *)hdr;
1158 /* 分片处理 */
1159 if (HI_TRUE == hmac_tx_is_need_frag(hmac_vap, hmac_user, netbuf, tx_ctl)) {
1160 #if (_PRE_MULTI_CORE_MODE_OFFLOAD_DMAC != _PRE_MULTI_CORE_MODE)
1161 hmac_nonqos_frame_set_sn(tx_ctl);
1162 #endif
1163 ret = hmac_frag_process_proc(hmac_vap, hmac_user, netbuf, tx_ctl);
1164 }
1165
1166 return ret;
1167 }
1168
1169 /* ****************************************************************************
1170 函 数 名 : hmac_tx_mpdu_process
1171 功能描述 : 单个MPDU处理函数
1172 输入参数 : pst_event-事件结构体
1173 pst_vap-vap结构体
1174 pst_buf-BUF结构体
1175 pst_tx_ctl-CB结构体
1176 输出参数 : 无
1177 返 回 值 :
1178 调用函数 :
1179 被调函数 :
1180
1181 修改历史 :
1182 1.日 期 : 2012年11月13日
1183 作 者 : HiSilicon
1184 修改内容 : 新生成函数
1185
1186 **************************************************************************** */
hmac_tx_lan_mpdu_process_sta(hmac_vap_stru * hmac_vap,oal_netbuf_stru * netbuf,hmac_tx_ctl_stru * tx_ctl)1187 static hmac_tx_return_type_enum_uint8 hmac_tx_lan_mpdu_process_sta(hmac_vap_stru *hmac_vap, oal_netbuf_stru *netbuf,
1188 hmac_tx_ctl_stru *tx_ctl)
1189 {
1190 hmac_user_stru *hmac_user = HI_NULL; /* 目标STA结构体 */
1191 mac_ether_header_stru *ether_hdr = HI_NULL; /* 以太网头 */
1192 hi_u32 ret;
1193 hmac_tx_return_type_enum_uint8 hmac_tx_ret;
1194 hi_u8 user_idx;
1195 hi_u8 *puc_ether_payload = HI_NULL;
1196
1197 ether_hdr = (mac_ether_header_stru *)oal_netbuf_data(netbuf);
1198 tx_ctl->tx_vap_index = hmac_vap->base_vap->vap_id;
1199
1200 user_idx = hmac_vap->base_vap->assoc_vap_id;
1201
1202 hmac_user = (hmac_user_stru *)hmac_user_get_user_stru(user_idx);
1203 if (hmac_user == HI_NULL) {
1204 return HMAC_TX_DROP_USER_NULL;
1205 }
1206
1207 if (hi_swap_byteorder_16(ETHER_TYPE_ARP) == ether_hdr->us_ether_type) {
1208 ether_hdr++;
1209 puc_ether_payload = (hi_u8 *)ether_hdr;
1210 /* The source MAC address is modified only if the packet is an */
1211 /* ARP Request or a Response. The appropriate bytes are checked. */
1212 /* Type field (2 bytes): ARP Request (1) or an ARP Response (2) */
1213 if ((puc_ether_payload[6] == 0x00) && /* 6 元素索引 */
1214 (puc_ether_payload[7] == 0x02 || puc_ether_payload[7] == 0x01)) { /* 7 元素索引 */
1215 /* Set Address2 field in the WLAN Header with source address */
1216 if (memcpy_s(puc_ether_payload + 8, WLAN_MAC_ADDR_LEN, /* 8 偏移量 */
1217 hmac_vap->base_vap->mib_info->wlan_mib_sta_config.auc_dot11_station_id, WLAN_MAC_ADDR_LEN) != EOK) {
1218 return HMAC_TX_DROP_80211_ENCAP_FAIL;
1219 }
1220 }
1221 }
1222
1223 tx_ctl->us_tx_user_idx = user_idx;
1224
1225 hmac_tx_ret = hmac_tx_ucast_process(hmac_vap, netbuf, hmac_user, tx_ctl);
1226 if (oal_unlikely(hmac_tx_ret != HMAC_TX_PASS)) {
1227 return hmac_tx_ret;
1228 }
1229
1230 /* 封装802.11头 */
1231 ret = hmac_tx_encap(hmac_vap, hmac_user, netbuf);
1232 if (oal_unlikely((ret != HI_SUCCESS))) {
1233 oam_warning_log1(hmac_vap->base_vap->vap_id, OAM_SF_TX,
1234 "{hmac_tx_lan_mpdu_process_sta::hmac_tx_encap failed[%d].}", ret);
1235 return HMAC_TX_DROP_80211_ENCAP_FAIL;
1236 }
1237
1238 return HMAC_TX_PASS;
1239 }
1240
1241 /* ****************************************************************************
1242 函 数 名 : hmac_tx_mpdu_process
1243 功能描述 : 单个MPDU处理函数
1244 输入参数 : pst_event-事件结构体
1245 pst_vap-vap结构体
1246 pst_buf-BUF结构体
1247 pst_tx_ctl-CB结构体
1248 输出参数 : 无
1249 返 回 值 :
1250 调用函数 :
1251 被调函数 :
1252
1253 修改历史 :
1254 1.日 期 : 2012年11月13日
1255 作 者 : HiSilicon
1256 修改内容 : 新生成函数
1257
1258 **************************************************************************** */
hmac_tx_lan_mpdu_process_ap(hmac_vap_stru * hmac_vap,oal_netbuf_stru * netbuf,hmac_tx_ctl_stru * tx_ctl)1259 static hmac_tx_return_type_enum_uint8 hmac_tx_lan_mpdu_process_ap(hmac_vap_stru *hmac_vap, oal_netbuf_stru *netbuf,
1260 hmac_tx_ctl_stru *tx_ctl)
1261 {
1262 hmac_user_stru *hmac_user = HI_NULL; /* 目标STA结构体 */
1263 hi_u8 user_idx = 0;
1264
1265 /* 判断是组播或单播,对于lan to wlan的单播帧,返回以太网地址 */
1266 mac_ether_header_stru *ether_hdr = (mac_ether_header_stru *)oal_netbuf_data(netbuf);
1267 hi_u8 *mac_addr = ether_hdr->auc_ether_dhost; /* 目的地址 */
1268
1269 /* 单播数据帧 */
1270 if (oal_likely(!ether_is_multicast(mac_addr))) {
1271 hi_u32 ret = mac_vap_find_user_by_macaddr(hmac_vap->base_vap, mac_addr, ETHER_ADDR_LEN, &user_idx);
1272 if (oal_unlikely(ret != HI_SUCCESS)) {
1273 oam_info_log3(hmac_vap->base_vap->vap_id, OAM_SF_TX,
1274 "{hmac_tx_lan_mpdu_process_ap::hmac_tx_find_user failed xx:xx:xx:%2x:%2x:%2x}", mac_addr[3],
1275 mac_addr[4], mac_addr[5]); /* 3 4 5 元素索引 */
1276 return HMAC_TX_DROP_USER_UNKNOWN;
1277 }
1278
1279 /* 转成HMAC的USER结构体 */
1280 hmac_user = (hmac_user_stru *)hmac_user_get_user_stru(user_idx);
1281 if (oal_unlikely((hmac_user == HI_NULL) || (hmac_user->base_user == HI_NULL))) {
1282 return HMAC_TX_DROP_USER_NULL;
1283 }
1284
1285 /* 用户状态判断 */
1286 if (oal_unlikely(hmac_user->base_user->user_asoc_state != MAC_USER_STATE_ASSOC)) {
1287 return HMAC_TX_DROP_USER_INACTIVE;
1288 }
1289
1290 /* 目标user指针 */
1291 tx_ctl->us_tx_user_idx = user_idx;
1292
1293 hmac_tx_return_type_enum_uint8 hmac_tx_ret = hmac_tx_ucast_process(hmac_vap, netbuf, hmac_user, tx_ctl);
1294 if (oal_unlikely(hmac_tx_ret != HMAC_TX_PASS)) {
1295 return hmac_tx_ret;
1296 }
1297 } else { /* 组播 or 广播 */
1298 /* 设置组播标识位 */
1299 tx_ctl->ismcast = HI_TRUE;
1300
1301 /* 更新ACK策略 */
1302 tx_ctl->ack_policy = WLAN_TX_NO_ACK;
1303
1304 /* 获取组播用户 */
1305 hmac_user = (hmac_user_stru *)hmac_user_get_user_stru(hmac_vap->base_vap->multi_user_idx);
1306 if (oal_unlikely(hmac_user == HI_NULL)) {
1307 oam_warning_log1(hmac_vap->base_vap->vap_id, OAM_SF_TX,
1308 "{hmac_tx_lan_mpdu_process_ap::get multi user failed[%d].}", hmac_vap->base_vap->multi_user_idx);
1309 return HMAC_TX_DROP_MUSER_NULL;
1310 }
1311
1312 tx_ctl->us_tx_user_idx = hmac_vap->base_vap->multi_user_idx;
1313 tx_ctl->tid = WLAN_TIDNO_BCAST;
1314 tx_ctl->ac = wlan_wme_tid_to_ac(tx_ctl->tid);
1315 }
1316
1317 /* 封装802.11头 */
1318 hi_u32 rst = hmac_tx_encap(hmac_vap, hmac_user, netbuf);
1319 if (oal_unlikely((rst != HI_SUCCESS))) {
1320 oam_warning_log1(hmac_vap->base_vap->vap_id, OAM_SF_TX,
1321 "{hmac_tx_lan_mpdu_process_ap::hmac_tx_encap failed[%d].}", rst);
1322 return HMAC_TX_DROP_80211_ENCAP_FAIL;
1323 }
1324
1325 return HMAC_TX_PASS;
1326 }
1327
hmac_tx_lan_to_wlan_no_tcp_opt_vap(const mac_vap_stru * mac_vap,oal_netbuf_stru * netbuf,hmac_vap_stru * hmac_vap,hmac_tx_ctl_stru ** tx_ctl_ptr,hmac_tx_return_type_enum_uint8 * hmac_tx_ret)1328 static hi_u32 hmac_tx_lan_to_wlan_no_tcp_opt_vap(const mac_vap_stru *mac_vap, oal_netbuf_stru *netbuf,
1329 hmac_vap_stru *hmac_vap, hmac_tx_ctl_stru **tx_ctl_ptr, hmac_tx_return_type_enum_uint8 *hmac_tx_ret)
1330 {
1331 hmac_tx_ctl_stru *tx_ctl = *tx_ctl_ptr;
1332 if (hmac_vap->base_vap->vap_mode == WLAN_VAP_MODE_BSS_AP
1333 #ifdef _PRE_WLAN_FEATURE_MESH
1334 || (hmac_vap->base_vap->vap_mode == WLAN_VAP_MODE_MESH)
1335 #endif
1336 ) {
1337 /* 处理当前 MPDU */
1338 if (mac_vap->mib_info->wlan_mib_sta_config.dot11_qos_option_implemented == HI_FALSE) {
1339 tx_ctl->ac = WLAN_WME_AC_VO; /* AP模式 关WMM 入VO队列 */
1340 tx_ctl->tid = wlan_wme_ac_to_tid(tx_ctl->ac);
1341 }
1342
1343 *hmac_tx_ret = hmac_tx_lan_mpdu_process_ap(hmac_vap, netbuf, tx_ctl);
1344 } else if (hmac_vap->base_vap->vap_mode == WLAN_VAP_MODE_BSS_STA) {
1345 /* 处理当前MPDU */
1346 tx_ctl->ac = WLAN_WME_AC_VO; /* STA模式 非qos帧入VO队列 */
1347 tx_ctl->tid = wlan_wme_ac_to_tid(tx_ctl->ac);
1348
1349 *hmac_tx_ret = hmac_tx_lan_mpdu_process_sta(hmac_vap, netbuf, tx_ctl);
1350 #ifdef _PRE_WLAN_FEATURE_WAPI
1351 if (*hmac_tx_ret == HMAC_TX_PASS) {
1352 hmac_user_stru *hmac_user = (hmac_user_stru *)hmac_user_get_user_stru(mac_vap->assoc_vap_id);
1353 if ((hmac_user == HI_NULL) || (hmac_user->base_user == HI_NULL)) {
1354 oam_warning_log1(0, 0, "hmac_tx_lan_to_wlan_no_tcp_opt_vap::usrid==%u !}", mac_vap->assoc_vap_id);
1355 return HMAC_TX_DROP_USER_NULL;
1356 }
1357
1358 /* 获取wapi对象 组播/单播 */
1359 mac_ieee80211_frame_stru *mac_hdr = ((hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf))->frame_header;
1360 hi_bool pairwise = !ether_is_multicast(mac_hdr->auc_address1);
1361 hmac_wapi_stru *wapi = hmac_user_get_wapi_ptr(mac_vap, pairwise, (hi_u8)hmac_user->base_user->us_assoc_id);
1362 if (wapi == HI_NULL) {
1363 oam_error_log0(0, 0, "{hmac_tx_lan_to_wlan_no_tcp_opt_vap::pst_wapi null.}");
1364 return HI_FAIL;
1365 }
1366 if ((wapi_is_port_valid(wapi) == HI_TRUE) && (wapi->wapi_netbuff_txhandle != HI_NULL)) {
1367 netbuf = wapi->wapi_netbuff_txhandle(wapi, netbuf);
1368 /* 由于wapi可能修改netbuff,此处需要重新获取一下cb */
1369 tx_ctl = (hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf);
1370 *tx_ctl_ptr = tx_ctl;
1371 }
1372 }
1373
1374 #endif /* #ifdef _PRE_WLAN_FEATURE_WAPI */
1375 }
1376
1377 return HI_SUCCESS;
1378 }
1379
hmac_tx_lan_to_wlan_no_tcp_opt_vap_mode(mac_vap_stru * mac_vap,const hmac_vap_stru * hmac_vap)1380 static hi_u32 hmac_tx_lan_to_wlan_no_tcp_opt_vap_mode(mac_vap_stru *mac_vap, const hmac_vap_stru *hmac_vap)
1381 {
1382 /* VAP模式判断 */
1383 if (mac_vap->vap_mode != WLAN_VAP_MODE_BSS_AP && mac_vap->vap_mode != WLAN_VAP_MODE_BSS_STA
1384 #ifdef _PRE_WLAN_FEATURE_MESH
1385 && (mac_vap->vap_mode != WLAN_VAP_MODE_MESH)
1386 #endif
1387 ) {
1388 oam_warning_log1(mac_vap->vap_id, OAM_SF_TX, "{hmac_tx_lan_to_wlan_no_tcp_opt_vap_mode::en_vap_mode=%d.}",
1389 mac_vap->vap_mode);
1390 return HI_ERR_CODE_CONFIG_UNSUPPORT;
1391 }
1392
1393 /* 如果关联用户数量为0,则丢弃报文 */
1394 if (oal_unlikely(hmac_vap->base_vap->user_nums == 0)) {
1395 return HI_FAIL;
1396 }
1397 #ifdef _PRE_WLAN_FEATURE_ALWAYS_TX
1398 /* 发数据,只发一次,避免反复申请tx描述符地址 */
1399 if (mac_vap->al_tx_flag == HI_SWITCH_ON) {
1400 if (mac_vap->first_run != HI_FALSE) {
1401 return HI_SUCCESS;
1402 }
1403 mac_vap_set_al_tx_first_run(mac_vap, HI_TRUE);
1404 }
1405 #endif
1406
1407 return HI_CONTINUE;
1408 }
1409
hmac_tx_lan_to_wlan_no_tcp_opt_to_dmac(const mac_vap_stru * mac_vap,oal_netbuf_stru * netbuf,const hmac_tx_ctl_stru * tx_ctl,hmac_tx_return_type_enum_uint8 hmac_tx_ret)1410 static hi_u32 hmac_tx_lan_to_wlan_no_tcp_opt_to_dmac(const mac_vap_stru *mac_vap, oal_netbuf_stru *netbuf,
1411 const hmac_tx_ctl_stru *tx_ctl, hmac_tx_return_type_enum_uint8 hmac_tx_ret)
1412 {
1413 hi_u32 ret = (hi_u32)hmac_tx_ret;
1414
1415 if (oal_likely(hmac_tx_ret == HMAC_TX_PASS)) {
1416 /* 抛事件,传给DMAC */
1417 frw_event_mem_stru *event_mem = frw_event_alloc(sizeof(dmac_tx_event_stru));
1418 if (oal_unlikely(event_mem == HI_NULL)) {
1419 oam_error_log0(0, OAM_SF_TX, "{hmac_tx_lan_to_wlan_no_tcp_opt_to_dmac::frw_event_alloc failed.}");
1420 return HI_ERR_CODE_ALLOC_MEM_FAIL;
1421 }
1422
1423 frw_event_stru *event = (frw_event_stru *)event_mem->puc_data; /* 事件结构体 */
1424
1425 /* 填写事件头 */
1426 frw_event_hdr_init(&(event->event_hdr), FRW_EVENT_TYPE_HOST_DRX, DMAC_TX_HOST_DRX, sizeof(dmac_tx_event_stru),
1427 FRW_EVENT_PIPELINE_STAGE_1, mac_vap->vap_id);
1428
1429 dmac_tx_event_stru *dtx_stru = (dmac_tx_event_stru *)event->auc_event_data;
1430 dtx_stru->netbuf = netbuf;
1431 dtx_stru->us_frame_len = tx_ctl->us_mpdu_len;
1432
1433 /* 调度事件 */
1434 ret = hcc_hmac_tx_data_event(event_mem, netbuf, HI_FALSE);
1435 /* 释放事件 */
1436 frw_event_free(event_mem);
1437 } else if ((oal_unlikely(hmac_tx_ret == HMAC_TX_BUFF)) || (hmac_tx_ret == HMAC_TX_DONE)) {
1438 hmac_free_netbuf_list(netbuf);
1439 ret = HI_SUCCESS;
1440 }
1441
1442 return ret;
1443 }
1444
1445 /* ****************************************************************************
1446 函 数 名 : hmac_tx_wlan_to_wlan_ap
1447 功能描述 : (1)WLAN TO WLAN流程tx入口函数,接收rx流程抛过来的netbuf或者netbuf链,
1448 其中每一个netbuf里面有一个MSDU,每一个MSDU的内容是一个以太网格式的
1449 帧。如果是netbuf链,第一个netbuf的prev指针为空,最后一个netbuf的
1450 next指针为空。
1451 (2)函数循环调用LAN TO WLAN的入口函数来处理每一个MSDU,这样就把
1452 WLAN TO WLAN流程统一到了LAN TO WLAN流程
1453 输入参数 : pst_event_mem-事件内存块
1454 输出参数 : 无
1455 返 回 值 : HI_SUCCESS或其它错误码
1456 调用函数 :
1457 被调函数 :
1458
1459 修改历史 :
1460 1.日 期 : 2012年11月13日
1461 作 者 : HiSilicon
1462 修改内容 : 新生成函数
1463
1464 **************************************************************************** */
hmac_tx_wlan_to_wlan_ap(oal_mem_stru * event_mem)1465 hi_u32 hmac_tx_wlan_to_wlan_ap(oal_mem_stru *event_mem)
1466 {
1467 frw_event_stru *event = HI_NULL; /* 事件结构体 */
1468 mac_vap_stru *mac_vap = HI_NULL;
1469 oal_netbuf_stru *netbuf = HI_NULL; /* 从netbuf链上取下来的指向netbuf的指针 */
1470 oal_netbuf_stru *buf_tmp = HI_NULL; /* 暂存netbuf指针,用于while循环 */
1471 hmac_tx_ctl_stru *tx_ctl = HI_NULL;
1472 hi_u32 ret;
1473 if (oal_unlikely(event_mem == HI_NULL)) {
1474 oam_error_log0(0, OAM_SF_WOW, "{hmac_wow_proc_dev_ready_slp_event::event_mem is null.}");
1475 return HI_ERR_CODE_PTR_NULL;
1476 }
1477
1478 /* 获取事件 */
1479 event = (frw_event_stru *)event_mem->puc_data;
1480
1481 /* 获取PAYLOAD中的netbuf链 */
1482 netbuf = (oal_netbuf_stru *)(*((uintptr_t *)(event->auc_event_data)));
1483
1484 ret = hmac_tx_get_mac_vap(event->event_hdr.vap_id, &mac_vap);
1485 if (oal_unlikely(ret != HI_SUCCESS)) {
1486 oam_error_log1(0, OAM_SF_TX, "{hmac_tx_wlan_to_wlan_ap::hmac_tx_get_mac_vap failed[%d].}", ret);
1487 hmac_free_netbuf_list(netbuf);
1488 return ret;
1489 }
1490
1491 /* 循环处理每一个netbuf,按照以太网帧的方式处理 */
1492 while (netbuf != HI_NULL) {
1493 buf_tmp = oal_netbuf_next(netbuf);
1494
1495 set_oal_netbuf_next(netbuf, HI_NULL);
1496 set_oal_netbuf_prev(netbuf, HI_NULL);
1497
1498 /* 由于此netbuf来自接收流程,是从内存池申请的,而以太网过来的netbuf是从
1499 操作系统申请的,二者的释放方式不一样,后续要通过事件类型字段来选择正确
1500 的释放方式
1501 */
1502 tx_ctl = (hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf);
1503 if (memset_s(tx_ctl, sizeof(hmac_tx_ctl_stru), 0, sizeof(hmac_tx_ctl_stru)) != EOK) {
1504 hmac_free_netbuf_list(netbuf);
1505 netbuf = buf_tmp;
1506 continue;
1507 }
1508
1509 tx_ctl->event_type = FRW_EVENT_TYPE_WLAN_DTX;
1510 tx_ctl->event_sub_type = DMAC_TX_WLAN_DTX;
1511
1512 #if (_PRE_MULTI_CORE_MODE_OFFLOAD_DMAC == _PRE_MULTI_CORE_MODE)
1513 /* set the queue map id when wlan to wlan */
1514 oal_skb_set_queue_mapping(netbuf, WLAN_NORMAL_QUEUE);
1515 #endif
1516
1517 ret = hmac_tx_lan_to_wlan(mac_vap, netbuf);
1518 if (oal_unlikely(ret != HI_SUCCESS)) {
1519 hmac_free_netbuf_list(netbuf);
1520 }
1521 netbuf = buf_tmp;
1522 }
1523
1524 return HI_SUCCESS;
1525 }
1526
1527 /* ****************************************************************************
1528 功能描述 : hmac AP模式 处理HOST DRX事件,注册到事件管理模块中
1529 PAYLOAD是一个NETBUF
1530 输入参数 : pst_vap: vap指针
1531 pst_buf: netbuf指针
1532 返 回 值 : HI_SUCCESS或其它错误码
1533 **************************************************************************** */
hmac_tx_lan_to_wlan(mac_vap_stru * mac_vap,oal_netbuf_stru * netbuf)1534 hi_u32 hmac_tx_lan_to_wlan(mac_vap_stru *mac_vap, oal_netbuf_stru *netbuf)
1535 {
1536 hmac_tx_return_type_enum_uint8 hmac_tx_ret = HMAC_TX_PASS;
1537
1538 hmac_vap_stru *hmac_vap = hmac_vap_get_vap_stru(mac_vap->vap_id); /* VAP结构体 */
1539 if (oal_unlikely(hmac_vap == HI_NULL)) {
1540 oam_error_log0(mac_vap->vap_id, OAM_SF_TX, "{hmac_tx_lan_to_wlan::pst_hmac_vap null.}");
1541 return HI_ERR_CODE_PTR_NULL;
1542 }
1543
1544 hi_u32 ret = hmac_tx_lan_to_wlan_no_tcp_opt_vap_mode(mac_vap, hmac_vap);
1545 if (ret != HI_CONTINUE) {
1546 return ret;
1547 }
1548
1549 /* 初始化CB tx rx字段 , CB字段在前面已经被清零, 在这里不需要重复对某些字段赋零值 */
1550 hmac_tx_ctl_stru* tx_ctl = (hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf);
1551 tx_ctl->mpdu_num = 1;
1552 tx_ctl->netbuf_num = 1;
1553 tx_ctl->frame_type = WLAN_DATA_BASICTYPE;
1554 tx_ctl->is_probe_data = DMAC_USER_ALG_NON_PROBE;
1555 tx_ctl->ack_policy = WLAN_TX_NORMAL_ACK;
1556 #ifdef _PRE_WLAN_FEATURE_ALWAYS_TX
1557 /* 变量初始化赋值 */
1558 tx_ctl->ack_policy = hmac_vap->ack_policy;
1559 #endif
1560 tx_ctl->tx_vap_index = mac_vap->vap_id;
1561 tx_ctl->us_tx_user_idx = MAC_INVALID_USER_ID;
1562 tx_ctl->ac = WLAN_WME_AC_BE; /* 初始化入BE队列 */
1563
1564 /* 由于LAN TO WLAN和WLAN TO WLAN的netbuf都走这个函数,为了区分,需要先判断
1565 到底是哪里来的netbuf然后再对CB的事件类型字段赋值
1566 */
1567 if (tx_ctl->event_type != FRW_EVENT_TYPE_WLAN_DTX) {
1568 tx_ctl->event_type = FRW_EVENT_TYPE_HOST_DRX;
1569 tx_ctl->event_sub_type = DMAC_TX_HOST_DRX;
1570 }
1571
1572 /* 此处数据可能从内核而来,也有可能由dev报上来再通过空口转出去,注意一下 */
1573 hi_u8 data_type = mac_get_data_type_from_8023((hi_u8 *)oal_netbuf_data(netbuf), MAC_NETBUFF_PAYLOAD_ETH);
1574 /* 维测,输出一个关键帧打印 */
1575 if ((data_type <= MAC_DATA_DHCP_ACK) || (data_type == MAC_DATA_ARP_REQ) || (data_type == MAC_DATA_ARP_RSP) ||
1576 (data_type == MAC_DATA_EAPOL)) {
1577 tx_ctl->is_vipframe = HI_TRUE;
1578 oam_warning_log2(mac_vap->vap_id, OAM_SF_TX,
1579 "{hmac_tx_lan_to_wlan:type:%u,len:%u}[0~3:dhcp 4:arp_req 5:arp_rsp 6:eapol]", data_type,
1580 oal_netbuf_len(netbuf));
1581 }
1582 #ifdef _PRE_WLAN_FEATURE_MESH
1583 if (data_type == MAC_DATA_RPL) {
1584 oam_warning_log1(0, OAM_SF_TX, "{hmac_tx_lan_to_wlan:Mesh rpl msg,len=%u}", oal_netbuf_len(netbuf));
1585 }
1586 #endif
1587
1588 ret = hmac_tx_lan_to_wlan_no_tcp_opt_vap(mac_vap, netbuf, hmac_vap, &tx_ctl, &hmac_tx_ret);
1589 if (ret != HI_SUCCESS) {
1590 return ret;
1591 }
1592
1593 return hmac_tx_lan_to_wlan_no_tcp_opt_to_dmac(mac_vap, netbuf, tx_ctl, hmac_tx_ret);
1594 }
1595
1596 #ifdef _PRE_WLAN_FEATURE_MESH
1597 /* ****************************************************************************
1598 函 数 名 : hmac_unicast_data_tx_event_info
1599 功能描述 : 处理dmac上报单播数据帧发送信息,上报WAL
1600 输入参数 : [1]pst_mac_vap
1601 [2]uc_len
1602 [3]puc_param
1603 返 回 值 : hi_u32
1604 **************************************************************************** */
hmac_unicast_data_tx_event_info(mac_vap_stru * mac_vap,hi_u8 len,const hi_u8 * puc_param)1605 hi_u32 hmac_unicast_data_tx_event_info(mac_vap_stru *mac_vap, hi_u8 len, const hi_u8 *puc_param)
1606 {
1607 hi_unref_param(len);
1608
1609 return hmac_send_event_to_host(mac_vap, puc_param, sizeof(dmac_tx_info_report_stru),
1610 HMAC_HOST_CTX_EVENT_SUB_TYPE_TX_DATA_INFO);
1611 }
1612 #endif
1613
1614 #ifdef __cplusplus
1615 #if __cplusplus
1616 }
1617 #endif
1618 #endif
1619