• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  * 文 件 名   : hmac_tx_amsdu.c
15  * 生成日期   : 2012年11月12日
16  * 功能描述   : amsdu聚合
17  */
18 
19 /*****************************************************************************
20   1 头文件包含
21 *****************************************************************************/
22 #include "hmac_tx_amsdu.h"
23 
24 #include "oam_struct.h"
25 #include "hmac_tx_data.h"
26 #include "hmac_feature_dft.h"
27 #include "hmac_tx_encap.h"
28 #include "hmac_ccpriv.h"
29 #ifdef __cplusplus
30 #if __cplusplus
31 extern "C" {
32 #endif
33 #endif
34 
35 #undef THIS_FILE_ID
36 #define THIS_FILE_ID DIAG_FILE_ID_WIFI_HOST_HMAC_TX_AMSDU_C
37 
38 #undef THIS_MOD_ID
39 #define THIS_MOD_ID DIAG_MOD_ID_WIFI_HOST
40 
41 /*****************************************************************************
42   2 全局变量定义
43 *****************************************************************************/
44 mac_llc_snap_stru g_st_mac_11c_snap_header = {
45     SNAP_LLC_LSAP,
46     SNAP_LLC_LSAP,
47     LLC_UI,
48     {
49         SNAP_RFC1042_ORGCODE_0,
50         SNAP_RFC1042_ORGCODE_1,
51         SNAP_RFC1042_ORGCODE_2,
52     },
53     0
54 };
55 
56 OAL_STATIC osal_u32  hmac_amsdu_tx_timeout_process(osal_void *p_arg);
57 OAL_STATIC OAL_INLINE oal_bool_enum_uint8 hmac_tx_amsdu_is_overflow(const hmac_amsdu_stru *amsdu,
58     osal_u32          frame_len);
59 OAL_STATIC osal_u32  hmac_amsdu_send(hmac_vap_stru *hmac_vap,
60     hmac_user_stru *hmac_user,
61     hmac_amsdu_stru *amsdu);
62 
63 /*****************************************************************************
64   3 函数实现
65 *****************************************************************************/
66 /*****************************************************************************
67  函 数 名  : hmac_amsdu_prepare_to_send
68  功能描述  : 发送一个amsdu帧
69 *****************************************************************************/
hmac_amsdu_prepare_to_send(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,hmac_amsdu_stru * amsdu)70 WIFI_HMAC_TCM_TEXT OAL_STATIC osal_void hmac_amsdu_prepare_to_send(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
71     hmac_amsdu_stru *amsdu)
72 {
73     osal_u32              ul_ret;
74 
75     /* 删除定时器 */
76     frw_destroy_timer_entry(&amsdu->amsdu_timer);
77     ul_ret = hmac_amsdu_send(hmac_vap, hmac_user, amsdu);
78     if (osal_unlikely(ul_ret != OAL_SUCC)) {
79         oam_warning_log2(0, OAM_SF_AMSDU,
80             "{hmac_amsdu_prepare_to_send::, amsdu send fails. erro[%d], short_pkt_num=%d.}",
81             ul_ret, amsdu->msdu_num);
82     }
83 }
84 
85 #if defined(_PRE_PRODUCT_ID_HOST)
86 /*****************************************************************************
87  函 数 名  : hmac_tx_amsdu_is_overflow
88 *****************************************************************************/
hmac_tx_amsdu_is_overflow(const hmac_amsdu_stru * amsdu,osal_u32 frame_len)89 WIFI_HMAC_TCM_TEXT OAL_STATIC OAL_INLINE oal_bool_enum_uint8 hmac_tx_amsdu_is_overflow(const hmac_amsdu_stru *amsdu,
90     osal_u32 frame_len)
91 
92 {
93     /* payload + padmax(3) 不能大于1568 */
94     if (((amsdu->amsdu_size + frame_len + SNAP_LLC_FRAME_LEN + 3) > WLAN_LARGE_NETBUF_SIZE) ||
95         ((amsdu->amsdu_size + frame_len + SNAP_LLC_FRAME_LEN) > WLAN_AMSDU_FRAME_MAX_LEN)) {
96         oam_info_log3(1, OAM_SF_TX,
97             "{hmac_tx_amsdu_is_overflow::amsdu_size=%d framelen=%d msdu_num=%d .}",
98             amsdu->amsdu_size, frame_len, amsdu->msdu_num);
99         return OAL_TRUE;
100     }
101 
102     return OAL_FALSE;
103 }
104 
105 /*****************************************************************************
106  函 数 名  : hmac_amsdu_send
107  功能描述  : 发送amsdu, 发送失败则释放buf
108  输入参数  : user: 用户结构体指针
109              amsdu: 要发送的amsdu
110  返 回 值  : 成功OAL_SUCC;失败OAL_ERR_CODE_PTR_NULL
111 *****************************************************************************/
hmac_amsdu_send(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,hmac_amsdu_stru * amsdu)112 WIFI_HMAC_TCM_TEXT OAL_STATIC osal_u32 hmac_amsdu_send(hmac_vap_stru *hmac_vap,
113     hmac_user_stru *hmac_user, hmac_amsdu_stru *amsdu)
114 {
115     osal_u32          ret;
116     mac_tx_ctl_stru    *cb;
117     oal_netbuf_stru *net_buf = oal_netbuf_delist(&(amsdu->msdu_head));
118     osal_u8 msdu_num;
119 
120     /* 给dmac传送的amsdu相关的信息以及802.11头挂接 */
121     if (osal_unlikely(net_buf == OAL_PTR_NULL)) {
122         oam_error_log1(0, OAM_SF_AMPDU, "vap_id[%d] {hmac_amsdu_send::net_buf null}", hmac_vap->vap_id);
123         return OAL_ERR_CODE_PTR_NULL;
124     }
125 
126     cb = (mac_tx_ctl_stru *)oal_netbuf_cb(net_buf);
127 
128     /* amsdu只聚合一个帧时,回退成非amsdu,统一encap接口 */
129     if (amsdu->msdu_num == 1) {
130         osal_s32 mret;
131 
132         mret = memmove_s(OAL_NETBUF_DATA(net_buf) + SNAP_LLC_FRAME_LEN, OAL_MAC_ADDR_LEN + OAL_MAC_ADDR_LEN,
133             OAL_NETBUF_DATA(net_buf), OAL_MAC_ADDR_LEN + OAL_MAC_ADDR_LEN);
134         if (mret != EOK) {
135             oal_netbuf_free(net_buf);
136             oam_error_log1(0, OAM_SF_AMPDU, "vap_id[%d] {hmac_amsdu_send::memmove_s fail}", hmac_vap->vap_id);
137             return OAL_ERR_CODE_PTR_NULL;
138         }
139 
140         oal_netbuf_pull(net_buf, SNAP_LLC_FRAME_LEN);
141 
142         mac_get_cb_is_amsdu(cb) = OAL_FALSE;
143         mac_get_cb_is_first_msdu(cb) = OAL_FALSE;
144     }
145 
146     /* 把最后一个子帧的PAD去除 */
147     oal_netbuf_trim(net_buf, amsdu->last_pad_len);
148 
149     mac_get_cb_mpdu_len(cb) = (osal_u16)OAL_NETBUF_LEN(net_buf);
150     mac_get_cb_mpdu_num(cb) = 1;
151     mac_get_cb_msdu_num(cb) = amsdu->msdu_num;
152 
153     /* 清零amsdu结构体信息 */
154     msdu_num = amsdu->msdu_num;
155     amsdu->amsdu_size = 0;
156     amsdu->msdu_num   = 0;
157 
158     /* 为整个amsdu封装802.11头 */
159     ret = hmac_tx_encap_etc(hmac_vap, hmac_user, net_buf);
160     if (osal_unlikely(ret != OAL_SUCC)) {
161         hmac_dft_print_drop_frame_info(THIS_FILE_ID, __LINE__, msdu_num, OSAL_NULL);
162         oal_netbuf_free(net_buf);
163         OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_abnormal_msdu_dropped, 1);
164         oam_error_log2(0, OAM_SF_AMPDU, "vap_id[%d] {hmac_amsdu_send::tx_encap failed[%d]}", hmac_vap->vap_id, ret);
165         return OAL_ERR_CODE_PTR_NULL;
166     }
167 
168     // 架构变化导致Host侧发包路径变长,原bh锁的范围过长影响性能,将发送报文至dmac.ko侧的处理移至锁外
169     osal_spin_unlock_bh(&amsdu->amsdu_lock);
170     ret = hmac_tx_send_encap_data(hmac_vap, net_buf);
171     if (osal_unlikely(ret != OAL_SUCC)) {
172         oal_netbuf_free(net_buf);
173         OAM_STAT_VAP_INCR(hmac_vap->vap_id, tx_abnormal_msdu_dropped, 1);
174         oam_warning_log2(0, OAM_SF_AMPDU, "vap_id[%d]hmac_amsdu_send::frw_send_data fail[%d]", hmac_vap->vap_id, ret);
175     }
176 
177     osal_spin_lock_bh(&amsdu->amsdu_lock);
178 
179     return  ret;
180 }
181 
182 /*****************************************************************************
183  函 数 名  : hmac_amsdu_tx_encap_mpdu
184  功能描述  : 多个msdu帧组建一个mpdu,进入此函数的msdu肯定能放入netbuf,否则overflow会溢出
185 *****************************************************************************/
hmac_amsdu_tx_encap_mpdu(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,hmac_amsdu_stru * amsdu,oal_netbuf_stru * buf)186 WIFI_HMAC_TCM_TEXT OAL_STATIC OAL_INLINE osal_u32 hmac_amsdu_tx_encap_mpdu(hmac_vap_stru *hmac_vap,
187     hmac_user_stru *hmac_user, hmac_amsdu_stru *amsdu, oal_netbuf_stru *buf)
188 {
189     osal_u32              msdu_len;
190     osal_u32              frame_len;
191     osal_u32              tailroom;
192     osal_u16              msdu_offset;    /* 拷贝新msdu帧的偏移地址 */
193     oal_netbuf_stru        *dest_buf;
194     mac_ether_header_stru  *ether_head;    /* 以太网过来的skb的以太网头 */
195     mac_llc_snap_stru      *snap_head;     /* 为填写snap头的临时指针 */
196 
197     /* 协议栈来帧原始长 */
198     frame_len = oal_netbuf_get_len(buf);
199     /* 4字节对齐后的msdu帧的长度 */
200     msdu_len = OAL_ROUND_UP(frame_len, 4);
201     /* msdu帧长 */
202     msdu_len += SNAP_LLC_FRAME_LEN;
203 
204     dest_buf = oal_netbuf_peek(&amsdu->msdu_head);
205     if (dest_buf == OAL_PTR_NULL) {
206         /* 链表中应该有netbuf */
207         oam_error_log0(0, OAM_SF_AMSDU, "{hmac_amsdu_tx_encap_mpdu::oal_netbuf_peek return NULL}");
208         return HMAC_TX_PASS;
209     }
210 
211     /* 当期netbuf剩余空间少于msdu长 */
212     tailroom = oal_netbuf_tailroom(dest_buf);
213     if (tailroom < msdu_len) {
214         oam_error_log3(0, OAM_SF_AMSDU, "{hmac_amsdu_tx_encap_mpdu::Notify1,tailroom[%d],msdu[%d],frame[%d]}",
215                        tailroom, msdu_len, frame_len);
216         /* 如果加上pad超出长度,尝试尾帧去掉pad */
217         msdu_len = frame_len + SNAP_LLC_FRAME_LEN;
218         if (tailroom < msdu_len) {
219             hmac_amsdu_prepare_to_send(hmac_vap, hmac_user, amsdu);
220             return HMAC_TX_PASS;
221         }
222     }
223 
224     /* NEW MSDU OFFSET */
225     msdu_offset = (osal_u16)oal_netbuf_get_len(dest_buf);
226 
227     /* ETH HEAD + LLC + PAYLOAD */
228     oal_netbuf_put(dest_buf, msdu_len);
229 
230     /* COPY ETH HEADER */
231     ether_head = (mac_ether_header_stru *)(oal_netbuf_data(dest_buf) + msdu_offset);
232     (osal_void)memcpy_s((osal_u8 *)ether_head, ETHER_HDR_LEN, oal_netbuf_data(buf), ETHER_HDR_LEN);
233 
234     /* FILL LLC HEADER */
235     snap_head = (mac_llc_snap_stru *)((osal_u8 *)ether_head + ETHER_HDR_LEN);
236     (osal_void)memcpy_s((osal_u8 *)snap_head, SNAP_LLC_FRAME_LEN,
237         (osal_u8 *)&g_st_mac_11c_snap_header, SNAP_LLC_FRAME_LEN);
238 
239     /* change type & length */
240     snap_head->ether_type = ether_head->ether_type;
241     ether_head->ether_type = oal_byteorder_host_to_net_uint16((osal_u16)(frame_len - ETHER_HDR_LEN +
242                                     SNAP_LLC_FRAME_LEN));
243 
244     /* COPY MSDU PAYLOAD */
245     (osal_void)memcpy_s((osal_u8 *)snap_head + SNAP_LLC_FRAME_LEN, frame_len - ETHER_HDR_LEN,
246         oal_netbuf_data(buf) + ETHER_HDR_LEN, frame_len - ETHER_HDR_LEN); /* 函数调用前已校验buf长度 */
247 
248     /* 释放旧msdu */
249     oal_netbuf_free(buf);
250 
251     /* 更新amsdu信息 */
252     amsdu->msdu_num++;
253     amsdu->amsdu_size += (osal_u16)msdu_len;
254     amsdu->last_pad_len = (osal_u8)(msdu_len - SNAP_LLC_FRAME_LEN - frame_len);
255 
256     tailroom = oal_netbuf_tailroom(dest_buf);
257     /* 当前netbuf剩余空间较少 || 已经达到聚合最大帧数 */
258     if ((tailroom < HMAC_AMSDU_TX_MIN_LENGTH) || (amsdu->msdu_num >= amsdu->amsdu_maxnum)) {
259         hmac_amsdu_prepare_to_send(hmac_vap, hmac_user, amsdu);
260     }
261 
262     /* 由于最新的msdu skb已经被释放,不管当前amsdu是否缓存或发送成功/失败,都需要返回TX BUFF */
263     return HMAC_TX_BUFF;
264 }
265 
266 /*****************************************************************************
267  函 数 名  : hmac_amsdu_alloc_netbuf
268  功能描述  : 申请netbuf用于聚合组装amsdu
269 *****************************************************************************/
hmac_amsdu_alloc_netbuf(hmac_amsdu_stru * amsdu,oal_netbuf_stru * buf)270 WIFI_HMAC_TCM_TEXT OAL_STATIC OAL_INLINE osal_u32 hmac_amsdu_alloc_netbuf(hmac_amsdu_stru *amsdu, oal_netbuf_stru *buf)
271 {
272     oal_netbuf_stru *dest_buf;
273     mac_tx_ctl_stru *cb;
274 
275     dest_buf = OAL_MEM_NETBUF_ALLOC(OAL_NORMAL_NETBUF, WLAN_LARGE_NETBUF_SIZE, OAL_NETBUF_PRIORITY_MID);
276     if (dest_buf == OAL_PTR_NULL) {
277         return OAL_FAIL;
278     }
279 
280     /* 子帧链入amsdu尾部 */
281     oal_netbuf_add_to_list_tail(dest_buf, &amsdu->msdu_head);
282 
283     (osal_void)memcpy_s(oal_netbuf_cb(dest_buf), OAL_SIZEOF(mac_tx_ctl_stru),
284         oal_netbuf_cb(buf), OAL_SIZEOF(mac_tx_ctl_stru));
285 
286     oal_netbuf_copy_queue_mapping(dest_buf, buf);
287 
288     cb = (mac_tx_ctl_stru *)oal_netbuf_cb(dest_buf);
289     mac_get_cb_is_first_msdu(cb)    = OAL_TRUE;
290     mac_get_cb_is_amsdu(cb)  = OAL_TRUE;
291     mac_get_cb_netbuf_num(cb)       = 1;
292 
293     return OAL_SUCC;
294 }
295 
296 /*****************************************************************************
297  函 数 名  : hmac_amsdu_tx_process_etc
298  功能描述  : amsdu聚合发送处理函数
299 *****************************************************************************/
hmac_amsdu_tx_process_etc(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,oal_netbuf_stru * buf)300 WIFI_HMAC_TCM_TEXT OSAL_STATIC osal_u32  hmac_amsdu_tx_process_etc(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
301     oal_netbuf_stru *buf)
302 {
303     osal_u8           tid_no;
304     osal_u32          frame_len;
305     osal_u32          ul_ret;
306     hmac_amsdu_stru    *amsdu;
307     mac_tx_ctl_stru    *tx_ctl;
308 
309     tx_ctl = (mac_tx_ctl_stru *)(oal_netbuf_cb(buf));
310     frame_len = oal_netbuf_get_len(buf);
311     tid_no    = mac_get_cb_wme_tid_type(tx_ctl);
312     amsdu    = &(hmac_user->hmac_amsdu[tid_no]);
313 
314     /* amsdu组帧溢出,将链表缓存帧发送并清空,新帧作为amsdu首帧入链表 */
315     if (hmac_tx_amsdu_is_overflow(amsdu, frame_len)) {
316         hmac_amsdu_prepare_to_send(hmac_vap, hmac_user, amsdu);
317     }
318 
319     if (amsdu->msdu_num == 0) {
320         oal_netbuf_list_head_init(&amsdu->msdu_head);
321         /* 申请netbuf用于聚合amsdu */
322         if (hmac_amsdu_alloc_netbuf(amsdu, buf) != OAL_SUCC) {
323             oam_warning_log1(0, OAM_SF_AMSDU, "vap_id[%d] {hmac_amsdu_tx_process_etc::failed to alloc netbuf.}",
324                              hmac_vap->vap_id);
325             return HMAC_TX_PASS;
326         }
327 
328         /* 启动定时器 */
329         frw_create_timer_entry(&amsdu->amsdu_timer,
330                                hmac_amsdu_tx_timeout_process,
331                                HMAC_AMSDU_LIFE_TIME,
332                                amsdu,
333                                OAL_FALSE);
334     }
335 
336     /* 处理每一个msdu */
337     ul_ret = hmac_amsdu_tx_encap_mpdu(hmac_vap, hmac_user, amsdu, buf);
338     return ul_ret;
339 }
340 #endif
341 
342 #ifdef _PRE_WLAN_FEATURE_MULTI_NETBUF_AMSDU
343 /*****************************************************************************
344  函 数 名  : hmac_tx_encap_large_skb_amsdu
345  功能描述  : 大包ampdu+amsdu入口函数
346  输入参数  : user: 用户结构体指针
347              buf: skb结构体指针
348 *****************************************************************************/
hmac_tx_encap_large_skb_amsdu(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,oal_netbuf_stru * buf,mac_tx_ctl_stru * tx_ctl)349 osal_void hmac_tx_encap_large_skb_amsdu(hmac_vap_stru *hmac_vap, hmac_user_stru *hmac_user,
350     oal_netbuf_stru *buf,
351     mac_tx_ctl_stru *tx_ctl)
352 {
353     mac_ether_header_stru                    *ether_hdr_temp;
354     mac_ether_header_stru                    *ether_hdr;
355     osal_u8                                 tid_no;
356     osal_u16                                mpdu_len;
357     osal_u16                                us_80211_frame_len;
358 
359     /* AMPDU+AMSDU功能未开启,由定制化门限决定,高于300Mbps时开启amsdu大包聚合 */
360     if (g_st_tx_large_amsdu.cur_amsdu_enable == OAL_FALSE) {
361         return;
362     }
363 
364     /* 针对关闭WMM,非QOS帧处理 */
365     if (hmac_user->cap_info.qos == OAL_FALSE) {
366         return;
367     }
368 
369     /* VO、组播队列不开启AMPDU+AMSDU */
370     tid_no = mac_get_cb_wme_tid_type(tx_ctl);
371     if (tid_no >= WLAN_TIDNO_VOICE) {
372         return;
373     }
374 
375     /* 判断该tid是否支持AMPDU+AMSDU */
376     if (hmac_user_is_amsdu_support(hmac_user, tid_no) == OAL_FALSE) {
377         return;
378     }
379 
380     /* 非长帧不进行AMPDU+AMSDU */
381     mpdu_len = (osal_u16)oal_netbuf_get_len(buf);
382     if ((mpdu_len < MAC_AMSDU_SKB_LEN_DOWN_LIMIT) || (mpdu_len > MAC_AMSDU_SKB_LEN_UP_LIMIT)) {
383         return;
384     }
385 
386     /* 超出分片帧门限不进行AMPDU+AMSDU,计算时考虑需要新增的EHER HEAD LEN和字节对齐,MAC HEAD考虑最长帧头 */
387     us_80211_frame_len = mpdu_len + SNAP_LLC_FRAME_LEN + 2 + MAC_80211_QOS_HTC_4ADDR_FRAME_LEN; /* 2长度 */
388     if (us_80211_frame_len > mac_mib_get_FragmentationThreshold(hmac_vap)) {
389         return;
390     }
391 
392     /* 已经是小包AMSDU聚合 */
393     if (mac_get_cb_is_amsdu(tx_ctl) == OAL_TRUE) {
394         return;
395     }
396 
397     /* ETHER HEAD头部空闲空间,4字节对齐;一般此条件均成立,放置于最后 */
398     if (oal_netbuf_headroom(buf) < (SNAP_LLC_FRAME_LEN + 2)) { /* 2长度判断 */
399         return;
400     }
401 
402     /* 80211 FRAME INCLUDE EHTER HEAD */
403     mac_get_cb_has_ether_head(tx_ctl) = OAL_TRUE;
404 
405     ether_hdr = (mac_ether_header_stru *)oal_netbuf_data(buf);
406 
407     /* 预留LLC HEAD长度 */
408     oal_netbuf_push(buf, SNAP_LLC_FRAME_LEN);
409     ether_hdr_temp = (mac_ether_header_stru *)oal_netbuf_data(buf);
410     /* 拷贝mac head */
411     (osal_void)memmove_s((osal_u8 *)ether_hdr_temp, ETHER_HDR_LEN, (osal_u8 *)ether_hdr, ETHER_HDR_LEN);
412     /* 设置AMSDU帧长度 */
413     ether_hdr_temp->ether_type = oal_byteorder_host_to_net_uint16((osal_u16)(
414                                             mpdu_len - ETHER_HDR_LEN +
415                                             SNAP_LLC_FRAME_LEN));
416 }
417 #endif
418 
419 /*****************************************************************************
420  函 数 名 : hmac_amsdu_tid_info_clear
421  功能描述 : 删除hmac tid中相关的amsdu信息
422  输入参数 : hmac_user : user信息
423             tid_index : TID索引0~7, 最大值为WLAN_TID_MAX_NUM = 8
424  注意事项 : 内部函数, 不校验入参有效性, 由调用者保证
425 *****************************************************************************/
hmac_amsdu_tid_info_clear(hmac_user_stru * hmac_user)426 OAL_STATIC osal_void hmac_amsdu_tid_info_clear(hmac_user_stru *hmac_user)
427 {
428     hmac_amsdu_stru *amsdu = OAL_PTR_NULL;
429     oal_netbuf_stru *amsdu_net_buf = OAL_PTR_NULL;
430     osal_u8 loop;
431 
432     for (loop = 0; loop < WLAN_TID_MAX_NUM; loop++) {
433         amsdu = &(hmac_user->hmac_amsdu[loop]);
434 
435         /* tid锁, 禁软中断 */
436         osal_spin_lock_bh(&amsdu->amsdu_lock);
437 
438         if (amsdu->amsdu_timer.is_registerd == OAL_TRUE) {
439             frw_destroy_timer_entry(&(amsdu->amsdu_timer));
440         }
441 
442         /* 清空聚合队列 */
443         if (amsdu->msdu_num != 0) {
444             while (oal_netbuf_list_empty(&amsdu->msdu_head) != OAL_TRUE) {
445                 amsdu_net_buf = oal_netbuf_delist(&(amsdu->msdu_head));
446                 oal_netbuf_free(amsdu_net_buf);
447                 amsdu_net_buf = OAL_PTR_NULL;
448             }
449             amsdu->msdu_num = 0;
450             amsdu->amsdu_size = 0;
451         }
452 
453         /* tid解锁, 使能软中断 */
454         osal_spin_unlock_bh(&amsdu->amsdu_lock);
455     }
456     return;
457 }
458 
hmac_amsdu_notify_check_param(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,const mac_ether_header_stru * ether_header,osal_u8 tid_no)459 WIFI_HMAC_TCM_TEXT WIFI_TCM_TEXT OSAL_STATIC osal_u32 hmac_amsdu_notify_check_param(hmac_vap_stru *hmac_vap,
460     hmac_user_stru *hmac_user, const mac_ether_header_stru *ether_header, osal_u8 tid_no)
461 {
462     oal_ip_header_stru *pst_ip = OAL_PTR_NULL;
463 
464     /* 检查amsdu开关是否打开,amsdu_tx_on 0/1; VAP 是否支持聚合 */
465     if ((mac_mib_get_CfgAmsduTxAtive(hmac_vap) != OAL_TRUE) ||
466         (mac_mib_get_AmsduAggregateAtive(hmac_vap) != OAL_TRUE)) {
467         return HMAC_TX_PASS;
468     }
469 
470     /* 判断该tid是否在ampdu情况下支持amsdu的发送,ampdu_amsdu 0/1 */
471     if (hmac_user_is_amsdu_support(hmac_user, tid_no) == OAL_FALSE) {
472         return HMAC_TX_PASS;
473     }
474 
475     if (ether_header->ether_type == oal_host2net_short(ETHER_TYPE_IP)) {
476         pst_ip = (oal_ip_header_stru *)(ether_header + 1);
477         /* 允许TCP ACK聚合 */
478         /* 为了解决业务量小时ping包延迟的问题,ICMP不聚合 */
479         if (oal_netbuf_is_icmp_etc(pst_ip) == OAL_TRUE) {
480             return HMAC_TX_PASS;
481         }
482     }
483     /* 检查用户是否是HT/VHT */
484     if (hmac_user_xht_support(hmac_user) == OAL_FALSE) {
485         oam_info_log1(0, OAM_SF_AMSDU, "vap_id[%d] {hmac_amsdu_notify_etc::user is not qos in amsdu notify}",
486             hmac_vap->vap_id);
487         return HMAC_TX_PASS;
488     }
489 
490     if (osal_unlikely(tid_no >= WLAN_TID_MAX_NUM)) {
491         oam_error_log1(0, OAM_SF_AMSDU, "vap_id[%d]{hmac_amsdu_notify_etc::invalid tid from] asmdu notify}",
492             hmac_vap->vap_id);
493         return HMAC_TX_PASS;
494     }
495 
496     if (tid_no == WLAN_TIDNO_VOICE) {
497         oam_info_log3(0, OAM_SF_AMSDU,
498             "vap_id[%d] {hmac_amsdu_notify_etc::VO TID NOT SUPPORT AMSDU tid_no=%d amsdu_supported=%d",
499             hmac_vap->vap_id, tid_no, hmac_user->amsdu_supported);
500         return HMAC_TX_PASS;
501     }
502     return OAL_CONTINUE;
503 }
504 /*****************************************************************************
505  函 数 名  : hmac_amsdu_notify_etc
506  功能描述  : amsdu入口函数
507  输入参数  : user: 用户结构体指针
508              buf: skb结构体指针
509 *****************************************************************************/
hmac_amsdu_notify_etc(hmac_vap_stru * hmac_vap,hmac_user_stru * hmac_user,oal_netbuf_stru * buf)510 WIFI_HMAC_TCM_TEXT WIFI_TCM_TEXT OSAL_STATIC osal_u32 hmac_amsdu_notify_etc(hmac_vap_stru *hmac_vap,
511     hmac_user_stru *hmac_user, oal_netbuf_stru *buf)
512 {
513     osal_u8           tid_no;
514     osal_u32          ul_ret;         /* 所调用函数的返回值 */
515     mac_tx_ctl_stru    *tx_ctl;
516     hmac_amsdu_stru    *amsdu;
517 
518     mac_ether_header_stru  *ether_header = (mac_ether_header_stru *)oal_netbuf_data(buf);
519 
520     /* 获取cb中的tid信息 */
521     tx_ctl = (mac_tx_ctl_stru *)(oal_netbuf_cb(buf));
522     tid_no    = mac_get_cb_wme_tid_type(tx_ctl);
523 
524     /* 针对关闭WMM,非QOS帧处理 */
525     if (hmac_user->cap_info.qos == OAL_FALSE) {
526         oam_info_log0(0, OAM_SF_TX, "{hmac_amsdu_notify_etc::UnQos Frame pass!!}");
527         return HMAC_TX_PASS;
528     }
529     /* 组播转单播数据不聚合 */
530     if (tx_ctl->is_m2u_data == OSAL_TRUE) {
531         return HMAC_TX_PASS;
532     }
533 #if !defined(_PRE_WLAN_FEATURE_WS73) && !defined(_PRE_WLAN_FEATURE_WS53)
534     if (tx_ctl->is_tcp_ack == OSAL_TRUE) {
535         return HMAC_TX_PASS;
536     }
537 #endif
538     /* vip tcp ack不聚合 */
539     if (mac_get_cb_vip_tcp_ack(tx_ctl) == OSAL_TRUE) {
540         return HMAC_TX_PASS;
541     }
542     ul_ret = hmac_amsdu_notify_check_param(hmac_vap, hmac_user, ether_header, tid_no);
543     if (ul_ret != OAL_CONTINUE) {
544         return ul_ret;
545     }
546 
547     amsdu = &(hmac_user->hmac_amsdu[tid_no]);
548     osal_spin_lock_bh(&amsdu->amsdu_lock);
549 
550     /* 新来帧是大帧,需将缓存帧发完 */
551     if (oal_netbuf_get_len(buf) > WLAN_MSDU_MAX_LEN) {
552         /* 防止乱序,应该先发送旧帧 */
553         if (amsdu->msdu_num != 0) {
554             hmac_amsdu_prepare_to_send(hmac_vap, hmac_user, amsdu);
555         }
556         osal_spin_unlock_bh(&amsdu->amsdu_lock);
557         return HMAC_TX_PASS;
558     }
559 
560     ul_ret = hmac_amsdu_tx_process_etc(hmac_vap, hmac_user, buf);
561     osal_spin_unlock_bh(&amsdu->amsdu_lock);
562     return ul_ret;
563 }
564 
565 /*****************************************************************************
566  函 数 名  : hmac_amsdu_tx_timeout_process
567  功能描述  : 时钟中断事件的处理函数
568  输入参数  : hmac_vap:
569 *****************************************************************************/
hmac_amsdu_tx_timeout_process(osal_void * p_arg)570 WIFI_HMAC_TCM_TEXT OAL_STATIC osal_u32 hmac_amsdu_tx_timeout_process(osal_void *p_arg)
571 {
572     hmac_amsdu_stru         *temp_amsdu;
573     mac_tx_ctl_stru         *cb;
574     hmac_user_stru          *hmac_user;
575     osal_u32               ul_ret;
576     oal_netbuf_stru         *pst_netbuf;
577     hmac_vap_stru           *hmac_vap;
578 
579     if (osal_unlikely(p_arg == OAL_PTR_NULL)) {
580         oam_error_log0(0, OAM_SF_AMPDU, "{hmac_amsdu_tx_timeout_process::input null}");
581         return OAL_ERR_CODE_PTR_NULL;
582     }
583 
584     temp_amsdu = (hmac_amsdu_stru *)p_arg;
585 
586     osal_spin_lock_bh(&temp_amsdu->amsdu_lock);
587 
588     /* 根据要发送的amsdu下第一个msdu子帧的cb字段的信息寻找对应用户结构体 */
589     pst_netbuf = oal_netbuf_peek(&temp_amsdu->msdu_head);
590     if (pst_netbuf == OAL_PTR_NULL) {
591         oam_info_log1(0, OAM_SF_AMSDU, "hmac_amsdu_tx_timeout_process::pst_netbuf NULL. msdu_num[%d]",
592                       temp_amsdu->msdu_num);
593         osal_spin_unlock_bh(&temp_amsdu->amsdu_lock);
594         return OAL_ERR_CODE_PTR_NULL;
595     }
596 
597     cb          = (mac_tx_ctl_stru *)oal_netbuf_cb(pst_netbuf);
598     hmac_vap    = (hmac_vap_stru *)mac_res_get_hmac_vap(mac_get_cb_tx_vap_index(cb));
599     if (osal_unlikely(hmac_vap == OAL_PTR_NULL)) {
600         osal_spin_unlock_bh(&temp_amsdu->amsdu_lock);
601         oam_error_log0(0, OAM_SF_AMPDU, "{hmac_amsdu_tx_timeout_process::hmac_vap null}");
602         return OAL_ERR_CODE_PTR_NULL;
603     }
604 
605     hmac_user = (hmac_user_stru *)mac_res_get_hmac_user_etc(mac_get_cb_tx_user_idx(cb));
606     if (osal_unlikely(hmac_user == OAL_PTR_NULL)) {
607         osal_spin_unlock_bh(&temp_amsdu->amsdu_lock);
608         oam_error_log1(0, OAM_SF_AMPDU, "{hmac_amsdu_tx_timeout_process::user[%d] null}",
609                        mac_get_cb_tx_user_idx(cb));
610         return OAL_ERR_CODE_PTR_NULL;
611     }
612 
613     ul_ret = hmac_amsdu_send(hmac_vap, hmac_user, temp_amsdu);
614     if (ul_ret != OAL_SUCC) {
615         oam_warning_log2(0, OAM_SF_AMSDU, "vap_id[%d] hmac_amsdu_tx_timeout_process::hmac_amsdu_send fail[%d]",
616                          hmac_vap->vap_id, ul_ret);
617     }
618 
619     osal_spin_unlock_bh(&temp_amsdu->amsdu_lock);
620     return OAL_SUCC;
621 }
622 
623 /*****************************************************************************
624  函 数 名  : hmac_amsdu_init_user_etc
625  功能描述  : 初始化用户tid队列的AMSDU特性值
626  输入参数  : hmac_user_stru *hmac_user_sta
627  返 回 值  : OAL_STATIC OAL_INLINE osal_void
628 *****************************************************************************/
hmac_amsdu_init_user_etc(hmac_user_stru * hmac_user)629 OSAL_STATIC osal_void hmac_amsdu_init_user_etc(hmac_user_stru *hmac_user)
630 {
631     osal_u32           amsdu_idx;
632     hmac_amsdu_stru     *amsdu;
633 
634     if (hmac_user == OAL_PTR_NULL) {
635         oam_error_log0(0, OAM_SF_AMPDU, "{hmac_amsdu_init_user_etc::hmac_user_sta null}");
636         return;
637     }
638 
639     hmac_user->amsdu_maxsize = WLAN_AMSDU_FRAME_MAX_LEN_LONG;
640 
641     hmac_user->amsdu_supported = AMSDU_ENABLE_ALL_TID;
642 
643     /* 设置amsdu域 */
644     for (amsdu_idx = 0; amsdu_idx < WLAN_TID_MAX_NUM; amsdu_idx++) {
645         amsdu = &(hmac_user->hmac_amsdu[amsdu_idx]);
646 
647         osal_spin_lock_init(&amsdu->amsdu_lock);
648         oal_netbuf_list_head_init(&(amsdu->msdu_head));
649         amsdu->amsdu_size    = 0;
650         amsdu->msdu_num      = 0;
651         hmac_amsdu_set_maxnum(amsdu, HMAC_AMSDU_MAX_NUM);
652     }
653 }
654 
655 #ifdef _PRE_WLAN_SUPPORT_CCPRIV_CMD
hmac_ccpriv_amsdu_tx_on(hmac_vap_stru * hmac_vap,const osal_s8 * param)656 OSAL_STATIC osal_s32 hmac_ccpriv_amsdu_tx_on(hmac_vap_stru *hmac_vap, const osal_s8 *param)
657 {
658     osal_s8                        ac_name[CCPRIV_CMD_NAME_MAX_LEN] = {0};
659     osal_s32                       ret;
660     osal_u8                        aggr_tx_on;
661 
662     ret = hmac_ccpriv_get_one_arg(&param, ac_name, OAL_SIZEOF(ac_name));
663     if (ret != OAL_SUCC) {
664         oam_warning_log1(0, OAM_SF_ANY, "{hmac_ccpriv_amsdu_tx_on::get_cmd_one_arg return err_code [%d]!}", ret);
665         return ret;
666     }
667 
668     aggr_tx_on = (osal_u8)oal_atoi((const osal_s8 *)ac_name);
669 
670     mac_mib_set_CfgAmsduTxAtive(hmac_vap, aggr_tx_on);
671     oam_warning_log2(0, OAM_SF_CFG, "vap_id[%d] {hmac_config_set_amsdu_tx_on_etc::ENABLE[%d].}",
672                      hmac_vap->vap_id, aggr_tx_on);
673 
674     return OAL_SUCC;
675 }
676 #endif
677 
hmac_tx_amsdu_init(osal_void)678 osal_u32 hmac_tx_amsdu_init(osal_void)
679 {
680     /* 注册对外接口 */
681 #ifdef _PRE_WLAN_FEATURE_MULTI_NETBUF_AMSDU
682     hmac_feature_hook_register(HMAC_FHOOK_AMSDU_TX_ENCAP_LARGE_SKB, hmac_tx_encap_large_skb_amsdu);
683 #endif
684     hmac_feature_hook_register(HMAC_FHOOK_AMSDU_TX_NOTIFY_ETC, hmac_amsdu_notify_etc);
685     hmac_feature_hook_register(HMAC_FHOOK_AMSDU_TX_INIT_USER_ETC, hmac_amsdu_init_user_etc);
686     hmac_feature_hook_register(HMAC_FHOOK_AMSDU_TID_INFO_CLEAR, hmac_amsdu_tid_info_clear);
687 
688 #ifdef _PRE_WLAN_SUPPORT_CCPRIV_CMD
689     /* ccpriv命令注册, 开启或关闭ampdu发送功能 ccpriv "vap0 amsdu_tx_on 0\1" */
690     hmac_ccpriv_register((const osal_s8 *)"amsdu_tx_on", hmac_ccpriv_amsdu_tx_on);
691 #endif
692 
693     return OAL_SUCC;
694 }
695 
hmac_tx_amsdu_deinit(osal_void)696 osal_void hmac_tx_amsdu_deinit(osal_void)
697 {
698     /* 去注册对外接口 */
699 #ifdef _PRE_WLAN_FEATURE_MULTI_NETBUF_AMSDU
700     hmac_feature_hook_unregister(HMAC_FHOOK_AMSDU_TX_ENCAP_LARGE_SKB);
701 #endif
702     hmac_feature_hook_unregister(HMAC_FHOOK_AMSDU_TX_NOTIFY_ETC);
703     hmac_feature_hook_unregister(HMAC_FHOOK_AMSDU_TX_INIT_USER_ETC);
704     hmac_feature_hook_unregister(HMAC_FHOOK_AMSDU_TID_INFO_CLEAR);
705 
706 #ifdef _PRE_WLAN_SUPPORT_CCPRIV_CMD
707     /* ccpriv命令去注册 */
708     hmac_ccpriv_unregister((const osal_s8 *)"amsdu_tx_on");
709 #endif
710 
711     return;
712 }
713 
714 #ifdef __cplusplus
715 #if __cplusplus
716 }
717 #endif
718 #endif
719 
720