• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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