• 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 "frw_timer.h"
23 #include "hmac_frag.h"
24 #include "hmac_11i.h"
25 
26 #ifdef __cplusplus
27 #if __cplusplus
28 extern "C" {
29 #endif
30 #endif
31 
32 /* ****************************************************************************
33   2 函数实现
34 **************************************************************************** */
35 /* ****************************************************************************
36  功能描述  : 报文分片处理
37 **************************************************************************** */
38 /* 规则5.1 避免函数过长,函数不超过50行(非空非注释),申请例外: 报文分片处理,功能内聚,建议屏蔽 */
hmac_frag_process(oal_netbuf_stru * netbuf_original,hmac_tx_ctl_stru * tx_ctl,hi_u32 cip_hdrsize,hi_u32 max_tx_unit)39 static hi_u32 hmac_frag_process(oal_netbuf_stru *netbuf_original, hmac_tx_ctl_stru *tx_ctl, hi_u32 cip_hdrsize,
40     hi_u32 max_tx_unit)
41 {
42     mac_ieee80211_frame_stru *frag_header = HI_NULL;
43     oal_netbuf_stru          *netbuf = HI_NULL;
44     hi_u32                    mac_hdr_size;
45     hi_u32                    offset;
46     hi_s32                    l_remainder;
47 
48     /* 加密字节数包含在分片门限中,预留加密字节长度,由硬件填写加密头 */
49     mac_hdr_size = tx_ctl->frame_header_length;
50     offset = max_tx_unit - cip_hdrsize;
51     l_remainder = (hi_s32)(oal_netbuf_len(netbuf_original) - offset);
52 
53     mac_ieee80211_frame_stru *mac_header = tx_ctl->frame_header;
54     mac_header->frame_control.more_frag = HI_TRUE;
55 
56     hi_u32 total_hdrsize         = mac_hdr_size + cip_hdrsize;
57     hi_u32 frag_num              = 1;
58     oal_netbuf_stru *netbuf_prev = netbuf_original;
59 
60     do {
61         hi_u32 frag_size = total_hdrsize + (hi_u32)l_remainder;
62 
63         /* 判断是否还有更多的分片 */
64         frag_size = (frag_size > max_tx_unit) ? max_tx_unit : frag_size;
65 
66         netbuf = oal_netbuf_alloc(frag_size + MAC_80211_QOS_HTC_4ADDR_FRAME_LEN, MAC_80211_QOS_HTC_4ADDR_FRAME_LEN,
67             4); /* align 4 */
68         if (netbuf == HI_NULL) {
69             /* 在外部释放之前申请的报文 */
70             oam_error_log0(0, OAM_SF_ANY, "{hmac_frag_process::pst_netbuf null.}");
71             return HI_ERR_CODE_PTR_NULL;
72         }
73 
74         hmac_tx_ctl_stru *tx_ctl_copy = (hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf);
75         /* 拷贝cb字段 */
76         if (memcpy_s(tx_ctl_copy, sizeof(hmac_tx_ctl_stru), tx_ctl, sizeof(hmac_tx_ctl_stru)) != EOK) {
77             oal_netbuf_free(netbuf);
78             oam_error_log0(0, OAM_SF_CFG, "hmac_frag_process:: pst_tx_ctl memcpy_s fail.");
79             return HI_FAIL;
80         }
81 
82         /* netbuf的headroom大于802.11 mac头长度 */
83         frag_header = (mac_ieee80211_frame_stru *)(oal_netbuf_payload(netbuf) - mac_hdr_size);
84         tx_ctl_copy->mac_head_type = 1; /* 指示mac头部在skb中 */
85 
86         /* 拷贝帧头内容 */
87         if (memcpy_s(frag_header, mac_hdr_size, mac_header, tx_ctl->frame_header_length) != EOK) {
88             oal_netbuf_free(netbuf);
89             oam_error_log0(0, OAM_SF_CFG, "hmac_frag_process:: pst_mac_header memcpy_s fail.");
90             return HI_FAIL;
91         }
92 
93         /* 赋值分片号 */
94         frag_header->frag_num = frag_num;
95         frag_num++;
96 
97         /* 计算分片报文帧体长度 */
98         hi_u32 copy_offset = offset;
99 
100         hi_u32 ret = oal_netbuf_copydata(netbuf_original, copy_offset, oal_netbuf_payload(netbuf),
101             (frag_size + MAC_80211_QOS_HTC_4ADDR_FRAME_LEN), (frag_size - total_hdrsize));
102         if (ret != HI_SUCCESS) {
103             oal_netbuf_free(netbuf);
104             oam_error_log0(0, OAM_SF_CFG, "hmac_frag_process:: oal_netbuf_copydata return fail.");
105             return ret;
106         }
107 
108         oal_netbuf_set_len(netbuf, (frag_size - total_hdrsize));
109         ((hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf))->frame_header = frag_header;
110         ((hmac_tx_ctl_stru *)oal_netbuf_cb(netbuf))->us_mpdu_len  = (hi_u16)(frag_size - total_hdrsize);
111         set_oal_netbuf_next(netbuf_prev, netbuf);
112         netbuf_prev = netbuf;
113 
114         oal_netbuf_push(netbuf, mac_hdr_size);
115 
116         /* 计算下一个分片报文的长度和偏移 */
117         l_remainder -= (hi_s32)(frag_size - total_hdrsize);
118         offset += (frag_size - total_hdrsize);
119     } while (l_remainder > 0);
120 
121     frag_header->frame_control.more_frag = HI_FALSE;
122     set_oal_netbuf_next(netbuf, HI_NULL);
123 
124     /* 原始报文作为分片报文的第一个 */
125     oal_netbuf_trim(netbuf_original, oal_netbuf_len(netbuf_original) - (max_tx_unit - cip_hdrsize));
126 
127     tx_ctl->us_mpdu_len = (hi_u16)(oal_netbuf_len(netbuf_original));
128 
129     return HI_SUCCESS;
130 }
131 
132 /* ****************************************************************************
133  功能描述  : 报文分片处理
134  修改历史      :
135   1.日    期   : 2014年2月18日
136     作    者   : HiSilicon
137     修改内容   : 新生成函数
138 **************************************************************************** */
hmac_frag_process_proc(const hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user,oal_netbuf_stru * netbuf,hmac_tx_ctl_stru * tx_ctl)139 hi_u32 hmac_frag_process_proc(const hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user, oal_netbuf_stru *netbuf,
140     hmac_tx_ctl_stru *tx_ctl)
141 {
142     hi_u32 threshold;
143     hi_u8  ic_header = 0;
144     hi_u32 ret;
145     hi_u32 last_frag;
146 
147     /* 获取分片门限 */
148     threshold = hmac_vap->base_vap->mib_info->wlan_mib_operation.dot11_fragmentation_threshold;
149 
150     /* 调用加密接口在使用TKIP时对MSDU进行加密后在进行分片 */
151     ret = hmac_en_mic(hmac_user, netbuf, &ic_header);
152     if (ret != HI_SUCCESS) {
153         oam_error_log1(hmac_vap->base_vap->vap_id, OAM_SF_ANY, "{hmac_frag_process_proc::hmac_en_mic failed[%d].}",
154             ret);
155         return ret;
156     }
157     /* D2手机ping不通问题,将门限值4*n+2 */
158     threshold = (threshold & (~(BIT0 | BIT1))) + 2;
159 
160     /* 规避1151硬件bug,调整分片门限:TKIP加密时,当最后一个分片的payload长度小于等于8时,无法进行加密 */
161     if (hmac_user->base_user->key_info.cipher_type == WLAN_80211_CIPHER_SUITE_TKIP) {
162         last_frag = oal_netbuf_len(netbuf) % (threshold - (hi_u32)ic_header - tx_ctl->frame_header_length);
163         if ((last_frag > 0) && (last_frag <= 8)) { /* 0:长度,8:长度 */
164             threshold = threshold + 8;             /* 8:门限加8 */
165             oam_info_log1(hmac_vap->base_vap->vap_id, OAM_SF_ANY,
166                 "{hmac_frag_process_proc::adjust the frag threshold to %d.}", threshold);
167         }
168     }
169     /* 进行分片处理 */
170     ret = hmac_frag_process(netbuf, tx_ctl, (hi_u32)ic_header, threshold);
171 
172     return ret;
173 }
174 
175 /* ****************************************************************************
176  功能描述  : 解分片超时处理
177  修改历史      :
178   1.日    期   : 2014年2月20日
179     作    者   : HiSilicon
180     修改内容   : 新生成函数
181 **************************************************************************** */
hmac_defrag_timeout_fn(hi_void * arg)182 hi_u32 hmac_defrag_timeout_fn(hi_void *arg)
183 {
184     hmac_user_stru *hmac_user = HI_NULL;
185     oal_netbuf_stru *netbuf = HI_NULL;
186     hmac_user = (hmac_user_stru *)arg;
187 
188     /* 超时后释放正在重组的分片报文 */
189     if (hmac_user->defrag_netbuf != HI_NULL) {
190         netbuf = hmac_user->defrag_netbuf;
191 
192         oal_netbuf_free(netbuf);
193         hmac_user->defrag_netbuf = HI_NULL;
194     }
195 
196     return HI_SUCCESS;
197 }
198 
hmac_defrag_process_frame(hmac_user_stru * hmac_user,oal_netbuf_stru * netbuf,hi_u8 frag_num,const mac_ieee80211_frame_stru * mac_hdr,hi_u8 more_frag)199 static hi_u32 hmac_defrag_process_frame(hmac_user_stru *hmac_user, oal_netbuf_stru *netbuf, hi_u8 frag_num,
200     const mac_ieee80211_frame_stru *mac_hdr, hi_u8 more_frag)
201 {
202     /* 首片分片的分片号不为0则释放 */
203     if (frag_num != 0) {
204         oal_netbuf_free(netbuf);
205         oam_info_log3(hmac_user->base_user->vap_id, OAM_SF_ANY,
206             "{hmac_defrag_process:frag_num not Zero %d,seq_num %d,frag %d}", frag_num, mac_hdr->seq_num, more_frag);
207         return HI_FAIL;
208     }
209 
210     /* 启动超时定时器,超时释放重组报文 */
211     frw_timer_create_timer(&hmac_user->defrag_timer, hmac_defrag_timeout_fn, HMAC_FRAG_TIMEOUT, hmac_user, HI_FALSE);
212 #ifdef _PRE_LWIP_ZERO_COPY
213     oal_netbuf_stru *new_buf = oal_pbuf_netbuf_alloc(HMAC_MAX_FRAG_SIZE);
214 #else
215     /* 内存池netbuf只有1600 可能不够,参照A公司申请2500操作系统原生态报文 */
216     oal_netbuf_stru *new_buf = oal_netbuf_alloc(HMAC_MAX_FRAG_SIZE, 0, 4); /* align 4 */
217 #endif
218     if (new_buf == HI_NULL) {
219         oam_error_log0(hmac_user->base_user->vap_id, OAM_SF_ANY, "{hmac_defrag_process::Alloc new_buf null.}");
220         oal_netbuf_free(netbuf);
221         return HI_FAIL;
222     }
223 
224     if (memcpy_s(oal_netbuf_cb(new_buf), oal_netbuf_cb_size(), oal_netbuf_cb(netbuf), oal_netbuf_cb_size()) != EOK) {
225         oam_error_log0(0, OAM_SF_ANY, "{hmac_defrag_process::mem safe function err!}");
226         oal_netbuf_free(new_buf);
227         oal_netbuf_free(netbuf);
228         return HI_FAIL;
229     }
230     hmac_rx_ctl_stru *rx_ctl = (hmac_rx_ctl_stru *)oal_netbuf_cb(new_buf);
231     hmac_user->defrag_netbuf = new_buf;
232 
233 #ifdef _PRE_LWIP_ZERO_COPY
234     oal_netbuf_reserve(new_buf, WLAN_MAX_MAC_HDR_LEN - rx_ctl->mac_header_len);
235 #endif
236 
237     /* 将分片报文拷贝到新申请的报文中并挂接到用户结构体下,释放原有的报文 */
238     oal_netbuf_init(new_buf, oal_netbuf_len(netbuf));
239     if (memcpy_s(oal_netbuf_data(new_buf), HMAC_MAX_FRAG_SIZE, oal_netbuf_data(netbuf), oal_netbuf_len(netbuf)) != EOK) {
240         oam_error_log0(0, 0, "hmac_defrag_process_frame:: memcpy_s FAILED");
241         oal_netbuf_free(hmac_user->defrag_netbuf);
242         hmac_user->defrag_netbuf = HI_NULL;
243         oal_netbuf_free(netbuf);
244         return HI_FAIL;
245     }
246     rx_ctl->pul_mac_hdr_start_addr = (hi_u32 *)oal_netbuf_header(new_buf);
247     oal_netbuf_free(netbuf);
248 
249     return HI_SUCCESS;
250 }
251 
hmac_get_defraged_netbuf(hmac_user_stru * hmac_user,mac_ieee80211_frame_stru * last_hdr)252 oal_netbuf_stru *hmac_get_defraged_netbuf(hmac_user_stru *hmac_user, mac_ieee80211_frame_stru *last_hdr)
253 {
254     oal_netbuf_stru *netbuf = hmac_user->defrag_netbuf;
255     /* 对重组好的报文进行mic检查 */
256     if (hmac_de_mic(hmac_user, netbuf) != HI_SUCCESS) {
257         oal_netbuf_free(netbuf);
258         netbuf = HI_NULL;
259         last_hdr = HI_NULL;
260     }
261 
262     hmac_user->defrag_netbuf = HI_NULL;
263     if (last_hdr == HI_NULL) {
264         oam_error_log0(0, 0, "{get_defraged_netbuf::pst_last_hdr null.}");
265         return HI_NULL;
266     }
267 
268     last_hdr->frag_num = 0;
269     frw_timer_immediate_destroy_timer(&hmac_user->defrag_timer);
270     return netbuf;
271 }
272 
273 /* ****************************************************************************
274  功能描述  : 去分片处理
275  修改历史      :
276   1.日    期   : 2014年2月20日
277     作    者   : HiSilicon
278     修改内容   : 新生成函数
279 **************************************************************************** */
hmac_defrag_process(hmac_user_stru * hmac_user,oal_netbuf_stru * netbuf,hi_u32 hrdsize)280 oal_netbuf_stru *hmac_defrag_process(hmac_user_stru *hmac_user, oal_netbuf_stru *netbuf, hi_u32 hrdsize)
281 {
282     mac_ieee80211_frame_stru *last_hdr = HI_NULL;
283 
284     mac_ieee80211_frame_stru *mac_hdr = (mac_ieee80211_frame_stru *)oal_netbuf_data(netbuf);
285     hi_u8 more_frag = (hi_u8)mac_hdr->frame_control.more_frag;
286 
287     /* 如果没有什么可以去分片的则直接返回 */
288     if (!more_frag && ((hi_u8)mac_hdr->frag_num == 0) && (hmac_user->defrag_netbuf == HI_NULL)) {
289         return netbuf;
290     }
291 
292     /* 首先检查到来的分片报文是不是属于正在重组的分片报文 */
293     if (hmac_user->defrag_netbuf != HI_NULL) {
294         frw_timer_restart_timer(&hmac_user->defrag_timer, HMAC_FRAG_TIMEOUT, HI_FALSE);
295         last_hdr = (mac_ieee80211_frame_stru *)oal_netbuf_data(hmac_user->defrag_netbuf);
296         /* 如果地址不匹配,序列号不匹配,分片号不匹配则释放现在正在重组的报文 */
297         if (mac_hdr->seq_num != last_hdr->seq_num || (hi_u8)mac_hdr->frag_num != ((hi_u8)last_hdr->frag_num + 1) ||
298             oal_compare_mac_addr(last_hdr->auc_address1, mac_hdr->auc_address1, WLAN_MAC_ADDR_LEN) ||
299             oal_compare_mac_addr(last_hdr->auc_address2, mac_hdr->auc_address2, WLAN_MAC_ADDR_LEN)) {
300             oal_netbuf_free(hmac_user->defrag_netbuf);
301             frw_timer_immediate_destroy_timer(&hmac_user->defrag_timer);
302             hmac_user->defrag_netbuf = HI_NULL;
303         }
304     }
305 
306     /* 判断到来的分片报文是否是第一个分片 */
307     if (hmac_user->defrag_netbuf == HI_NULL) {
308         if (hmac_defrag_process_frame(hmac_user, netbuf, (hi_u8)mac_hdr->frag_num, mac_hdr, more_frag) != HI_SUCCESS) {
309             return HI_NULL;
310         }
311     } else {
312         /* 此分片是期望的到来的分片,重启定时器,并进行重组 */
313         frw_timer_restart_timer(&hmac_user->defrag_timer, HMAC_FRAG_TIMEOUT, HI_FALSE);
314         oal_netbuf_pull(netbuf, hrdsize);
315         /* 去分片失败释放当前分片报文 */
316         if (oal_netbuf_concat(hmac_user->defrag_netbuf, netbuf) != HI_SUCCESS) {
317             oal_netbuf_free(hmac_user->defrag_netbuf);
318             oal_netbuf_free(netbuf);
319             frw_timer_immediate_destroy_timer(&hmac_user->defrag_timer);
320             hmac_user->defrag_netbuf = HI_NULL;
321             return HI_NULL;
322         }
323         /* 记录最新分片报文的分片号 */
324         last_hdr->seq_num   = mac_hdr->seq_num;
325         last_hdr->frag_num  = mac_hdr->frag_num;
326     }
327 
328     /* 判断是否重组完毕,存在更多报文返回空指针,重组完毕返回组好的报文 */
329     if (more_frag) {
330         return HI_NULL;
331     }
332 
333     return hmac_get_defraged_netbuf(hmac_user, last_hdr);
334 }
335 
336 #ifdef __cplusplus
337 #if __cplusplus
338 }
339 #endif
340 #endif
341