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