]>
Commit | Line | Data |
---|---|---|
abb3b3dc | 1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along with | |
15 | * this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
17 | * | |
18 | * | |
19 | ******************************************************************************/ | |
20 | #define _RTW_RECV_C_ | |
21 | #include <drv_conf.h> | |
22 | #include <osdep_service.h> | |
23 | #include <drv_types.h> | |
24 | #include <recv_osdep.h> | |
25 | #include <mlme_osdep.h> | |
26 | #include <ip.h> | |
27 | #include <if_ether.h> | |
28 | #include <ethernet.h> | |
29 | ||
30 | #ifdef CONFIG_USB_HCI | |
31 | #include <usb_ops.h> | |
32 | #endif | |
33 | ||
34 | #if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS) | |
35 | ||
36 | #error "Shall be Linux or Windows, but not both!\n" | |
37 | ||
38 | #endif | |
39 | ||
40 | #include <wifi.h> | |
41 | #include <circ_buf.h> | |
42 | ||
43 | #ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS | |
44 | void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS); | |
45 | #endif //CONFIG_NEW_SIGNAL_STAT_PROCESS | |
46 | ||
47 | ||
48 | void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv) | |
49 | { | |
50 | ||
51 | ||
52 | _func_enter_; | |
53 | ||
54 | _rtw_memset((u8 *)psta_recvpriv, 0, sizeof (struct sta_recv_priv)); | |
55 | ||
56 | _rtw_spinlock_init(&psta_recvpriv->lock); | |
57 | ||
58 | //for(i=0; i<MAX_RX_NUMBLKS; i++) | |
59 | // _rtw_init_queue(&psta_recvpriv->blk_strms[i]); | |
60 | ||
61 | _rtw_init_queue(&psta_recvpriv->defrag_q); | |
62 | ||
63 | _func_exit_; | |
64 | ||
65 | } | |
66 | ||
67 | sint _rtw_init_recv_priv(struct recv_priv *precvpriv, _adapter *padapter) | |
68 | { | |
69 | sint i; | |
70 | ||
71 | union recv_frame *precvframe; | |
72 | ||
73 | sint res=_SUCCESS; | |
74 | ||
75 | _func_enter_; | |
76 | ||
77 | // We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). | |
78 | //_rtw_memset((unsigned char *)precvpriv, 0, sizeof (struct recv_priv)); | |
79 | ||
80 | _rtw_spinlock_init(&precvpriv->lock); | |
81 | ||
82 | _rtw_init_queue(&precvpriv->free_recv_queue); | |
83 | _rtw_init_queue(&precvpriv->recv_pending_queue); | |
84 | _rtw_init_queue(&precvpriv->uc_swdec_pending_queue); | |
85 | ||
86 | precvpriv->adapter = padapter; | |
87 | ||
88 | precvpriv->free_recvframe_cnt = NR_RECVFRAME; | |
89 | ||
90 | rtw_os_recv_resource_init(precvpriv, padapter); | |
91 | ||
92 | precvpriv->pallocated_frame_buf = rtw_zvmalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ); | |
93 | ||
94 | if(precvpriv->pallocated_frame_buf==NULL){ | |
95 | res= _FAIL; | |
96 | goto exit; | |
97 | } | |
98 | //_rtw_memset(precvpriv->pallocated_frame_buf, 0, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ); | |
99 | ||
100 | precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ); | |
101 | //precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - | |
102 | // ((SIZE_PTR) (precvpriv->pallocated_frame_buf) &(RXFRAME_ALIGN_SZ-1)); | |
103 | ||
104 | precvframe = (union recv_frame*) precvpriv->precv_frame_buf; | |
105 | ||
106 | ||
107 | for(i=0; i < NR_RECVFRAME ; i++) | |
108 | { | |
109 | _rtw_init_listhead(&(precvframe->u.list)); | |
110 | ||
111 | rtw_list_insert_tail(&(precvframe->u.list), &(precvpriv->free_recv_queue.queue)); | |
112 | ||
113 | res = rtw_os_recv_resource_alloc(padapter, precvframe); | |
114 | ||
115 | precvframe->u.hdr.adapter =padapter; | |
116 | precvframe++; | |
117 | ||
118 | } | |
119 | ||
120 | #ifdef CONFIG_USB_HCI | |
121 | ||
122 | precvpriv->rx_pending_cnt=1; | |
123 | ||
124 | _rtw_init_sema(&precvpriv->allrxreturnevt, 0); | |
125 | ||
126 | #endif | |
127 | ||
128 | res = rtw_hal_init_recv_priv(padapter); | |
129 | ||
130 | precvpriv->recvbuf_skb_alloc_fail_cnt = 0; | |
131 | precvpriv->recvbuf_null_cnt = 0; | |
132 | precvpriv->read_port_complete_EINPROGRESS_cnt = 0; | |
133 | precvpriv->read_port_complete_other_urb_err_cnt = 0; | |
134 | ||
135 | #ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS | |
136 | #ifdef PLATFORM_LINUX | |
137 | _init_timer(&precvpriv->signal_stat_timer, padapter->pnetdev, RTW_TIMER_HDL_NAME(signal_stat), padapter); | |
138 | #elif defined(PLATFORM_OS_CE) || defined(PLATFORM_WINDOWS) | |
139 | _init_timer(&precvpriv->signal_stat_timer, padapter->hndis_adapter, RTW_TIMER_HDL_NAME(signal_stat), padapter); | |
140 | #endif | |
141 | ||
142 | precvpriv->signal_stat_sampling_interval = 1000; //ms | |
143 | //precvpriv->signal_stat_converging_constant = 5000; //ms | |
144 | ||
145 | rtw_set_signal_stat_timer(precvpriv); | |
146 | #endif //CONFIG_NEW_SIGNAL_STAT_PROCESS | |
147 | ||
148 | exit: | |
149 | ||
150 | _func_exit_; | |
151 | ||
152 | return res; | |
153 | ||
154 | } | |
155 | ||
156 | void rtw_mfree_recv_priv_lock(struct recv_priv *precvpriv); | |
157 | void rtw_mfree_recv_priv_lock(struct recv_priv *precvpriv) | |
158 | { | |
159 | _rtw_spinlock_free(&precvpriv->lock); | |
160 | #ifdef CONFIG_RECV_THREAD_MODE | |
161 | _rtw_free_sema(&precvpriv->recv_sema); | |
162 | _rtw_free_sema(&precvpriv->terminate_recvthread_sema); | |
163 | #endif | |
164 | ||
165 | _rtw_spinlock_free(&precvpriv->free_recv_queue.lock); | |
166 | _rtw_spinlock_free(&precvpriv->recv_pending_queue.lock); | |
167 | ||
168 | _rtw_spinlock_free(&precvpriv->free_recv_buf_queue.lock); | |
169 | ||
170 | #ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX | |
171 | _rtw_spinlock_free(&precvpriv->recv_buf_pending_queue.lock); | |
172 | #endif // CONFIG_USE_USB_BUFFER_ALLOC_RX | |
173 | } | |
174 | ||
175 | void _rtw_free_recv_priv (struct recv_priv *precvpriv) | |
176 | { | |
177 | _adapter *padapter = precvpriv->adapter; | |
178 | ||
179 | _func_enter_; | |
180 | ||
181 | rtw_free_uc_swdec_pending_queue(padapter); | |
182 | ||
183 | rtw_mfree_recv_priv_lock(precvpriv); | |
184 | ||
185 | rtw_os_recv_resource_free(precvpriv); | |
186 | ||
187 | if(precvpriv->pallocated_frame_buf) { | |
188 | rtw_vmfree(precvpriv->pallocated_frame_buf, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ); | |
189 | } | |
190 | ||
191 | rtw_hal_free_recv_priv(padapter); | |
192 | ||
193 | _func_exit_; | |
194 | ||
195 | } | |
196 | ||
197 | union recv_frame *_rtw_alloc_recvframe (_queue *pfree_recv_queue) | |
198 | { | |
199 | ||
200 | union recv_frame *precvframe; | |
201 | _list *plist, *phead; | |
202 | _adapter *padapter; | |
203 | struct recv_priv *precvpriv; | |
204 | _func_enter_; | |
205 | ||
206 | if(_rtw_queue_empty(pfree_recv_queue) == _TRUE) | |
207 | { | |
208 | precvframe = NULL; | |
209 | } | |
210 | else | |
211 | { | |
212 | phead = get_list_head(pfree_recv_queue); | |
213 | ||
214 | plist = get_next(phead); | |
215 | ||
216 | precvframe = LIST_CONTAINOR(plist, union recv_frame, u); | |
217 | ||
218 | rtw_list_delete(&precvframe->u.hdr.list); | |
219 | padapter=precvframe->u.hdr.adapter; | |
220 | if(padapter !=NULL){ | |
221 | precvpriv=&padapter->recvpriv; | |
222 | if(pfree_recv_queue == &precvpriv->free_recv_queue) | |
223 | precvpriv->free_recvframe_cnt--; | |
224 | } | |
225 | } | |
226 | ||
227 | _func_exit_; | |
228 | ||
229 | return precvframe; | |
230 | ||
231 | } | |
232 | ||
233 | union recv_frame *rtw_alloc_recvframe (_queue *pfree_recv_queue) | |
234 | { | |
235 | _irqL irqL; | |
236 | union recv_frame *precvframe; | |
237 | ||
238 | _enter_critical_bh(&pfree_recv_queue->lock, &irqL); | |
239 | ||
240 | precvframe = _rtw_alloc_recvframe(pfree_recv_queue); | |
241 | ||
242 | _exit_critical_bh(&pfree_recv_queue->lock, &irqL); | |
243 | ||
244 | return precvframe; | |
245 | } | |
246 | ||
247 | void rtw_init_recvframe(union recv_frame *precvframe, struct recv_priv *precvpriv) | |
248 | { | |
249 | /* Perry: This can be removed */ | |
250 | _rtw_init_listhead(&precvframe->u.hdr.list); | |
251 | ||
252 | precvframe->u.hdr.len=0; | |
253 | } | |
254 | ||
255 | int rtw_free_recvframe(union recv_frame *precvframe, _queue *pfree_recv_queue) | |
256 | { | |
257 | _irqL irqL; | |
258 | _adapter *padapter=precvframe->u.hdr.adapter; | |
259 | struct recv_priv *precvpriv = &padapter->recvpriv; | |
260 | ||
261 | _func_enter_; | |
262 | ||
263 | #ifdef CONFIG_CONCURRENT_MODE | |
264 | if(padapter->adapter_type > PRIMARY_ADAPTER) | |
265 | { | |
266 | padapter = padapter->pbuddy_adapter;//get primary_padapter | |
267 | precvpriv = &padapter->recvpriv; | |
268 | pfree_recv_queue = &precvpriv->free_recv_queue; | |
269 | precvframe->u.hdr.adapter = padapter; | |
270 | } | |
271 | #endif | |
272 | ||
273 | ||
274 | #ifdef PLATFORM_WINDOWS | |
275 | rtw_os_read_port(padapter, precvframe->u.hdr.precvbuf); | |
276 | #endif | |
277 | ||
278 | #if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD) | |
279 | ||
280 | if(precvframe->u.hdr.pkt) | |
281 | { | |
282 | #ifdef CONFIG_BSD_RX_USE_MBUF | |
283 | m_freem(precvframe->u.hdr.pkt); | |
284 | #else // CONFIG_BSD_RX_USE_MBUF | |
285 | rtw_skb_free(precvframe->u.hdr.pkt);//free skb by driver | |
286 | #endif // CONFIG_BSD_RX_USE_MBUF | |
287 | precvframe->u.hdr.pkt = NULL; | |
288 | } | |
289 | ||
290 | #endif //defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD) | |
291 | ||
292 | _enter_critical_bh(&pfree_recv_queue->lock, &irqL); | |
293 | ||
294 | rtw_list_delete(&(precvframe->u.hdr.list)); | |
295 | ||
296 | rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(pfree_recv_queue)); | |
297 | ||
298 | if(padapter !=NULL){ | |
299 | if(pfree_recv_queue == &precvpriv->free_recv_queue) | |
300 | precvpriv->free_recvframe_cnt++; | |
301 | } | |
302 | ||
303 | _exit_critical_bh(&pfree_recv_queue->lock, &irqL); | |
304 | ||
305 | _func_exit_; | |
306 | ||
307 | return _SUCCESS; | |
308 | ||
309 | } | |
310 | ||
311 | ||
312 | ||
313 | ||
314 | sint _rtw_enqueue_recvframe(union recv_frame *precvframe, _queue *queue) | |
315 | { | |
316 | ||
317 | _adapter *padapter=precvframe->u.hdr.adapter; | |
318 | struct recv_priv *precvpriv = &padapter->recvpriv; | |
319 | ||
320 | _func_enter_; | |
321 | ||
322 | //_rtw_init_listhead(&(precvframe->u.hdr.list)); | |
323 | rtw_list_delete(&(precvframe->u.hdr.list)); | |
324 | ||
325 | ||
326 | rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(queue)); | |
327 | ||
328 | if (padapter != NULL) { | |
329 | if (queue == &precvpriv->free_recv_queue) | |
330 | precvpriv->free_recvframe_cnt++; | |
331 | } | |
332 | ||
333 | _func_exit_; | |
334 | ||
335 | return _SUCCESS; | |
336 | } | |
337 | ||
338 | sint rtw_enqueue_recvframe(union recv_frame *precvframe, _queue *queue) | |
339 | { | |
340 | sint ret; | |
341 | _irqL irqL; | |
342 | ||
343 | //_spinlock(&pfree_recv_queue->lock); | |
344 | _enter_critical_bh(&queue->lock, &irqL); | |
345 | ret = _rtw_enqueue_recvframe(precvframe, queue); | |
346 | //_rtw_spinunlock(&pfree_recv_queue->lock); | |
347 | _exit_critical_bh(&queue->lock, &irqL); | |
348 | ||
349 | return ret; | |
350 | } | |
351 | ||
352 | /* | |
353 | sint rtw_enqueue_recvframe(union recv_frame *precvframe, _queue *queue) | |
354 | { | |
355 | return rtw_free_recvframe(precvframe, queue); | |
356 | } | |
357 | */ | |
358 | ||
359 | ||
360 | ||
361 | ||
362 | /* | |
363 | caller : defrag ; recvframe_chk_defrag in recv_thread (passive) | |
364 | pframequeue: defrag_queue : will be accessed in recv_thread (passive) | |
365 | ||
366 | using spinlock to protect | |
367 | ||
368 | */ | |
369 | ||
370 | void rtw_free_recvframe_queue(_queue *pframequeue, _queue *pfree_recv_queue) | |
371 | { | |
372 | union recv_frame *precvframe; | |
373 | _list *plist, *phead; | |
374 | ||
375 | _func_enter_; | |
376 | _rtw_spinlock(&pframequeue->lock); | |
377 | ||
378 | phead = get_list_head(pframequeue); | |
379 | plist = get_next(phead); | |
380 | ||
381 | while(rtw_end_of_queue_search(phead, plist) == _FALSE) | |
382 | { | |
383 | precvframe = LIST_CONTAINOR(plist, union recv_frame, u); | |
384 | ||
385 | plist = get_next(plist); | |
386 | ||
387 | //rtw_list_delete(&precvframe->u.hdr.list); // will do this in rtw_free_recvframe() | |
388 | ||
389 | rtw_free_recvframe(precvframe, pfree_recv_queue); | |
390 | } | |
391 | ||
392 | _rtw_spinunlock(&pframequeue->lock); | |
393 | ||
394 | _func_exit_; | |
395 | ||
396 | } | |
397 | ||
398 | u32 rtw_free_uc_swdec_pending_queue(_adapter *adapter) | |
399 | { | |
400 | u32 cnt = 0; | |
401 | union recv_frame *pending_frame; | |
402 | while((pending_frame=rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) { | |
403 | rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue); | |
404 | DBG_871X("%s: dequeue uc_swdec_pending_queue\n", __func__); | |
405 | cnt++; | |
406 | } | |
407 | ||
408 | return cnt; | |
409 | } | |
410 | ||
411 | ||
412 | sint rtw_enqueue_recvbuf_to_head(struct recv_buf *precvbuf, _queue *queue) | |
413 | { | |
414 | _irqL irqL; | |
415 | ||
416 | _enter_critical(&queue->lock, &irqL); | |
417 | ||
418 | rtw_list_delete(&precvbuf->list); | |
419 | rtw_list_insert_head(&precvbuf->list, get_list_head(queue)); | |
420 | ||
421 | _exit_critical(&queue->lock, &irqL); | |
422 | ||
423 | return _SUCCESS; | |
424 | } | |
425 | ||
426 | sint rtw_enqueue_recvbuf(struct recv_buf *precvbuf, _queue *queue) | |
427 | { | |
428 | _irqL irqL; | |
429 | ||
430 | _enter_critical(&queue->lock, &irqL); | |
431 | ||
432 | rtw_list_delete(&precvbuf->list); | |
433 | ||
434 | rtw_list_insert_tail(&precvbuf->list, get_list_head(queue)); | |
435 | ||
436 | _exit_critical(&queue->lock, &irqL); | |
437 | ||
438 | ||
439 | return _SUCCESS; | |
440 | ||
441 | } | |
442 | ||
443 | struct recv_buf *rtw_dequeue_recvbuf (_queue *queue) | |
444 | { | |
445 | _irqL irqL; | |
446 | struct recv_buf *precvbuf; | |
447 | _list *plist, *phead; | |
448 | ||
449 | _enter_critical(&queue->lock, &irqL); | |
450 | ||
451 | if(_rtw_queue_empty(queue) == _TRUE) | |
452 | { | |
453 | precvbuf = NULL; | |
454 | } | |
455 | else | |
456 | { | |
457 | phead = get_list_head(queue); | |
458 | ||
459 | plist = get_next(phead); | |
460 | ||
461 | precvbuf = LIST_CONTAINOR(plist, struct recv_buf, list); | |
462 | ||
463 | rtw_list_delete(&precvbuf->list); | |
464 | ||
465 | } | |
466 | ||
467 | _exit_critical(&queue->lock, &irqL); | |
468 | ||
469 | ||
470 | return precvbuf; | |
471 | ||
472 | } | |
473 | ||
474 | sint recvframe_chkmic(_adapter *adapter, union recv_frame *precvframe); | |
475 | sint recvframe_chkmic(_adapter *adapter, union recv_frame *precvframe){ | |
476 | ||
477 | sint i,res=_SUCCESS; | |
478 | u32 datalen; | |
479 | u8 miccode[8]; | |
480 | u8 bmic_err=_FALSE,brpt_micerror = _TRUE; | |
481 | u8 *pframe, *payload,*pframemic; | |
482 | u8 *mickey; | |
483 | //u8 *iv,rxdata_key_idx=0; | |
484 | struct sta_info *stainfo; | |
485 | struct rx_pkt_attrib *prxattrib=&precvframe->u.hdr.attrib; | |
486 | struct security_priv *psecuritypriv=&adapter->securitypriv; | |
487 | ||
488 | struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; | |
489 | struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); | |
490 | _func_enter_; | |
491 | ||
492 | stainfo=rtw_get_stainfo(&adapter->stapriv ,&prxattrib->ta[0]); | |
493 | ||
494 | if(prxattrib->encrypt ==_TKIP_) | |
495 | { | |
496 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n recvframe_chkmic:prxattrib->encrypt ==_TKIP_\n")); | |
497 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n recvframe_chkmic:da=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", | |
498 | prxattrib->ra[0],prxattrib->ra[1],prxattrib->ra[2],prxattrib->ra[3],prxattrib->ra[4],prxattrib->ra[5])); | |
499 | ||
500 | //calculate mic code | |
501 | if(stainfo!= NULL) | |
502 | { | |
503 | if(IS_MCAST(prxattrib->ra)) | |
504 | { | |
505 | //mickey=&psecuritypriv->dot118021XGrprxmickey.skey[0]; | |
506 | //iv = precvframe->u.hdr.rx_data+prxattrib->hdrlen; | |
507 | //rxdata_key_idx =( ((iv[3])>>6)&0x3) ; | |
508 | mickey=&psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0]; | |
509 | ||
510 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n recvframe_chkmic: bcmc key \n")); | |
511 | //DBG_871X("\n recvframe_chkmic: bcmc key psecuritypriv->dot118021XGrpKeyid(%d),pmlmeinfo->key_index(%d) ,recv key_id(%d)\n", | |
512 | // psecuritypriv->dot118021XGrpKeyid,pmlmeinfo->key_index,rxdata_key_idx); | |
513 | ||
514 | if(psecuritypriv->binstallGrpkey==_FALSE) | |
515 | { | |
516 | res=_FAIL; | |
517 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n")); | |
518 | DBG_871X("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n"); | |
519 | goto exit; | |
520 | } | |
521 | } | |
522 | else{ | |
523 | mickey=&stainfo->dot11tkiprxmickey.skey[0]; | |
524 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n recvframe_chkmic: unicast key \n")); | |
525 | } | |
526 | ||
527 | datalen=precvframe->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len-prxattrib->icv_len-8;//icv_len included the mic code | |
528 | pframe=precvframe->u.hdr.rx_data; | |
529 | payload=pframe+prxattrib->hdrlen+prxattrib->iv_len; | |
530 | ||
531 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n",prxattrib->iv_len,prxattrib->icv_len)); | |
532 | ||
533 | //rtw_seccalctkipmic(&stainfo->dot11tkiprxmickey.skey[0],pframe,payload, datalen ,&miccode[0],(unsigned char)prxattrib->priority); //care the length of the data | |
534 | ||
535 | rtw_seccalctkipmic(mickey,pframe,payload, datalen ,&miccode[0],(unsigned char)prxattrib->priority); //care the length of the data | |
536 | ||
537 | pframemic=payload+datalen; | |
538 | ||
539 | bmic_err=_FALSE; | |
540 | ||
541 | for(i=0;i<8;i++){ | |
542 | if(miccode[i] != *(pframemic+i)){ | |
543 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvframe_chkmic:miccode[%d](%02x) != *(pframemic+%d)(%02x) ",i,miccode[i],i,*(pframemic+i))); | |
544 | bmic_err=_TRUE; | |
545 | } | |
546 | } | |
547 | ||
548 | ||
549 | if(bmic_err==_TRUE){ | |
550 | ||
551 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n *(pframemic-8)-*(pframemic-1)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", | |
552 | *(pframemic-8),*(pframemic-7),*(pframemic-6),*(pframemic-5),*(pframemic-4),*(pframemic-3),*(pframemic-2),*(pframemic-1))); | |
553 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n *(pframemic-16)-*(pframemic-9)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", | |
554 | *(pframemic-16),*(pframemic-15),*(pframemic-14),*(pframemic-13),*(pframemic-12),*(pframemic-11),*(pframemic-10),*(pframemic-9))); | |
555 | ||
556 | { | |
557 | uint i; | |
558 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n ======demp packet (len=%d)======\n",precvframe->u.hdr.len)); | |
559 | for(i=0;i<precvframe->u.hdr.len;i=i+8){ | |
560 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x", | |
561 | *(precvframe->u.hdr.rx_data+i),*(precvframe->u.hdr.rx_data+i+1), | |
562 | *(precvframe->u.hdr.rx_data+i+2),*(precvframe->u.hdr.rx_data+i+3), | |
563 | *(precvframe->u.hdr.rx_data+i+4),*(precvframe->u.hdr.rx_data+i+5), | |
564 | *(precvframe->u.hdr.rx_data+i+6),*(precvframe->u.hdr.rx_data+i+7))); | |
565 | } | |
566 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n ======demp packet end [len=%d]======\n",precvframe->u.hdr.len)); | |
567 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n hrdlen=%d, \n",prxattrib->hdrlen)); | |
568 | } | |
569 | ||
570 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("ra=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x psecuritypriv->binstallGrpkey=%d ", | |
571 | prxattrib->ra[0],prxattrib->ra[1],prxattrib->ra[2], | |
572 | prxattrib->ra[3],prxattrib->ra[4],prxattrib->ra[5],psecuritypriv->binstallGrpkey)); | |
573 | ||
574 | // double check key_index for some timing issue , | |
575 | // cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue | |
576 | if((IS_MCAST(prxattrib->ra)==_TRUE) && (prxattrib->key_index != pmlmeinfo->key_index )) | |
577 | brpt_micerror = _FALSE; | |
578 | ||
579 | if(brpt_micerror == _TRUE) | |
580 | { | |
581 | rtw_handle_tkip_mic_err(adapter,(u8)IS_MCAST(prxattrib->ra)); | |
582 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" mic error :prxattrib->bdecrypted=%d \n", brpt_micerror)); | |
583 | DBG_871X(" mic error :brpt_micerror=%d\n", brpt_micerror); | |
584 | } | |
585 | ||
586 | res=_FAIL; | |
587 | ||
588 | } | |
589 | else{ | |
590 | //mic checked ok | |
591 | if((psecuritypriv->bcheck_grpkey ==_FALSE)&&(IS_MCAST(prxattrib->ra)==_TRUE)){ | |
592 | psecuritypriv->bcheck_grpkey =_TRUE; | |
593 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("psecuritypriv->bcheck_grpkey =_TRUE")); | |
594 | } | |
595 | } | |
596 | ||
597 | } | |
598 | else | |
599 | { | |
600 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvframe_chkmic: rtw_get_stainfo==NULL!!!\n")); | |
601 | } | |
602 | ||
603 | recvframe_pull_tail(precvframe, 8); | |
604 | ||
605 | } | |
606 | ||
607 | exit: | |
608 | ||
609 | _func_exit_; | |
610 | ||
611 | return res; | |
612 | ||
613 | } | |
614 | ||
615 | //decrypt and set the ivlen,icvlen of the recv_frame | |
616 | union recv_frame * decryptor(_adapter *padapter,union recv_frame *precv_frame); | |
617 | union recv_frame * decryptor(_adapter *padapter,union recv_frame *precv_frame) | |
618 | { | |
619 | ||
620 | struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib; | |
621 | struct security_priv *psecuritypriv=&padapter->securitypriv; | |
622 | union recv_frame *return_packet=precv_frame; | |
623 | u32 res=_SUCCESS; | |
624 | _func_enter_; | |
625 | ||
626 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("prxstat->decrypted=%x prxattrib->encrypt = 0x%03x\n",prxattrib->bdecrypted,prxattrib->encrypt)); | |
627 | ||
628 | if(prxattrib->encrypt>0) | |
629 | { | |
630 | u8 *iv = precv_frame->u.hdr.rx_data+prxattrib->hdrlen; | |
631 | prxattrib->key_index = ( ((iv[3])>>6)&0x3) ; | |
632 | ||
633 | if(prxattrib->key_index > WEP_KEYS) | |
634 | { | |
635 | DBG_871X("prxattrib->key_index(%d) > WEP_KEYS \n", prxattrib->key_index); | |
636 | ||
637 | switch(prxattrib->encrypt){ | |
638 | case _WEP40_: | |
639 | case _WEP104_: | |
640 | prxattrib->key_index = psecuritypriv->dot11PrivacyKeyIndex; | |
641 | break; | |
642 | case _TKIP_: | |
643 | case _AES_: | |
644 | default: | |
645 | prxattrib->key_index = psecuritypriv->dot118021XGrpKeyid; | |
646 | break; | |
647 | } | |
648 | } | |
649 | } | |
650 | ||
651 | if((prxattrib->encrypt>0) && ((prxattrib->bdecrypted==0) ||(psecuritypriv->sw_decrypt==_TRUE))) | |
652 | { | |
653 | ||
654 | #ifdef CONFIG_CONCURRENT_MODE | |
655 | if(!IS_MCAST(prxattrib->ra))//bc/mc packets use sw decryption for concurrent mode | |
656 | #endif | |
657 | psecuritypriv->hw_decrypted=_FALSE; | |
658 | ||
659 | #ifdef DBG_RX_DECRYPTOR | |
660 | DBG_871X("prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d\n" | |
661 | , prxattrib->bdecrypted ,prxattrib->encrypt, psecuritypriv->hw_decrypted); | |
662 | #endif | |
663 | ||
664 | switch(prxattrib->encrypt){ | |
665 | case _WEP40_: | |
666 | case _WEP104_: | |
667 | rtw_wep_decrypt(padapter, (u8 *)precv_frame); | |
668 | break; | |
669 | case _TKIP_: | |
670 | res = rtw_tkip_decrypt(padapter, (u8 *)precv_frame); | |
671 | break; | |
672 | case _AES_: | |
673 | res = rtw_aes_decrypt(padapter, (u8 * )precv_frame); | |
674 | break; | |
675 | default: | |
676 | break; | |
677 | } | |
678 | } | |
679 | else if(prxattrib->bdecrypted==1 | |
680 | && prxattrib->encrypt >0 | |
681 | && (psecuritypriv->busetkipkey==1 || prxattrib->encrypt !=_TKIP_ ) | |
682 | ) | |
683 | { | |
684 | #if 0 | |
685 | if((prxstat->icv==1)&&(prxattrib->encrypt!=_AES_)) | |
686 | { | |
687 | psecuritypriv->hw_decrypted=_FALSE; | |
688 | ||
689 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("psecuritypriv->hw_decrypted=_FALSE")); | |
690 | ||
691 | rtw_free_recvframe(precv_frame, &padapter->recvpriv.free_recv_queue); | |
692 | ||
693 | return_packet=NULL; | |
694 | ||
695 | } | |
696 | else | |
697 | #endif | |
698 | { | |
699 | psecuritypriv->hw_decrypted=_TRUE; | |
700 | #ifdef DBG_RX_DECRYPTOR | |
701 | DBG_871X("prxstat->bdecrypted:%d, prxattrib->encrypt:%d, Setting psecuritypriv->hw_decrypted = %d\n" | |
702 | , prxattrib->bdecrypted ,prxattrib->encrypt, psecuritypriv->hw_decrypted); | |
703 | #endif | |
704 | ||
705 | } | |
706 | } | |
707 | else { | |
708 | #ifdef DBG_RX_DECRYPTOR | |
709 | DBG_871X("prxstat->bdecrypted:%d, prxattrib->encrypt:%d, psecuritypriv->hw_decrypted:%d\n" | |
710 | , prxattrib->bdecrypted ,prxattrib->encrypt, psecuritypriv->hw_decrypted); | |
711 | #endif | |
712 | } | |
713 | ||
714 | if(res == _FAIL) | |
715 | { | |
716 | rtw_free_recvframe(return_packet,&padapter->recvpriv.free_recv_queue); | |
717 | return_packet = NULL; | |
718 | ||
719 | } | |
720 | //recvframe_chkmic(adapter, precv_frame); //move to recvframme_defrag function | |
721 | ||
722 | _func_exit_; | |
723 | ||
724 | return return_packet; | |
725 | ||
726 | } | |
727 | //###set the security information in the recv_frame | |
728 | union recv_frame * portctrl(_adapter *adapter,union recv_frame * precv_frame); | |
729 | union recv_frame * portctrl(_adapter *adapter,union recv_frame * precv_frame) | |
730 | { | |
731 | u8 *psta_addr,*ptr; | |
732 | uint auth_alg; | |
733 | struct recv_frame_hdr *pfhdr; | |
734 | struct sta_info * psta; | |
735 | struct sta_priv *pstapriv ; | |
736 | union recv_frame * prtnframe; | |
737 | u16 ether_type=0; | |
738 | u16 eapol_type = 0x888e;//for Funia BD's WPA issue | |
739 | struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; | |
740 | ||
741 | _func_enter_; | |
742 | ||
743 | pstapriv = &adapter->stapriv; | |
744 | ptr = get_recvframe_data(precv_frame); | |
745 | pfhdr = &precv_frame->u.hdr; | |
746 | psta_addr = pfhdr->attrib.ta; | |
747 | psta = rtw_get_stainfo(pstapriv, psta_addr); | |
748 | ||
749 | auth_alg = adapter->securitypriv.dot11AuthAlgrthm; | |
750 | ||
751 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("########portctrl:adapter->securitypriv.dot11AuthAlgrthm= 0x%d\n",adapter->securitypriv.dot11AuthAlgrthm)); | |
752 | ||
753 | if(auth_alg==2) | |
754 | { | |
755 | if ((psta!=NULL) && (psta->ieee8021x_blocked)) | |
756 | { | |
757 | //blocked | |
758 | //only accept EAPOL frame | |
759 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("########portctrl:psta->ieee8021x_blocked==1\n")); | |
760 | ||
761 | prtnframe=precv_frame; | |
762 | ||
763 | //get ether_type | |
764 | ptr=ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE; | |
765 | _rtw_memcpy(ðer_type,ptr, 2); | |
766 | ether_type= ntohs((unsigned short )ether_type); | |
767 | ||
768 | if (ether_type == eapol_type) { | |
769 | prtnframe=precv_frame; | |
770 | } | |
771 | else { | |
772 | //free this frame | |
773 | rtw_free_recvframe(precv_frame, &adapter->recvpriv.free_recv_queue); | |
774 | prtnframe=NULL; | |
775 | } | |
776 | } | |
777 | else | |
778 | { | |
779 | //allowed | |
780 | //check decryption status, and decrypt the frame if needed | |
781 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("########portctrl:psta->ieee8021x_blocked==0\n")); | |
782 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("portctrl:precv_frame->hdr.attrib.privacy=%x\n",precv_frame->u.hdr.attrib.privacy)); | |
783 | ||
784 | if(pattrib->bdecrypted==0) | |
785 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("portctrl:prxstat->decrypted=%x\n", pattrib->bdecrypted)); | |
786 | ||
787 | prtnframe=precv_frame; | |
788 | //check is the EAPOL frame or not (Rekey) | |
789 | if(ether_type == eapol_type){ | |
790 | ||
791 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("########portctrl:ether_type == 0x888e\n")); | |
792 | //check Rekey | |
793 | ||
794 | prtnframe=precv_frame; | |
795 | } | |
796 | else{ | |
797 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("########portctrl:ether_type = 0x%.4x\n",ether_type)); | |
798 | } | |
799 | } | |
800 | } | |
801 | else | |
802 | { | |
803 | prtnframe=precv_frame; | |
804 | } | |
805 | ||
806 | _func_exit_; | |
807 | ||
808 | return prtnframe; | |
809 | ||
810 | } | |
811 | ||
812 | sint recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache); | |
813 | sint recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache) | |
814 | { | |
815 | sint tid = precv_frame->u.hdr.attrib.priority; | |
816 | ||
817 | u16 seq_ctrl = ( (precv_frame->u.hdr.attrib.seq_num&0xffff) << 4) | | |
818 | (precv_frame->u.hdr.attrib.frag_num & 0xf); | |
819 | ||
820 | _func_enter_; | |
821 | ||
822 | if(tid>15) | |
823 | { | |
824 | RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, (tid>15)! seq_ctrl=0x%x, tid=0x%x\n", seq_ctrl, tid)); | |
825 | ||
826 | return _FAIL; | |
827 | } | |
828 | ||
829 | if(1)//if(bretry) | |
830 | { | |
831 | if(seq_ctrl == prxcache->tid_rxseq[tid]) | |
832 | { | |
833 | RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, seq_ctrl=0x%x, tid=0x%x, tid_rxseq=0x%x\n", seq_ctrl, tid, prxcache->tid_rxseq[tid])); | |
834 | ||
835 | return _FAIL; | |
836 | } | |
837 | } | |
838 | ||
839 | prxcache->tid_rxseq[tid] = seq_ctrl; | |
840 | ||
841 | _func_exit_; | |
842 | ||
843 | return _SUCCESS; | |
844 | ||
845 | } | |
846 | ||
847 | void process_pwrbit_data(_adapter *padapter, union recv_frame *precv_frame); | |
848 | void process_pwrbit_data(_adapter *padapter, union recv_frame *precv_frame) | |
849 | { | |
850 | #ifdef CONFIG_AP_MODE | |
851 | unsigned char pwrbit; | |
852 | u8 *ptr = precv_frame->u.hdr.rx_data; | |
853 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; | |
854 | struct sta_priv *pstapriv = &padapter->stapriv; | |
855 | struct sta_info *psta=NULL; | |
856 | ||
857 | psta = rtw_get_stainfo(pstapriv, pattrib->src); | |
858 | ||
859 | pwrbit = GetPwrMgt(ptr); | |
860 | ||
861 | if(psta) | |
862 | { | |
863 | if(pwrbit) | |
864 | { | |
865 | if(!(psta->state & WIFI_SLEEP_STATE)) | |
866 | { | |
867 | //psta->state |= WIFI_SLEEP_STATE; | |
868 | //pstapriv->sta_dz_bitmap |= BIT(psta->aid); | |
869 | ||
870 | stop_sta_xmit(padapter, psta); | |
871 | ||
872 | //DBG_871X("to sleep, sta_dz_bitmap=%x\n", pstapriv->sta_dz_bitmap); | |
873 | } | |
874 | } | |
875 | else | |
876 | { | |
877 | if(psta->state & WIFI_SLEEP_STATE) | |
878 | { | |
879 | //psta->state ^= WIFI_SLEEP_STATE; | |
880 | //pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); | |
881 | ||
882 | wakeup_sta_to_xmit(padapter, psta); | |
883 | ||
884 | //DBG_871X("to wakeup, sta_dz_bitmap=%x\n", pstapriv->sta_dz_bitmap); | |
885 | } | |
886 | } | |
887 | ||
888 | } | |
889 | ||
890 | #endif | |
891 | } | |
892 | ||
893 | void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame); | |
894 | void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame) | |
895 | { | |
896 | #ifdef CONFIG_AP_MODE | |
897 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; | |
898 | struct sta_priv *pstapriv = &padapter->stapriv; | |
899 | struct sta_info *psta=NULL; | |
900 | ||
901 | psta = rtw_get_stainfo(pstapriv, pattrib->src); | |
902 | ||
903 | if(!psta) return; | |
904 | ||
905 | #ifdef CONFIG_TDLS | |
906 | if( !(psta->tdls_sta_state & TDLS_LINKED_STATE ) ) | |
907 | { | |
908 | #endif //CONFIG_TDLS | |
909 | ||
910 | if(!psta->qos_option) | |
911 | return; | |
912 | ||
913 | if(!(psta->qos_info&0xf)) | |
914 | return; | |
915 | ||
916 | #ifdef CONFIG_TDLS | |
917 | } | |
918 | #endif //CONFIG_TDLS | |
919 | ||
920 | if(psta->state&WIFI_SLEEP_STATE) | |
921 | { | |
922 | u8 wmmps_ac=0; | |
923 | ||
924 | switch(pattrib->priority) | |
925 | { | |
926 | case 1: | |
927 | case 2: | |
928 | wmmps_ac = psta->uapsd_bk&BIT(1); | |
929 | break; | |
930 | case 4: | |
931 | case 5: | |
932 | wmmps_ac = psta->uapsd_vi&BIT(1); | |
933 | break; | |
934 | case 6: | |
935 | case 7: | |
936 | wmmps_ac = psta->uapsd_vo&BIT(1); | |
937 | break; | |
938 | case 0: | |
939 | case 3: | |
940 | default: | |
941 | wmmps_ac = psta->uapsd_be&BIT(1); | |
942 | break; | |
943 | } | |
944 | ||
945 | if(wmmps_ac) | |
946 | { | |
947 | if(psta->sleepq_ac_len>0) | |
948 | { | |
949 | //process received triggered frame | |
950 | xmit_delivery_enabled_frames(padapter, psta); | |
951 | } | |
952 | else | |
953 | { | |
954 | //issue one qos null frame with More data bit = 0 and the EOSP bit set (=1) | |
955 | issue_qos_nulldata(padapter, psta->hwaddr, (u16)pattrib->priority, 0, 0); | |
956 | } | |
957 | } | |
958 | ||
959 | } | |
960 | ||
961 | ||
962 | #endif | |
963 | ||
964 | } | |
965 | ||
966 | #ifdef CONFIG_TDLS | |
967 | sint OnTDLS(_adapter *adapter, union recv_frame *precv_frame) | |
968 | { | |
969 | struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; | |
970 | sint ret = _SUCCESS; | |
971 | u8 *paction = get_recvframe_data(precv_frame); | |
972 | u8 category_field = 1; | |
973 | #ifdef CONFIG_WFD | |
974 | u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a }; | |
975 | #endif //CONFIG_WFD | |
976 | struct tdls_info *ptdlsinfo = &(adapter->tdlsinfo); | |
977 | ||
978 | //point to action field | |
979 | paction+=pattrib->hdrlen | |
980 | + pattrib->iv_len | |
981 | + SNAP_SIZE | |
982 | + ETH_TYPE_LEN | |
983 | + PAYLOAD_TYPE_LEN | |
984 | + category_field; | |
985 | ||
986 | if(ptdlsinfo->enable == 0) | |
987 | { | |
988 | DBG_871X("recv tdls frame, " | |
989 | "but tdls haven't enabled\n"); | |
990 | ret = _FAIL; | |
991 | return ret; | |
992 | } | |
993 | ||
994 | switch(*paction){ | |
995 | case TDLS_SETUP_REQUEST: | |
996 | DBG_871X("recv tdls setup request frame\n"); | |
997 | ret=On_TDLS_Setup_Req(adapter, precv_frame); | |
998 | break; | |
999 | case TDLS_SETUP_RESPONSE: | |
1000 | DBG_871X("recv tdls setup response frame\n"); | |
1001 | ret=On_TDLS_Setup_Rsp(adapter, precv_frame); | |
1002 | break; | |
1003 | case TDLS_SETUP_CONFIRM: | |
1004 | DBG_871X("recv tdls setup confirm frame\n"); | |
1005 | ret=On_TDLS_Setup_Cfm(adapter, precv_frame); | |
1006 | break; | |
1007 | case TDLS_TEARDOWN: | |
1008 | DBG_871X("recv tdls teardown, free sta_info\n"); | |
1009 | ret=On_TDLS_Teardown(adapter, precv_frame); | |
1010 | break; | |
1011 | case TDLS_DISCOVERY_REQUEST: | |
1012 | DBG_871X("recv tdls discovery request frame\n"); | |
1013 | ret=On_TDLS_Dis_Req(adapter, precv_frame); | |
1014 | break; | |
1015 | case TDLS_PEER_TRAFFIC_RESPONSE: | |
1016 | DBG_871X("recv tdls peer traffic response frame\n"); | |
1017 | ret=On_TDLS_Peer_Traffic_Rsp(adapter, precv_frame); | |
1018 | break; | |
1019 | case TDLS_CHANNEL_SWITCH_REQUEST: | |
1020 | DBG_871X("recv tdls channel switch request frame\n"); | |
1021 | ret=On_TDLS_Ch_Switch_Req(adapter, precv_frame); | |
1022 | break; | |
1023 | case TDLS_CHANNEL_SWITCH_RESPONSE: | |
1024 | DBG_871X("recv tdls channel switch response frame\n"); | |
1025 | ret=On_TDLS_Ch_Switch_Rsp(adapter, precv_frame); | |
1026 | break; | |
1027 | #ifdef CONFIG_WFD | |
1028 | case 0x50: //First byte of WFA OUI | |
1029 | if( _rtw_memcmp(WFA_OUI, (paction), 3) ) | |
1030 | { | |
1031 | if( *(paction + 3) == 0x04) //Probe request frame | |
1032 | { | |
1033 | //WFDTDLS: for sigma test, do not setup direct link automatically | |
1034 | ptdlsinfo->dev_discovered = 1; | |
1035 | DBG_871X("recv tunneled probe request frame\n"); | |
1036 | issue_tunneled_probe_rsp(adapter, precv_frame); | |
1037 | } | |
1038 | if( *(paction + 3) == 0x05) //Probe response frame | |
1039 | { | |
1040 | //WFDTDLS: for sigma test, do not setup direct link automatically | |
1041 | ptdlsinfo->dev_discovered = 1; | |
1042 | DBG_871X("recv tunneled probe response frame\n"); | |
1043 | } | |
1044 | } | |
1045 | break; | |
1046 | #endif //CONFIG_WFD | |
1047 | default: | |
1048 | DBG_871X("receive TDLS frame but not supported\n"); | |
1049 | ret=_FAIL; | |
1050 | break; | |
1051 | } | |
1052 | ||
1053 | exit: | |
1054 | return ret; | |
1055 | ||
1056 | } | |
1057 | #endif //CONFIG_TDLS | |
1058 | ||
1059 | void count_rx_stats(_adapter *padapter, union recv_frame *prframe, struct sta_info*sta); | |
1060 | void count_rx_stats(_adapter *padapter, union recv_frame *prframe, struct sta_info*sta) | |
1061 | { | |
1062 | int sz; | |
1063 | struct sta_info *psta = NULL; | |
1064 | struct stainfo_stats *pstats = NULL; | |
1065 | struct rx_pkt_attrib *pattrib = & prframe->u.hdr.attrib; | |
1066 | struct recv_priv *precvpriv = &padapter->recvpriv; | |
1067 | ||
1068 | sz = get_recvframe_len(prframe); | |
1069 | precvpriv->rx_bytes += sz; | |
1070 | ||
1071 | padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++; | |
1072 | ||
1073 | if( (!MacAddr_isBcst(pattrib->dst)) && (!IS_MCAST(pattrib->dst))){ | |
1074 | padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++; | |
1075 | } | |
1076 | ||
1077 | if(sta) | |
1078 | psta = sta; | |
1079 | else | |
1080 | psta = prframe->u.hdr.psta; | |
1081 | ||
1082 | if(psta) | |
1083 | { | |
1084 | pstats = &psta->sta_stats; | |
1085 | ||
1086 | pstats->rx_data_pkts++; | |
1087 | pstats->rx_bytes += sz; | |
1088 | } | |
1089 | ||
1090 | } | |
1091 | ||
1092 | sint sta2sta_data_frame( | |
1093 | _adapter *adapter, | |
1094 | union recv_frame *precv_frame, | |
1095 | struct sta_info**psta | |
1096 | ); | |
1097 | sint sta2sta_data_frame( | |
1098 | _adapter *adapter, | |
1099 | union recv_frame *precv_frame, | |
1100 | struct sta_info**psta | |
1101 | ) | |
1102 | { | |
1103 | u8 *ptr = precv_frame->u.hdr.rx_data; | |
1104 | sint ret = _SUCCESS; | |
1105 | struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; | |
1106 | struct sta_priv *pstapriv = &adapter->stapriv; | |
1107 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; | |
1108 | u8 *mybssid = get_bssid(pmlmepriv); | |
1109 | u8 *myhwaddr = myid(&adapter->eeprompriv); | |
1110 | u8 * sta_addr = NULL; | |
1111 | sint bmcast = IS_MCAST(pattrib->dst); | |
1112 | ||
1113 | #ifdef CONFIG_TDLS | |
1114 | struct tdls_info *ptdlsinfo = &adapter->tdlsinfo; | |
1115 | struct sta_info *ptdls_sta=NULL; | |
1116 | u8 *psnap_type=ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE; | |
1117 | u8 *pframe_body = psnap_type + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN; | |
1118 | #endif //CONFIG_TDLS | |
1119 | ||
1120 | _func_enter_; | |
1121 | ||
1122 | if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) || | |
1123 | (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) | |
1124 | { | |
1125 | ||
1126 | // filter packets that SA is myself or multicast or broadcast | |
1127 | if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)){ | |
1128 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" SA==myself \n")); | |
1129 | ret= _FAIL; | |
1130 | goto exit; | |
1131 | } | |
1132 | ||
1133 | if( (!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast) ){ | |
1134 | ret= _FAIL; | |
1135 | goto exit; | |
1136 | } | |
1137 | ||
1138 | if( _rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || | |
1139 | _rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || | |
1140 | (!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN)) ) { | |
1141 | ret= _FAIL; | |
1142 | goto exit; | |
1143 | } | |
1144 | ||
1145 | sta_addr = pattrib->src; | |
1146 | ||
1147 | } | |
1148 | else if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) | |
1149 | { | |
1150 | #ifdef CONFIG_TDLS | |
1151 | //direct link data transfer | |
1152 | if(ptdlsinfo->setup_state == TDLS_LINKED_STATE){ | |
1153 | ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->src); | |
1154 | if(ptdls_sta==NULL) | |
1155 | { | |
1156 | ret=_FAIL; | |
1157 | goto exit; | |
1158 | } | |
1159 | else if(ptdls_sta->tdls_sta_state&TDLS_LINKED_STATE) | |
1160 | { | |
1161 | //drop QoS-SubType Data, including QoS NULL, excluding QoS-Data | |
1162 | if( (GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE )== WIFI_QOS_DATA_TYPE) | |
1163 | { | |
1164 | if(GetFrameSubType(ptr)&(BIT(4)|BIT(5)|BIT(6))) | |
1165 | { | |
1166 | DBG_871X("drop QoS-Sybtype Data\n"); | |
1167 | ret= _FAIL; | |
1168 | goto exit; | |
1169 | } | |
1170 | } | |
1171 | // filter packets that SA is myself or multicast or broadcast | |
1172 | if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)){ | |
1173 | ret= _FAIL; | |
1174 | goto exit; | |
1175 | } | |
1176 | // da should be for me | |
1177 | if((!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN))&& (!bmcast)) | |
1178 | { | |
1179 | ret= _FAIL; | |
1180 | goto exit; | |
1181 | } | |
1182 | // check BSSID | |
1183 | if( _rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || | |
1184 | _rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || | |
1185 | (!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN)) ) | |
1186 | { | |
1187 | ret= _FAIL; | |
1188 | goto exit; | |
1189 | } | |
1190 | ||
1191 | //process UAPSD tdls sta | |
1192 | process_pwrbit_data(adapter, precv_frame); | |
1193 | ||
1194 | // if NULL-frame, check pwrbit | |
1195 | if ((GetFrameSubType(ptr)) == WIFI_DATA_NULL) | |
1196 | { | |
1197 | //NULL-frame with pwrbit=1, buffer_STA should buffer frames for sleep_STA | |
1198 | if(GetPwrMgt(ptr)) | |
1199 | { | |
1200 | DBG_871X("TDLS: recv peer null frame with pwr bit 1\n"); | |
1201 | ptdls_sta->tdls_sta_state|=TDLS_PEER_SLEEP_STATE; | |
1202 | } | |
1203 | // it would be triggered when we are off channel and receiving NULL DATA | |
1204 | // we can confirm that peer STA is at off channel | |
1205 | else if(ptdls_sta->tdls_sta_state&TDLS_CH_SWITCH_ON_STATE) | |
1206 | { | |
1207 | if((ptdls_sta->tdls_sta_state & TDLS_PEER_AT_OFF_STATE) != TDLS_PEER_AT_OFF_STATE) | |
1208 | { | |
1209 | issue_nulldata_to_TDLS_peer_STA(adapter, ptdls_sta, 0); | |
1210 | ptdls_sta->tdls_sta_state |= TDLS_PEER_AT_OFF_STATE; | |
1211 | On_TDLS_Peer_Traffic_Rsp(adapter, precv_frame); | |
1212 | } | |
1213 | } | |
1214 | ||
1215 | ret= _FAIL; | |
1216 | goto exit; | |
1217 | } | |
1218 | //receive some of all TDLS management frames, process it at ON_TDLS | |
1219 | if((_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_TDLS, 2))){ | |
1220 | ret= OnTDLS(adapter, precv_frame); | |
1221 | goto exit; | |
1222 | } | |
1223 | ||
1224 | } | |
1225 | ||
1226 | sta_addr = pattrib->src; | |
1227 | ||
1228 | } | |
1229 | else | |
1230 | #endif //CONFIG_TDLS | |
1231 | { | |
1232 | // For Station mode, sa and bssid should always be BSSID, and DA is my mac-address | |
1233 | if(!_rtw_memcmp(pattrib->bssid, pattrib->src, ETH_ALEN) ) | |
1234 | { | |
1235 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("bssid != TA under STATION_MODE; drop pkt\n")); | |
1236 | ret= _FAIL; | |
1237 | goto exit; | |
1238 | } | |
1239 | ||
1240 | sta_addr = pattrib->bssid; | |
1241 | } | |
1242 | } | |
1243 | else if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) | |
1244 | { | |
1245 | if (bmcast) | |
1246 | { | |
1247 | // For AP mode, if DA == MCAST, then BSSID should be also MCAST | |
1248 | if (!IS_MCAST(pattrib->bssid)){ | |
1249 | ret= _FAIL; | |
1250 | goto exit; | |
1251 | } | |
1252 | } | |
1253 | else // not mc-frame | |
1254 | { | |
1255 | // For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID | |
1256 | if(!_rtw_memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) { | |
1257 | ret= _FAIL; | |
1258 | goto exit; | |
1259 | } | |
1260 | ||
1261 | sta_addr = pattrib->src; | |
1262 | } | |
1263 | ||
1264 | } | |
1265 | else if(check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) | |
1266 | { | |
1267 | _rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN); | |
1268 | _rtw_memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN); | |
1269 | _rtw_memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN); | |
1270 | _rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); | |
1271 | _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); | |
1272 | ||
1273 | sta_addr = mybssid; | |
1274 | } | |
1275 | else | |
1276 | { | |
1277 | ret = _FAIL; | |
1278 | } | |
1279 | ||
1280 | ||
1281 | ||
1282 | if(bmcast) | |
1283 | *psta = rtw_get_bcmc_stainfo(adapter); | |
1284 | else | |
1285 | *psta = rtw_get_stainfo(pstapriv, sta_addr); // get ap_info | |
1286 | ||
1287 | #ifdef CONFIG_TDLS | |
1288 | if(ptdls_sta != NULL) | |
1289 | *psta = ptdls_sta; | |
1290 | #endif //CONFIG_TDLS | |
1291 | ||
1292 | ||
1293 | if (*psta == NULL) { | |
1294 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("can't get psta under sta2sta_data_frame ; drop pkt\n")); | |
1295 | #ifdef CONFIG_MP_INCLUDED | |
1296 | if(check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) | |
1297 | adapter->mppriv.rx_pktloss++; | |
1298 | #endif | |
1299 | ret= _FAIL; | |
1300 | goto exit; | |
1301 | } | |
1302 | ||
1303 | exit: | |
1304 | _func_exit_; | |
1305 | return ret; | |
1306 | ||
1307 | } | |
1308 | ||
1309 | sint ap2sta_data_frame( | |
1310 | _adapter *adapter, | |
1311 | union recv_frame *precv_frame, | |
1312 | struct sta_info**psta ); | |
1313 | sint ap2sta_data_frame( | |
1314 | _adapter *adapter, | |
1315 | union recv_frame *precv_frame, | |
1316 | struct sta_info**psta ) | |
1317 | { | |
1318 | u8 *ptr = precv_frame->u.hdr.rx_data; | |
1319 | struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; | |
1320 | sint ret = _SUCCESS; | |
1321 | struct sta_priv *pstapriv = &adapter->stapriv; | |
1322 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; | |
1323 | u8 *mybssid = get_bssid(pmlmepriv); | |
1324 | u8 *myhwaddr = myid(&adapter->eeprompriv); | |
1325 | sint bmcast = IS_MCAST(pattrib->dst); | |
1326 | ||
1327 | _func_enter_; | |
1328 | ||
1329 | if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) | |
1330 | && (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE | |
1331 | || check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE ) | |
1332 | ) | |
1333 | { | |
1334 | ||
1335 | // filter packets that SA is myself or multicast or broadcast | |
1336 | if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)){ | |
1337 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" SA==myself \n")); | |
1338 | #ifdef DBG_RX_DROP_FRAME | |
1339 | DBG_871X("DBG_RX_DROP_FRAME %s SA=%x:%x:%x:%x:%x:%x, myhwaddr= %x:%x:%x:%x:%x:%x\n", __FUNCTION__, | |
1340 | pattrib->src[0], pattrib->src[1], pattrib->src[2], | |
1341 | pattrib->src[3], pattrib->src[4], pattrib->src[5], | |
1342 | *(myhwaddr), *(myhwaddr+1), *(myhwaddr+2), | |
1343 | *(myhwaddr+3), *(myhwaddr+4), *(myhwaddr+5)); | |
1344 | #endif | |
1345 | ret= _FAIL; | |
1346 | goto exit; | |
1347 | } | |
1348 | ||
1349 | // da should be for me | |
1350 | if((!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN))&& (!bmcast)) | |
1351 | { | |
1352 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_, | |
1353 | (" ap2sta_data_frame: compare DA fail; DA="MAC_FMT"\n", MAC_ARG(pattrib->dst))); | |
1354 | #ifdef DBG_RX_DROP_FRAME | |
1355 | DBG_871X("DBG_RX_DROP_FRAME %s DA="MAC_FMT"\n", __func__, MAC_ARG(pattrib->dst)); | |
1356 | #endif | |
1357 | ret= _FAIL; | |
1358 | goto exit; | |
1359 | } | |
1360 | ||
1361 | ||
1362 | // check BSSID | |
1363 | if( _rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || | |
1364 | _rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) || | |
1365 | (!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN)) ) | |
1366 | { | |
1367 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_, | |
1368 | (" ap2sta_data_frame: compare BSSID fail ; BSSID="MAC_FMT"\n", MAC_ARG(pattrib->bssid))); | |
1369 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("mybssid="MAC_FMT"\n", MAC_ARG(mybssid))); | |
1370 | #ifdef DBG_RX_DROP_FRAME | |
1371 | DBG_871X("DBG_RX_DROP_FRAME %s BSSID="MAC_FMT", mybssid="MAC_FMT"\n", | |
1372 | __FUNCTION__, MAC_ARG(pattrib->bssid), MAC_ARG(mybssid)); | |
1373 | DBG_871X( "this adapter = %d, buddy adapter = %d\n", adapter->adapter_type, adapter->pbuddy_adapter->adapter_type ); | |
1374 | #endif | |
1375 | ||
1376 | if(!bmcast) | |
1377 | { | |
1378 | DBG_871X("issue_deauth to the nonassociated ap=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->bssid)); | |
1379 | issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); | |
1380 | } | |
1381 | ||
1382 | ret= _FAIL; | |
1383 | goto exit; | |
1384 | } | |
1385 | ||
1386 | if(bmcast) | |
1387 | *psta = rtw_get_bcmc_stainfo(adapter); | |
1388 | else | |
1389 | *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); // get ap_info | |
1390 | ||
1391 | if (*psta == NULL) { | |
1392 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("ap2sta: can't get psta under STATION_MODE ; drop pkt\n")); | |
1393 | #ifdef DBG_RX_DROP_FRAME | |
1394 | DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under STATION_MODE ; drop pkt\n", __FUNCTION__); | |
1395 | #endif | |
1396 | ret= _FAIL; | |
1397 | goto exit; | |
1398 | } | |
1399 | ||
1400 | if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) { | |
1401 | } | |
1402 | ||
1403 | if (GetFrameSubType(ptr) & BIT(6)) { | |
1404 | /* No data, will not indicate to upper layer, temporily count it here */ | |
1405 | count_rx_stats(adapter, precv_frame, *psta); | |
1406 | ret = RTW_RX_HANDLED; | |
1407 | goto exit; | |
1408 | } | |
1409 | ||
1410 | } | |
1411 | else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) && | |
1412 | (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) ) | |
1413 | { | |
1414 | _rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN); | |
1415 | _rtw_memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN); | |
1416 | _rtw_memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN); | |
1417 | _rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); | |
1418 | _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN); | |
1419 | ||
1420 | // | |
1421 | _rtw_memcpy(pattrib->bssid, mybssid, ETH_ALEN); | |
1422 | ||
1423 | ||
1424 | *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); // get sta_info | |
1425 | if (*psta == NULL) { | |
1426 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("can't get psta under MP_MODE ; drop pkt\n")); | |
1427 | #ifdef DBG_RX_DROP_FRAME | |
1428 | DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under WIFI_MP_STATE ; drop pkt\n", __FUNCTION__); | |
1429 | #endif | |
1430 | ret= _FAIL; | |
1431 | goto exit; | |
1432 | } | |
1433 | ||
1434 | ||
1435 | } | |
1436 | else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) | |
1437 | { | |
1438 | /* Special case */ | |
1439 | ret = RTW_RX_HANDLED; | |
1440 | goto exit; | |
1441 | } | |
1442 | else | |
1443 | { | |
1444 | if(_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN)&& (!bmcast)) | |
1445 | { | |
1446 | *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); // get sta_info | |
1447 | if (*psta == NULL) | |
1448 | { | |
1449 | DBG_871X("issue_deauth to the ap=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->bssid)); | |
1450 | ||
1451 | issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); | |
1452 | } | |
1453 | } | |
1454 | ||
1455 | ret = _FAIL; | |
1456 | #ifdef DBG_RX_DROP_FRAME | |
1457 | DBG_871X("DBG_RX_DROP_FRAME %s fw_state:0x%x\n", __FUNCTION__, get_fwstate(pmlmepriv)); | |
1458 | #endif | |
1459 | } | |
1460 | ||
1461 | exit: | |
1462 | ||
1463 | _func_exit_; | |
1464 | ||
1465 | return ret; | |
1466 | ||
1467 | } | |
1468 | ||
1469 | sint sta2ap_data_frame( | |
1470 | _adapter *adapter, | |
1471 | union recv_frame *precv_frame, | |
1472 | struct sta_info**psta ); | |
1473 | sint sta2ap_data_frame( | |
1474 | _adapter *adapter, | |
1475 | union recv_frame *precv_frame, | |
1476 | struct sta_info**psta ) | |
1477 | { | |
1478 | u8 *ptr = precv_frame->u.hdr.rx_data; | |
1479 | struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; | |
1480 | struct sta_priv *pstapriv = &adapter->stapriv; | |
1481 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; | |
1482 | unsigned char *mybssid = get_bssid(pmlmepriv); | |
1483 | sint ret=_SUCCESS; | |
1484 | ||
1485 | _func_enter_; | |
1486 | ||
1487 | if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) | |
1488 | { | |
1489 | //For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR | |
1490 | if(!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN)) | |
1491 | { | |
1492 | ret= _FAIL; | |
1493 | goto exit; | |
1494 | } | |
1495 | ||
1496 | *psta = rtw_get_stainfo(pstapriv, pattrib->src); | |
1497 | if (*psta == NULL) | |
1498 | { | |
1499 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("can't get psta under AP_MODE; drop pkt\n")); | |
1500 | DBG_871X("issue_deauth to sta=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src)); | |
1501 | ||
1502 | issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); | |
1503 | ||
1504 | ret = RTW_RX_HANDLED; | |
1505 | goto exit; | |
1506 | } | |
1507 | ||
1508 | process_pwrbit_data(adapter, precv_frame); | |
1509 | ||
1510 | if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) { | |
1511 | process_wmmps_data(adapter, precv_frame); | |
1512 | } | |
1513 | ||
1514 | if (GetFrameSubType(ptr) & BIT(6)) { | |
1515 | /* No data, will not indicate to upper layer, temporily count it here */ | |
1516 | count_rx_stats(adapter, precv_frame, *psta); | |
1517 | ret = RTW_RX_HANDLED; | |
1518 | goto exit; | |
1519 | } | |
1520 | } | |
1521 | else { | |
1522 | u8 *myhwaddr = myid(&adapter->eeprompriv); | |
1523 | if (!_rtw_memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) { | |
1524 | ret = RTW_RX_HANDLED; | |
1525 | goto exit; | |
1526 | } | |
1527 | DBG_871X("issue_deauth to sta=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src)); | |
1528 | issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); | |
1529 | ret = RTW_RX_HANDLED; | |
1530 | goto exit; | |
1531 | } | |
1532 | ||
1533 | exit: | |
1534 | ||
1535 | _func_exit_; | |
1536 | ||
1537 | return ret; | |
1538 | ||
1539 | } | |
1540 | ||
1541 | sint validate_recv_ctrl_frame(_adapter *padapter, union recv_frame *precv_frame); | |
1542 | sint validate_recv_ctrl_frame(_adapter *padapter, union recv_frame *precv_frame) | |
1543 | { | |
1544 | #ifdef CONFIG_AP_MODE | |
1545 | struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; | |
1546 | struct sta_priv *pstapriv = &padapter->stapriv; | |
1547 | u8 *pframe = precv_frame->u.hdr.rx_data; | |
1548 | //uint len = precv_frame->u.hdr.len; | |
1549 | ||
1550 | //DBG_871X("+validate_recv_ctrl_frame\n"); | |
1551 | ||
1552 | if (GetFrameType(pframe) != WIFI_CTRL_TYPE) | |
1553 | { | |
1554 | return _FAIL; | |
1555 | } | |
1556 | ||
1557 | //receive the frames that ra(a1) is my address | |
1558 | if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN)) | |
1559 | { | |
1560 | return _FAIL; | |
1561 | } | |
1562 | ||
1563 | //only handle ps-poll | |
1564 | if(GetFrameSubType(pframe) == WIFI_PSPOLL) | |
1565 | { | |
1566 | u16 aid; | |
1567 | u8 wmmps_ac=0; | |
1568 | struct sta_info *psta=NULL; | |
1569 | ||
1570 | aid = GetAid(pframe); | |
1571 | psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); | |
1572 | ||
1573 | if((psta==NULL) || (psta->aid!=aid)) | |
1574 | { | |
1575 | return _FAIL; | |
1576 | } | |
1577 | ||
1578 | //for rx pkt statistics | |
1579 | psta->sta_stats.rx_ctrl_pkts++; | |
1580 | ||
1581 | switch(pattrib->priority) | |
1582 | { | |
1583 | case 1: | |
1584 | case 2: | |
1585 | wmmps_ac = psta->uapsd_bk&BIT(0); | |
1586 | break; | |
1587 | case 4: | |
1588 | case 5: | |
1589 | wmmps_ac = psta->uapsd_vi&BIT(0); | |
1590 | break; | |
1591 | case 6: | |
1592 | case 7: | |
1593 | wmmps_ac = psta->uapsd_vo&BIT(0); | |
1594 | break; | |
1595 | case 0: | |
1596 | case 3: | |
1597 | default: | |
1598 | wmmps_ac = psta->uapsd_be&BIT(0); | |
1599 | break; | |
1600 | } | |
1601 | ||
1602 | if(wmmps_ac) | |
1603 | return _FAIL; | |
1604 | ||
1605 | if(psta->state & WIFI_STA_ALIVE_CHK_STATE) | |
1606 | { | |
1607 | DBG_871X("%s alive check-rx ps-poll\n", __func__); | |
1608 | psta->expire_to = pstapriv->expire_to; | |
1609 | psta->state ^= WIFI_STA_ALIVE_CHK_STATE; | |
1610 | } | |
1611 | ||
1612 | if((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) | |
1613 | { | |
1614 | _irqL irqL; | |
1615 | _list *xmitframe_plist, *xmitframe_phead; | |
1616 | struct xmit_frame *pxmitframe=NULL; | |
1617 | struct xmit_priv *pxmitpriv = &padapter->xmitpriv; | |
1618 | ||
1619 | //_enter_critical_bh(&psta->sleep_q.lock, &irqL); | |
1620 | _enter_critical_bh(&pxmitpriv->lock, &irqL); | |
1621 | ||
1622 | xmitframe_phead = get_list_head(&psta->sleep_q); | |
1623 | xmitframe_plist = get_next(xmitframe_phead); | |
1624 | ||
1625 | if ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) | |
1626 | { | |
1627 | pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list); | |
1628 | ||
1629 | xmitframe_plist = get_next(xmitframe_plist); | |
1630 | ||
1631 | rtw_list_delete(&pxmitframe->list); | |
1632 | ||
1633 | psta->sleepq_len--; | |
1634 | ||
1635 | if(psta->sleepq_len>0) | |
1636 | pxmitframe->attrib.mdata = 1; | |
1637 | else | |
1638 | pxmitframe->attrib.mdata = 0; | |
1639 | ||
1640 | pxmitframe->attrib.triggered = 1; | |
1641 | ||
1642 | //DBG_871X("handling ps-poll, q_len=%d, tim=%x\n", psta->sleepq_len, pstapriv->tim_bitmap); | |
1643 | ||
1644 | #if 0 | |
1645 | _exit_critical_bh(&psta->sleep_q.lock, &irqL); | |
1646 | if(rtw_hal_xmit(padapter, pxmitframe) == _TRUE) | |
1647 | { | |
1648 | rtw_os_xmit_complete(padapter, pxmitframe); | |
1649 | } | |
1650 | _enter_critical_bh(&psta->sleep_q.lock, &irqL); | |
1651 | #endif | |
1652 | rtw_hal_xmitframe_enqueue(padapter, pxmitframe); | |
1653 | ||
1654 | if(psta->sleepq_len==0) | |
1655 | { | |
1656 | pstapriv->tim_bitmap &= ~BIT(psta->aid); | |
1657 | ||
1658 | //DBG_871X("after handling ps-poll, tim=%x\n", pstapriv->tim_bitmap); | |
1659 | ||
1660 | //upate BCN for TIM IE | |
1661 | //update_BCNTIM(padapter); | |
1662 | update_beacon(padapter, _TIM_IE_, NULL, _FALSE); | |
1663 | } | |
1664 | ||
1665 | //_exit_critical_bh(&psta->sleep_q.lock, &irqL); | |
1666 | _exit_critical_bh(&pxmitpriv->lock, &irqL); | |
1667 | ||
1668 | } | |
1669 | else | |
1670 | { | |
1671 | //_exit_critical_bh(&psta->sleep_q.lock, &irqL); | |
1672 | _exit_critical_bh(&pxmitpriv->lock, &irqL); | |
1673 | ||
1674 | //DBG_871X("no buffered packets to xmit\n"); | |
1675 | if(pstapriv->tim_bitmap&BIT(psta->aid)) | |
1676 | { | |
1677 | if(psta->sleepq_len==0) | |
1678 | { | |
1679 | DBG_871X("no buffered packets to xmit\n"); | |
1680 | ||
1681 | //issue nulldata with More data bit = 0 to indicate we have no buffered packets | |
1682 | issue_nulldata(padapter, psta->hwaddr, 0, 0, 0); | |
1683 | } | |
1684 | else | |
1685 | { | |
1686 | DBG_871X("error!psta->sleepq_len=%d\n", psta->sleepq_len); | |
1687 | psta->sleepq_len=0; | |
1688 | } | |
1689 | ||
1690 | pstapriv->tim_bitmap &= ~BIT(psta->aid); | |
1691 | ||
1692 | //upate BCN for TIM IE | |
1693 | //update_BCNTIM(padapter); | |
1694 | update_beacon(padapter, _TIM_IE_, NULL, _FALSE); | |
1695 | } | |
1696 | ||
1697 | } | |
1698 | ||
1699 | } | |
1700 | ||
1701 | } | |
1702 | ||
1703 | #endif | |
1704 | ||
1705 | return _FAIL; | |
1706 | ||
1707 | } | |
1708 | ||
1709 | union recv_frame* recvframe_chk_defrag(PADAPTER padapter, union recv_frame *precv_frame); | |
1710 | sint validate_recv_mgnt_frame(PADAPTER padapter, union recv_frame *precv_frame); | |
1711 | sint validate_recv_mgnt_frame(PADAPTER padapter, union recv_frame *precv_frame) | |
1712 | { | |
1713 | //struct mlme_priv *pmlmepriv = &adapter->mlmepriv; | |
1714 | ||
1715 | RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+validate_recv_mgnt_frame\n")); | |
1716 | ||
1717 | #if 0 | |
1718 | if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) | |
1719 | { | |
1720 | #ifdef CONFIG_NATIVEAP_MLME | |
1721 | mgt_dispatcher(padapter, precv_frame); | |
1722 | #else | |
1723 | rtw_hostapd_mlme_rx(padapter, precv_frame); | |
1724 | #endif | |
1725 | } | |
1726 | else | |
1727 | { | |
1728 | mgt_dispatcher(padapter, precv_frame); | |
1729 | } | |
1730 | #endif | |
1731 | ||
1732 | precv_frame = recvframe_chk_defrag(padapter, precv_frame); | |
1733 | if (precv_frame == NULL) { | |
1734 | RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,("%s: fragment packet\n",__FUNCTION__)); | |
1735 | return _SUCCESS; | |
1736 | } | |
1737 | ||
1738 | { | |
1739 | //for rx pkt statistics | |
1740 | struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(precv_frame->u.hdr.rx_data)); | |
1741 | if (psta) { | |
1742 | psta->sta_stats.rx_mgnt_pkts++; | |
1743 | if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_BEACON) | |
1744 | psta->sta_stats.rx_beacon_pkts++; | |
1745 | else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBEREQ) | |
1746 | psta->sta_stats.rx_probereq_pkts++; | |
1747 | else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBERSP) { | |
1748 | if (_rtw_memcmp(padapter->eeprompriv.mac_addr, GetAddr1Ptr(precv_frame->u.hdr.rx_data), ETH_ALEN) == _TRUE) | |
1749 | psta->sta_stats.rx_probersp_pkts++; | |
1750 | else if (is_broadcast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data)) | |
1751 | || is_multicast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data))) | |
1752 | psta->sta_stats.rx_probersp_bm_pkts++; | |
1753 | else | |
1754 | psta->sta_stats.rx_probersp_uo_pkts++; | |
1755 | } | |
1756 | } | |
1757 | } | |
1758 | ||
1759 | #ifdef CONFIG_INTEL_PROXIM | |
1760 | if(padapter->proximity.proxim_on==_TRUE) | |
1761 | { | |
1762 | struct rx_pkt_attrib * pattrib=&precv_frame->u.hdr.attrib; | |
1763 | struct recv_stat* prxstat=( struct recv_stat * ) precv_frame->u.hdr.rx_head ; | |
1764 | u8 * pda,*psa,*pbssid,*ptr; | |
1765 | ptr=precv_frame->u.hdr.rx_data; | |
1766 | pda = get_da(ptr); | |
1767 | psa = get_sa(ptr); | |
1768 | pbssid = get_hdr_bssid(ptr); | |
1769 | ||
1770 | ||
1771 | _rtw_memcpy(pattrib->dst, pda, ETH_ALEN); | |
1772 | _rtw_memcpy(pattrib->src, psa, ETH_ALEN); | |
1773 | ||
1774 | _rtw_memcpy(pattrib->bssid, pbssid, ETH_ALEN); | |
1775 | ||
1776 | switch(pattrib->to_fr_ds) | |
1777 | { | |
1778 | case 0: | |
1779 | _rtw_memcpy(pattrib->ra, pda, ETH_ALEN); | |
1780 | _rtw_memcpy(pattrib->ta, psa, ETH_ALEN); | |
1781 | break; | |
1782 | ||
1783 | case 1: | |
1784 | _rtw_memcpy(pattrib->ra, pda, ETH_ALEN); | |
1785 | _rtw_memcpy(pattrib->ta, pbssid, ETH_ALEN); | |
1786 | break; | |
1787 | ||
1788 | case 2: | |
1789 | _rtw_memcpy(pattrib->ra, pbssid, ETH_ALEN); | |
1790 | _rtw_memcpy(pattrib->ta, psa, ETH_ALEN); | |
1791 | break; | |
1792 | ||
1793 | case 3: | |
1794 | _rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN); | |
1795 | _rtw_memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN); | |
1796 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" case 3\n")); | |
1797 | break; | |
1798 | ||
1799 | default: | |
1800 | break; | |
1801 | ||
1802 | } | |
1803 | pattrib->priority=0; | |
1804 | pattrib->hdrlen = pattrib->to_fr_ds==3 ? 30 : 24; | |
1805 | ||
1806 | padapter->proximity.proxim_rx(padapter,precv_frame); | |
1807 | } | |
1808 | #endif | |
1809 | mgt_dispatcher(padapter, precv_frame); | |
1810 | ||
1811 | return _SUCCESS; | |
1812 | ||
1813 | } | |
1814 | ||
1815 | sint validate_recv_data_frame(_adapter *adapter, union recv_frame *precv_frame); | |
1816 | sint validate_recv_data_frame(_adapter *adapter, union recv_frame *precv_frame) | |
1817 | { | |
1818 | u8 bretry; | |
1819 | u8 *psa, *pda, *pbssid; | |
1820 | struct sta_info *psta = NULL; | |
1821 | u8 *ptr = precv_frame->u.hdr.rx_data; | |
1822 | struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; | |
1823 | struct security_priv *psecuritypriv = &adapter->securitypriv; | |
1824 | sint ret = _SUCCESS; | |
1825 | #ifdef CONFIG_TDLS | |
1826 | struct tdls_info *ptdlsinfo = &adapter->tdlsinfo; | |
1827 | #endif //CONFIG_TDLS | |
1828 | ||
1829 | _func_enter_; | |
1830 | ||
1831 | bretry = GetRetry(ptr); | |
1832 | pda = get_da(ptr); | |
1833 | psa = get_sa(ptr); | |
1834 | pbssid = get_hdr_bssid(ptr); | |
1835 | ||
1836 | if(pbssid == NULL){ | |
1837 | ret= _FAIL; | |
1838 | goto exit; | |
1839 | } | |
1840 | ||
1841 | _rtw_memcpy(pattrib->dst, pda, ETH_ALEN); | |
1842 | _rtw_memcpy(pattrib->src, psa, ETH_ALEN); | |
1843 | ||
1844 | _rtw_memcpy(pattrib->bssid, pbssid, ETH_ALEN); | |
1845 | ||
1846 | switch(pattrib->to_fr_ds) | |
1847 | { | |
1848 | case 0: | |
1849 | _rtw_memcpy(pattrib->ra, pda, ETH_ALEN); | |
1850 | _rtw_memcpy(pattrib->ta, psa, ETH_ALEN); | |
1851 | ret = sta2sta_data_frame(adapter, precv_frame, &psta); | |
1852 | break; | |
1853 | ||
1854 | case 1: | |
1855 | _rtw_memcpy(pattrib->ra, pda, ETH_ALEN); | |
1856 | _rtw_memcpy(pattrib->ta, pbssid, ETH_ALEN); | |
1857 | ret = ap2sta_data_frame(adapter, precv_frame, &psta); | |
1858 | break; | |
1859 | ||
1860 | case 2: | |
1861 | _rtw_memcpy(pattrib->ra, pbssid, ETH_ALEN); | |
1862 | _rtw_memcpy(pattrib->ta, psa, ETH_ALEN); | |
1863 | ret = sta2ap_data_frame(adapter, precv_frame, &psta); | |
1864 | break; | |
1865 | ||
1866 | case 3: | |
1867 | _rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN); | |
1868 | _rtw_memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN); | |
1869 | ret =_FAIL; | |
1870 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" case 3\n")); | |
1871 | break; | |
1872 | ||
1873 | default: | |
1874 | ret =_FAIL; | |
1875 | break; | |
1876 | ||
1877 | } | |
1878 | ||
1879 | if(ret ==_FAIL){ | |
1880 | #ifdef DBG_RX_DROP_FRAME | |
1881 | DBG_871X("DBG_RX_DROP_FRAME %s case:%d, res:%d\n", __FUNCTION__, pattrib->to_fr_ds, ret); | |
1882 | #endif | |
1883 | goto exit; | |
1884 | } else if (ret == RTW_RX_HANDLED) { | |
1885 | goto exit; | |
1886 | } | |
1887 | ||
1888 | ||
1889 | if(psta==NULL){ | |
1890 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" after to_fr_ds_chk; psta==NULL \n")); | |
1891 | ret= _FAIL; | |
1892 | goto exit; | |
1893 | } | |
1894 | ||
1895 | //psta->rssi = prxcmd->rssi; | |
1896 | //psta->signal_quality= prxcmd->sq; | |
1897 | precv_frame->u.hdr.psta = psta; | |
1898 | ||
1899 | ||
1900 | pattrib->amsdu=0; | |
1901 | pattrib->ack_policy = 0; | |
1902 | //parsing QC field | |
1903 | if(pattrib->qos == 1) | |
1904 | { | |
1905 | pattrib->priority = GetPriority((ptr + 24)); | |
1906 | pattrib->ack_policy = GetAckpolicy((ptr + 24)); | |
1907 | pattrib->amsdu = GetAMsdu((ptr + 24)); | |
1908 | pattrib->hdrlen = pattrib->to_fr_ds==3 ? 32 : 26; | |
1909 | ||
1910 | if(pattrib->priority!=0 && pattrib->priority!=3) | |
1911 | { | |
1912 | adapter->recvpriv.bIsAnyNonBEPkts = _TRUE; | |
1913 | } | |
1914 | } | |
1915 | else | |
1916 | { | |
1917 | pattrib->priority=0; | |
1918 | pattrib->hdrlen = pattrib->to_fr_ds==3 ? 30 : 24; | |
1919 | } | |
1920 | ||
1921 | ||
1922 | if(pattrib->order)//HT-CTRL 11n | |
1923 | { | |
1924 | pattrib->hdrlen += 4; | |
1925 | } | |
1926 | ||
1927 | precv_frame->u.hdr.preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority]; | |
1928 | ||
1929 | // decache, drop duplicate recv packets | |
1930 | if(recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == _FAIL) | |
1931 | { | |
1932 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("decache : drop pkt\n")); | |
1933 | ret= _FAIL; | |
1934 | goto exit; | |
1935 | } | |
1936 | ||
1937 | #if 0 | |
1938 | if(psta->tdls_sta_state & TDLS_LINKED_STATE ) | |
1939 | { | |
1940 | if(psta->dot118021XPrivacy==_AES_) | |
1941 | pattrib->encrypt=psta->dot118021XPrivacy; | |
1942 | } | |
1943 | #endif //CONFIG_TDLS | |
1944 | ||
1945 | if(pattrib->privacy){ | |
1946 | ||
1947 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("validate_recv_data_frame:pattrib->privacy=%x\n", pattrib->privacy)); | |
1948 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n ^^^^^^^^^^^IS_MCAST(pattrib->ra(0x%02x))=%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0],IS_MCAST(pattrib->ra))); | |
1949 | ||
1950 | #ifdef CONFIG_TDLS | |
1951 | if((psta->tdls_sta_state & TDLS_LINKED_STATE) && (psta->dot118021XPrivacy==_AES_)) | |
1952 | { | |
1953 | pattrib->encrypt=psta->dot118021XPrivacy; | |
1954 | } | |
1955 | else | |
1956 | #endif //CONFIG_TDLS | |
1957 | GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, IS_MCAST(pattrib->ra)); | |
1958 | ||
1959 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n pattrib->encrypt=%d\n",pattrib->encrypt)); | |
1960 | ||
1961 | SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt); | |
1962 | } | |
1963 | else | |
1964 | { | |
1965 | pattrib->encrypt = 0; | |
1966 | pattrib->iv_len = pattrib->icv_len = 0; | |
1967 | } | |
1968 | ||
1969 | exit: | |
1970 | ||
1971 | _func_exit_; | |
1972 | ||
1973 | return ret; | |
1974 | } | |
1975 | ||
1976 | #ifdef CONFIG_IEEE80211W | |
1977 | static sint validate_80211w_mgmt(_adapter *adapter, union recv_frame *precv_frame) | |
1978 | { | |
1979 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; | |
1980 | struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; | |
1981 | u8 *ptr = precv_frame->u.hdr.rx_data; | |
1982 | u8 type; | |
1983 | u8 subtype; | |
1984 | ||
1985 | type = GetFrameType(ptr); | |
1986 | subtype = GetFrameSubType(ptr); //bit(7)~bit(2) | |
1987 | ||
1988 | //only support station mode | |
1989 | if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) | |
1990 | && adapter->securitypriv.binstallBIPkey == _TRUE) | |
1991 | { | |
1992 | //unicast management frame decrypt | |
1993 | if(pattrib->privacy && !(IS_MCAST(GetAddr1Ptr(ptr))) && | |
1994 | (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || subtype == WIFI_ACTION)) | |
1995 | { | |
1996 | u8 *ppp, *mgmt_DATA; | |
1997 | u32 data_len=0; | |
1998 | ppp = GetAddr2Ptr(ptr); | |
1999 | ||
2000 | pattrib->bdecrypted = 0; | |
2001 | pattrib->encrypt = _AES_; | |
2002 | pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr); | |
2003 | //set iv and icv length | |
2004 | SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt); | |
2005 | _rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN); | |
2006 | _rtw_memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN); | |
2007 | //actual management data frame body | |
2008 | data_len = pattrib->pkt_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; | |
2009 | mgmt_DATA = rtw_zmalloc(data_len); | |
2010 | if(mgmt_DATA == NULL) | |
2011 | { | |
2012 | DBG_871X("%s mgmt allocate fail !!!!!!!!!\n", __FUNCTION__); | |
2013 | goto validate_80211w_fail; | |
2014 | } | |
2015 | /*//dump the packet content before decrypt | |
2016 | { | |
2017 | int pp; | |
2018 | printk("pattrib->pktlen = %d =>", pattrib->pkt_len); | |
2019 | for(pp=0;pp< pattrib->pkt_len; pp++) | |
2020 | printk(" %02x ", ptr[pp]); | |
2021 | printk("\n"); | |
2022 | }*/ | |
2023 | ||
2024 | precv_frame = decryptor(adapter, precv_frame); | |
2025 | //save actual management data frame body | |
2026 | _rtw_memcpy(mgmt_DATA, ptr+pattrib->hdrlen+pattrib->iv_len, data_len); | |
2027 | //overwrite the iv field | |
2028 | _rtw_memcpy(ptr+pattrib->hdrlen, mgmt_DATA, data_len); | |
2029 | //remove the iv and icv length | |
2030 | pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len; | |
2031 | rtw_mfree(mgmt_DATA, data_len); | |
2032 | /*//print packet content after decryption | |
2033 | { | |
2034 | int pp; | |
2035 | printk("after decryption pattrib->pktlen = %d @@=>", pattrib->pkt_len); | |
2036 | for(pp=0;pp< pattrib->pkt_len; pp++) | |
2037 | printk(" %02x ", ptr[pp]); | |
2038 | printk("\n"); | |
2039 | }*/ | |
2040 | if(!precv_frame) | |
2041 | { | |
2042 | DBG_871X("%s mgmt descrypt fail !!!!!!!!!\n", __FUNCTION__); | |
2043 | goto validate_80211w_fail; | |
2044 | } | |
2045 | } | |
2046 | else if(IS_MCAST(GetAddr1Ptr(ptr)) && | |
2047 | (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)) | |
2048 | { | |
2049 | sint BIP_ret = _SUCCESS; | |
2050 | //verify BIP MME IE of broadcast/multicast de-auth/disassoc packet | |
2051 | BIP_ret = rtw_BIP_verify(adapter, (u8 * )precv_frame); | |
2052 | if(BIP_ret == _FAIL) | |
2053 | { | |
2054 | //DBG_871X("802.11w BIP verify fail\n"); | |
2055 | goto validate_80211w_fail; | |
2056 | } | |
2057 | else if(BIP_ret == RTW_RX_HANDLED) | |
2058 | { | |
2059 | //DBG_871X("802.11w recv none protected packet\n"); | |
2060 | //issue sa query request | |
2061 | issue_action_SA_Query(adapter, NULL, 0, 0); | |
2062 | goto validate_80211w_fail; | |
2063 | } | |
2064 | }//802.11w protect | |
2065 | else | |
2066 | { | |
2067 | if(subtype == WIFI_ACTION) | |
2068 | { | |
2069 | //according 802.11-2012 standard, these five types are not robust types | |
2070 | if( ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_PUBLIC && | |
2071 | ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_HT && | |
2072 | ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_UNPROTECTED_WNM && | |
2073 | ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_SELF_PROTECTED && | |
2074 | ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_P2P) | |
2075 | { | |
2076 | DBG_871X("action frame category=%d should robust\n", ptr[WLAN_HDR_A3_LEN]); | |
2077 | goto validate_80211w_fail; | |
2078 | } | |
2079 | } | |
2080 | else if(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC) | |
2081 | { | |
2082 | DBG_871X("802.11w recv none protected packet\n"); | |
2083 | //issue sa query request | |
2084 | issue_action_SA_Query(adapter, NULL, 0, 0); | |
2085 | goto validate_80211w_fail; | |
2086 | } | |
2087 | } | |
2088 | } | |
2089 | return _SUCCESS; | |
2090 | ||
2091 | validate_80211w_fail: | |
2092 | return _FAIL; | |
2093 | ||
2094 | } | |
2095 | #endif //CONFIG_IEEE80211W | |
2096 | ||
2097 | sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame); | |
2098 | sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame) | |
2099 | { | |
2100 | //shall check frame subtype, to / from ds, da, bssid | |
2101 | ||
2102 | //then call check if rx seq/frag. duplicated. | |
2103 | ||
2104 | u8 type; | |
2105 | u8 subtype; | |
2106 | sint retval = _SUCCESS; | |
2107 | ||
2108 | struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib; | |
2109 | ||
2110 | u8 *ptr = precv_frame->u.hdr.rx_data; | |
2111 | u8 ver =(unsigned char) (*ptr)&0x3 ; | |
2112 | #ifdef CONFIG_FIND_BEST_CHANNEL | |
2113 | struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv; | |
2114 | #endif | |
2115 | ||
2116 | #ifdef CONFIG_TDLS | |
2117 | struct tdls_info *ptdlsinfo = &adapter->tdlsinfo; | |
2118 | #endif //CONFIG_TDLS | |
2119 | ||
2120 | _func_enter_; | |
2121 | ||
2122 | ||
2123 | #ifdef CONFIG_FIND_BEST_CHANNEL | |
2124 | if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { | |
2125 | int ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, rtw_get_oper_ch(adapter)); | |
2126 | if (ch_set_idx >= 0) | |
2127 | pmlmeext->channel_set[ch_set_idx].rx_count++; | |
2128 | } | |
2129 | #endif | |
2130 | ||
2131 | #ifdef CONFIG_TDLS | |
2132 | if(ptdlsinfo->ch_sensing==1 && ptdlsinfo->cur_channel !=0){ | |
2133 | ptdlsinfo->collect_pkt_num[ptdlsinfo->cur_channel-1]++; | |
2134 | } | |
2135 | #endif //CONFIG_TDLS | |
2136 | ||
2137 | #ifdef RTK_DMP_PLATFORM | |
2138 | if ( 0 ) | |
2139 | { | |
2140 | DBG_871X("++\n"); | |
2141 | { | |
2142 | int i; | |
2143 | for(i=0; i<64;i=i+8) | |
2144 | DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:", *(ptr+i), | |
2145 | *(ptr+i+1), *(ptr+i+2) ,*(ptr+i+3) ,*(ptr+i+4),*(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); | |
2146 | ||
2147 | } | |
2148 | DBG_871X("--\n"); | |
2149 | } | |
2150 | #endif //RTK_DMP_PLATFORM | |
2151 | ||
2152 | //add version chk | |
2153 | if(ver!=0){ | |
2154 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_data_frame fail! (ver!=0)\n")); | |
2155 | retval= _FAIL; | |
2156 | goto exit; | |
2157 | } | |
2158 | ||
2159 | type = GetFrameType(ptr); | |
2160 | subtype = GetFrameSubType(ptr); //bit(7)~bit(2) | |
2161 | ||
2162 | pattrib->to_fr_ds = get_tofr_ds(ptr); | |
2163 | ||
2164 | pattrib->frag_num = GetFragNum(ptr); | |
2165 | pattrib->seq_num = GetSequence(ptr); | |
2166 | ||
2167 | pattrib->pw_save = GetPwrMgt(ptr); | |
2168 | pattrib->mfrag = GetMFrag(ptr); | |
2169 | pattrib->mdata = GetMData(ptr); | |
2170 | pattrib->privacy = GetPrivacy(ptr); | |
2171 | pattrib->order = GetOrder(ptr); | |
2172 | #if 0 //for debug | |
2173 | ||
2174 | if(pHalData->bDumpRxPkt ==1){ | |
2175 | int i; | |
2176 | DBG_871X("############################# \n"); | |
2177 | ||
2178 | for(i=0; i<64;i=i+8) | |
2179 | DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i), | |
2180 | *(ptr+i+1), *(ptr+i+2) ,*(ptr+i+3) ,*(ptr+i+4),*(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); | |
2181 | DBG_871X("############################# \n"); | |
2182 | } | |
2183 | else if(pHalData->bDumpRxPkt ==2){ | |
2184 | if(type== WIFI_MGT_TYPE){ | |
2185 | int i; | |
2186 | DBG_871X("############################# \n"); | |
2187 | ||
2188 | for(i=0; i<64;i=i+8) | |
2189 | DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i), | |
2190 | *(ptr+i+1), *(ptr+i+2) ,*(ptr+i+3) ,*(ptr+i+4),*(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); | |
2191 | DBG_871X("############################# \n"); | |
2192 | } | |
2193 | } | |
2194 | else if(pHalData->bDumpRxPkt ==3){ | |
2195 | if(type== WIFI_DATA_TYPE){ | |
2196 | int i; | |
2197 | DBG_871X("############################# \n"); | |
2198 | ||
2199 | for(i=0; i<64;i=i+8) | |
2200 | DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i), | |
2201 | *(ptr+i+1), *(ptr+i+2) ,*(ptr+i+3) ,*(ptr+i+4),*(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); | |
2202 | DBG_871X("############################# \n"); | |
2203 | } | |
2204 | } | |
2205 | ||
2206 | #endif | |
2207 | switch (type) | |
2208 | { | |
2209 | case WIFI_MGT_TYPE: //mgnt | |
2210 | #ifdef CONFIG_IEEE80211W | |
2211 | if(validate_80211w_mgmt(adapter, precv_frame) == _FAIL) | |
2212 | { | |
2213 | retval = _FAIL; | |
2214 | break; | |
2215 | } | |
2216 | #endif //CONFIG_IEEE80211W | |
2217 | ||
2218 | retval = validate_recv_mgnt_frame(adapter, precv_frame); | |
2219 | if (retval == _FAIL) | |
2220 | { | |
2221 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_mgnt_frame fail\n")); | |
2222 | } | |
2223 | retval = _FAIL; // only data frame return _SUCCESS | |
2224 | break; | |
2225 | case WIFI_CTRL_TYPE: //ctrl | |
2226 | retval = validate_recv_ctrl_frame(adapter, precv_frame); | |
2227 | if (retval == _FAIL) | |
2228 | { | |
2229 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_ctrl_frame fail\n")); | |
2230 | } | |
2231 | retval = _FAIL; // only data frame return _SUCCESS | |
2232 | break; | |
2233 | case WIFI_DATA_TYPE: //data | |
2234 | rtw_led_control(adapter, LED_CTL_RX); | |
2235 | pattrib->qos = (subtype & BIT(7))? 1:0; | |
2236 | retval = validate_recv_data_frame(adapter, precv_frame); | |
2237 | if (retval == _FAIL) | |
2238 | { | |
2239 | struct recv_priv *precvpriv = &adapter->recvpriv; | |
2240 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_data_frame fail\n")); | |
2241 | precvpriv->rx_drop++; | |
2242 | } | |
2243 | break; | |
2244 | default: | |
2245 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_data_frame fail! type=0x%x\n", type)); | |
2246 | #ifdef DBG_RX_DROP_FRAME | |
2247 | DBG_871X("DBG_RX_DROP_FRAME validate_recv_data_frame fail! type=0x%x\n", type); | |
2248 | #endif | |
2249 | retval = _FAIL; | |
2250 | break; | |
2251 | } | |
2252 | ||
2253 | exit: | |
2254 | ||
2255 | _func_exit_; | |
2256 | ||
2257 | return retval; | |
2258 | } | |
2259 | ||
2260 | ||
2261 | //remove the wlanhdr and add the eth_hdr | |
2262 | #if 1 | |
2263 | ||
2264 | sint wlanhdr_to_ethhdr ( union recv_frame *precvframe); | |
2265 | sint wlanhdr_to_ethhdr ( union recv_frame *precvframe) | |
2266 | { | |
2267 | sint rmv_len; | |
2268 | u16 eth_type, len; | |
2269 | u8 bsnaphdr; | |
2270 | u8 *psnap_type; | |
2271 | struct ieee80211_snap_hdr *psnap; | |
2272 | ||
2273 | sint ret=_SUCCESS; | |
2274 | _adapter *adapter =precvframe->u.hdr.adapter; | |
2275 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; | |
2276 | ||
2277 | u8 *ptr = get_recvframe_data(precvframe) ; // point to frame_ctrl field | |
2278 | struct rx_pkt_attrib *pattrib = & precvframe->u.hdr.attrib; | |
2279 | ||
2280 | _func_enter_; | |
2281 | ||
2282 | if(pattrib->encrypt){ | |
2283 | recvframe_pull_tail(precvframe, pattrib->icv_len); | |
2284 | } | |
2285 | ||
2286 | psnap=(struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len); | |
2287 | psnap_type=ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE; | |
2288 | /* convert hdr + possible LLC headers into Ethernet header */ | |
2289 | //eth_type = (psnap_type[0] << 8) | psnap_type[1]; | |
2290 | if((_rtw_memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) && | |
2291 | (_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == _FALSE) && | |
2292 | (_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)==_FALSE) )|| | |
2293 | //eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || | |
2294 | _rtw_memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)){ | |
2295 | /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */ | |
2296 | bsnaphdr = _TRUE; | |
2297 | } | |
2298 | else { | |
2299 | /* Leave Ethernet header part of hdr and full payload */ | |
2300 | bsnaphdr = _FALSE; | |
2301 | } | |
2302 | ||
2303 | rmv_len = pattrib->hdrlen + pattrib->iv_len +(bsnaphdr?SNAP_SIZE:0); | |
2304 | len = precvframe->u.hdr.len - rmv_len; | |
2305 | ||
2306 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n===pattrib->hdrlen: %x, pattrib->iv_len:%x ===\n\n", pattrib->hdrlen, pattrib->iv_len)); | |
2307 | ||
2308 | _rtw_memcpy(ð_type, ptr+rmv_len, 2); | |
2309 | eth_type= ntohs((unsigned short )eth_type); //pattrib->ether_type | |
2310 | pattrib->eth_type = eth_type; | |
2311 | ||
2312 | if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)) | |
2313 | { | |
2314 | ptr += rmv_len ; | |
2315 | *ptr = 0x87; | |
2316 | *(ptr+1) = 0x12; | |
2317 | ||
2318 | eth_type = 0x8712; | |
2319 | // append rx status for mp test packets | |
2320 | ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2)-24); | |
2321 | _rtw_memcpy(ptr, get_rxmem(precvframe), 24); | |
2322 | ptr+=24; | |
2323 | } | |
2324 | else { | |
2325 | ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+ (bsnaphdr?2:0))); | |
2326 | } | |
2327 | ||
2328 | _rtw_memcpy(ptr, pattrib->dst, ETH_ALEN); | |
2329 | _rtw_memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN); | |
2330 | ||
2331 | if(!bsnaphdr) { | |
2332 | len = htons(len); | |
2333 | _rtw_memcpy(ptr+12, &len, 2); | |
2334 | } | |
2335 | ||
2336 | _func_exit_; | |
2337 | return ret; | |
2338 | ||
2339 | } | |
2340 | ||
2341 | #else | |
2342 | ||
2343 | sint wlanhdr_to_ethhdr ( union recv_frame *precvframe) | |
2344 | { | |
2345 | sint rmv_len; | |
2346 | u16 eth_type; | |
2347 | u8 bsnaphdr; | |
2348 | u8 *psnap_type; | |
2349 | struct ieee80211_snap_hdr *psnap; | |
2350 | ||
2351 | sint ret=_SUCCESS; | |
2352 | _adapter *adapter =precvframe->u.hdr.adapter; | |
2353 | struct mlme_priv *pmlmepriv = &adapter->mlmepriv; | |
2354 | ||
2355 | u8* ptr = get_recvframe_data(precvframe) ; // point to frame_ctrl field | |
2356 | struct rx_pkt_attrib *pattrib = & precvframe->u.hdr.attrib; | |
2357 | struct _vlan *pvlan = NULL; | |
2358 | ||
2359 | _func_enter_; | |
2360 | ||
2361 | psnap=(struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len); | |
2362 | psnap_type=ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE; | |
2363 | if (psnap->dsap==0xaa && psnap->ssap==0xaa && psnap->ctrl==0x03) | |
2364 | { | |
2365 | if (_rtw_memcmp(psnap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)) | |
2366 | bsnaphdr=_TRUE;//wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_RFC1042; | |
2367 | else if (_rtw_memcmp(psnap->oui, SNAP_HDR_APPLETALK_DDP, WLAN_IEEE_OUI_LEN) && | |
2368 | _rtw_memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_DDP, 2) ) | |
2369 | bsnaphdr=_TRUE; //wlan_pkt_format = WLAN_PKT_FORMAT_APPLETALK; | |
2370 | else if (_rtw_memcmp( psnap->oui, oui_8021h, WLAN_IEEE_OUI_LEN)) | |
2371 | bsnaphdr=_TRUE; //wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_TUNNEL; | |
2372 | else { | |
2373 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("drop pkt due to invalid frame format!\n")); | |
2374 | ret= _FAIL; | |
2375 | goto exit; | |
2376 | } | |
2377 | ||
2378 | } else | |
2379 | bsnaphdr=_FALSE;//wlan_pkt_format = WLAN_PKT_FORMAT_OTHERS; | |
2380 | ||
2381 | rmv_len = pattrib->hdrlen + pattrib->iv_len +(bsnaphdr?SNAP_SIZE:0); | |
2382 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("===pattrib->hdrlen: %x, pattrib->iv_len:%x ===\n", pattrib->hdrlen, pattrib->iv_len)); | |
2383 | ||
2384 | if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) | |
2385 | { | |
2386 | ptr += rmv_len ; | |
2387 | *ptr = 0x87; | |
2388 | *(ptr+1) = 0x12; | |
2389 | ||
2390 | //back to original pointer | |
2391 | ptr -= rmv_len; | |
2392 | } | |
2393 | ||
2394 | ptr += rmv_len ; | |
2395 | ||
2396 | _rtw_memcpy(ð_type, ptr, 2); | |
2397 | eth_type= ntohs((unsigned short )eth_type); //pattrib->ether_type | |
2398 | ptr +=2; | |
2399 | ||
2400 | if(pattrib->encrypt){ | |
2401 | recvframe_pull_tail(precvframe, pattrib->icv_len); | |
2402 | } | |
2403 | ||
2404 | if(eth_type == 0x8100) //vlan | |
2405 | { | |
2406 | pvlan = (struct _vlan *) ptr; | |
2407 | ||
2408 | //eth_type = get_vlan_encap_proto(pvlan); | |
2409 | //eth_type = pvlan->h_vlan_encapsulated_proto;//? | |
2410 | rmv_len += 4; | |
2411 | ptr+=4; | |
2412 | } | |
2413 | ||
2414 | if(eth_type==0x0800)//ip | |
2415 | { | |
2416 | //struct iphdr* piphdr = (struct iphdr*) ptr; | |
2417 | //__u8 tos = (unsigned char)(pattrib->priority & 0xff); | |
2418 | ||
2419 | //piphdr->tos = tos; | |
2420 | ||
2421 | //if (piphdr->protocol == 0x06) | |
2422 | //{ | |
2423 | // RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("@@@===recv tcp len:%d @@@===\n", precvframe->u.hdr.len)); | |
2424 | //} | |
2425 | } | |
2426 | else if(eth_type==0x8712)// append rx status for mp test packets | |
2427 | { | |
2428 | //ptr -= 16; | |
2429 | //_rtw_memcpy(ptr, get_rxmem(precvframe), 16); | |
2430 | } | |
2431 | else | |
2432 | { | |
2433 | #ifdef PLATFORM_OS_XP | |
2434 | NDIS_PACKET_8021Q_INFO VlanPriInfo; | |
2435 | UINT32 UserPriority = precvframe->u.hdr.attrib.priority; | |
2436 | UINT32 VlanID = (pvlan!=NULL ? get_vlan_id(pvlan) : 0 ); | |
2437 | ||
2438 | VlanPriInfo.Value = // Get current value. | |
2439 | NDIS_PER_PACKET_INFO_FROM_PACKET(precvframe->u.hdr.pkt, Ieee8021QInfo); | |
2440 | ||
2441 | VlanPriInfo.TagHeader.UserPriority = UserPriority; | |
2442 | VlanPriInfo.TagHeader.VlanId = VlanID ; | |
2443 | ||
2444 | VlanPriInfo.TagHeader.CanonicalFormatId = 0; // Should be zero. | |
2445 | VlanPriInfo.TagHeader.Reserved = 0; // Should be zero. | |
2446 | NDIS_PER_PACKET_INFO_FROM_PACKET(precvframe->u.hdr.pkt, Ieee8021QInfo) = VlanPriInfo.Value; | |
2447 | #endif | |
2448 | } | |
2449 | ||
2450 | if(eth_type==0x8712)// append rx status for mp test packets | |
2451 | { | |
2452 | ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2)-24); | |
2453 | _rtw_memcpy(ptr, get_rxmem(precvframe), 24); | |
2454 | ptr+=24; | |
2455 | } | |
2456 | else | |
2457 | ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2)); | |
2458 | ||
2459 | _rtw_memcpy(ptr, pattrib->dst, ETH_ALEN); | |
2460 | _rtw_memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN); | |
2461 | ||
2462 | eth_type = htons((unsigned short)eth_type) ; | |
2463 | _rtw_memcpy(ptr+12, ð_type, 2); | |
2464 | ||
2465 | exit: | |
2466 | ||
2467 | _func_exit_; | |
2468 | ||
2469 | return ret; | |
2470 | } | |
2471 | #endif | |
2472 | ||
2473 | ||
2474 | #ifdef CONFIG_SDIO_HCI | |
2475 | #ifdef PLATFORM_LINUX | |
2476 | static void recvframe_expand_pkt( | |
2477 | PADAPTER padapter, | |
2478 | union recv_frame *prframe) | |
2479 | { | |
2480 | struct recv_frame_hdr *pfhdr; | |
2481 | _pkt *ppkt; | |
2482 | u8 shift_sz; | |
2483 | u32 alloc_sz; | |
2484 | ||
2485 | ||
2486 | pfhdr = &prframe->u.hdr; | |
2487 | ||
2488 | // 6 is for IP header 8 bytes alignment in QoS packet case. | |
2489 | if (pfhdr->attrib.qos) | |
2490 | shift_sz = 6; | |
2491 | else | |
2492 | shift_sz = 0; | |
2493 | ||
2494 | // for first fragment packet, need to allocate | |
2495 | // (1536 + RXDESC_SIZE + drvinfo_sz) to reassemble packet | |
2496 | // 8 is for skb->data 8 bytes alignment. | |
2497 | // alloc_sz = _RND(1536 + RXDESC_SIZE + pfhdr->attrib.drvinfosize + shift_sz + 8, 128); | |
2498 | alloc_sz = 1664; // round (1536 + 24 + 32 + shift_sz + 8) to 128 bytes alignment | |
2499 | ||
2500 | //3 1. alloc new skb | |
2501 | // prepare extra space for 4 bytes alignment | |
2502 | ppkt = rtw_skb_alloc(alloc_sz); | |
2503 | ||
2504 | if (!ppkt) return; // no way to expand | |
2505 | ||
2506 | //3 2. Prepare new skb to replace & release old skb | |
2507 | // force ppkt->data at 8-byte alignment address | |
2508 | skb_reserve(ppkt, 8 - ((SIZE_PTR)ppkt->data & 7)); | |
2509 | // force ip_hdr at 8-byte alignment address according to shift_sz | |
2510 | skb_reserve(ppkt, shift_sz); | |
2511 | ||
2512 | // copy data to new pkt | |
2513 | _rtw_memcpy(skb_put(ppkt, pfhdr->len), pfhdr->rx_data, pfhdr->len); | |
2514 | ||
2515 | rtw_skb_free(pfhdr->pkt); | |
2516 | ||
2517 | // attach new pkt to recvframe | |
2518 | pfhdr->pkt = ppkt; | |
2519 | pfhdr->rx_head = ppkt->head; | |
2520 | pfhdr->rx_data = ppkt->data; | |
2521 | pfhdr->rx_tail = skb_tail_pointer(ppkt); | |
2522 | pfhdr->rx_end = skb_end_pointer(ppkt); | |
2523 | } | |
2524 | #else | |
2525 | #warning "recvframe_expand_pkt not implement, defrag may crash system" | |
2526 | #endif | |
2527 | #endif | |
2528 | ||
2529 | //perform defrag | |
2530 | union recv_frame * recvframe_defrag(_adapter *adapter,_queue *defrag_q); | |
2531 | union recv_frame * recvframe_defrag(_adapter *adapter,_queue *defrag_q) | |
2532 | { | |
2533 | _list *plist, *phead; | |
2534 | u8 *data,wlanhdr_offset; | |
2535 | u8 curfragnum; | |
2536 | struct recv_frame_hdr *pfhdr,*pnfhdr; | |
2537 | union recv_frame* prframe, *pnextrframe; | |
2538 | _queue *pfree_recv_queue; | |
2539 | ||
2540 | _func_enter_; | |
2541 | ||
2542 | curfragnum=0; | |
2543 | pfree_recv_queue=&adapter->recvpriv.free_recv_queue; | |
2544 | ||
2545 | phead = get_list_head(defrag_q); | |
2546 | plist = get_next(phead); | |
2547 | prframe = LIST_CONTAINOR(plist, union recv_frame, u); | |
2548 | pfhdr=&prframe->u.hdr; | |
2549 | rtw_list_delete(&(prframe->u.list)); | |
2550 | ||
2551 | if(curfragnum!=pfhdr->attrib.frag_num) | |
2552 | { | |
2553 | //the first fragment number must be 0 | |
2554 | //free the whole queue | |
2555 | rtw_free_recvframe(prframe, pfree_recv_queue); | |
2556 | rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); | |
2557 | ||
2558 | return NULL; | |
2559 | } | |
2560 | ||
2561 | #ifdef CONFIG_SDIO_HCI | |
2562 | recvframe_expand_pkt(adapter, prframe); | |
2563 | #endif | |
2564 | ||
2565 | curfragnum++; | |
2566 | ||
2567 | plist= get_list_head(defrag_q); | |
2568 | ||
2569 | plist = get_next(plist); | |
2570 | ||
2571 | data=get_recvframe_data(prframe); | |
2572 | ||
2573 | while(rtw_end_of_queue_search(phead, plist) == _FALSE) | |
2574 | { | |
2575 | pnextrframe = LIST_CONTAINOR(plist, union recv_frame , u); | |
2576 | pnfhdr=&pnextrframe->u.hdr; | |
2577 | ||
2578 | ||
2579 | //check the fragment sequence (2nd ~n fragment frame) | |
2580 | ||
2581 | if(curfragnum!=pnfhdr->attrib.frag_num) | |
2582 | { | |
2583 | //the fragment number must be increasing (after decache) | |
2584 | //release the defrag_q & prframe | |
2585 | rtw_free_recvframe(prframe, pfree_recv_queue); | |
2586 | rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); | |
2587 | return NULL; | |
2588 | } | |
2589 | ||
2590 | curfragnum++; | |
2591 | ||
2592 | //copy the 2nd~n fragment frame's payload to the first fragment | |
2593 | //get the 2nd~last fragment frame's payload | |
2594 | ||
2595 | wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len; | |
2596 | ||
2597 | recvframe_pull(pnextrframe, wlanhdr_offset); | |
2598 | ||
2599 | //append to first fragment frame's tail (if privacy frame, pull the ICV) | |
2600 | recvframe_pull_tail(prframe, pfhdr->attrib.icv_len); | |
2601 | ||
2602 | //memcpy | |
2603 | _rtw_memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len); | |
2604 | ||
2605 | recvframe_put(prframe, pnfhdr->len); | |
2606 | ||
2607 | pfhdr->attrib.icv_len=pnfhdr->attrib.icv_len; | |
2608 | plist = get_next(plist); | |
2609 | ||
2610 | }; | |
2611 | ||
2612 | //free the defrag_q queue and return the prframe | |
2613 | rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); | |
2614 | ||
2615 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("Performance defrag!!!!!\n")); | |
2616 | ||
2617 | _func_exit_; | |
2618 | ||
2619 | return prframe; | |
2620 | } | |
2621 | ||
2622 | //check if need to defrag, if needed queue the frame to defrag_q | |
2623 | union recv_frame* recvframe_chk_defrag(PADAPTER padapter, union recv_frame *precv_frame) | |
2624 | { | |
2625 | u8 ismfrag; | |
2626 | u8 fragnum; | |
2627 | u8 *psta_addr; | |
2628 | struct recv_frame_hdr *pfhdr; | |
2629 | struct sta_info *psta; | |
2630 | struct sta_priv *pstapriv; | |
2631 | _list *phead; | |
2632 | union recv_frame *prtnframe = NULL; | |
2633 | _queue *pfree_recv_queue, *pdefrag_q; | |
2634 | ||
2635 | _func_enter_; | |
2636 | ||
2637 | pstapriv = &padapter->stapriv; | |
2638 | ||
2639 | pfhdr = &precv_frame->u.hdr; | |
2640 | ||
2641 | pfree_recv_queue = &padapter->recvpriv.free_recv_queue; | |
2642 | ||
2643 | //need to define struct of wlan header frame ctrl | |
2644 | ismfrag = pfhdr->attrib.mfrag; | |
2645 | fragnum = pfhdr->attrib.frag_num; | |
2646 | ||
2647 | psta_addr = pfhdr->attrib.ta; | |
2648 | psta = rtw_get_stainfo(pstapriv, psta_addr); | |
2649 | if (psta == NULL) | |
2650 | { | |
2651 | u8 type = GetFrameType(pfhdr->rx_data); | |
2652 | if (type != WIFI_DATA_TYPE) { | |
2653 | psta = rtw_get_bcmc_stainfo(padapter); | |
2654 | pdefrag_q = &psta->sta_recvpriv.defrag_q; | |
2655 | } else | |
2656 | pdefrag_q = NULL; | |
2657 | } | |
2658 | else | |
2659 | pdefrag_q = &psta->sta_recvpriv.defrag_q; | |
2660 | ||
2661 | if ((ismfrag==0) && (fragnum==0)) | |
2662 | { | |
2663 | prtnframe = precv_frame;//isn't a fragment frame | |
2664 | } | |
2665 | ||
2666 | if (ismfrag==1) | |
2667 | { | |
2668 | //0~(n-1) fragment frame | |
2669 | //enqueue to defraf_g | |
2670 | if(pdefrag_q != NULL) | |
2671 | { | |
2672 | if(fragnum==0) | |
2673 | { | |
2674 | //the first fragment | |
2675 | if(_rtw_queue_empty(pdefrag_q) == _FALSE) | |
2676 | { | |
2677 | //free current defrag_q | |
2678 | rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue); | |
2679 | } | |
2680 | } | |
2681 | ||
2682 | ||
2683 | //Then enqueue the 0~(n-1) fragment into the defrag_q | |
2684 | ||
2685 | //_rtw_spinlock(&pdefrag_q->lock); | |
2686 | phead = get_list_head(pdefrag_q); | |
2687 | rtw_list_insert_tail(&pfhdr->list, phead); | |
2688 | //_rtw_spinunlock(&pdefrag_q->lock); | |
2689 | ||
2690 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("Enqueuq: ismfrag = %d, fragnum= %d\n", ismfrag,fragnum)); | |
2691 | ||
2692 | prtnframe=NULL; | |
2693 | ||
2694 | } | |
2695 | else | |
2696 | { | |
2697 | //can't find this ta's defrag_queue, so free this recv_frame | |
2698 | rtw_free_recvframe(precv_frame, pfree_recv_queue); | |
2699 | prtnframe=NULL; | |
2700 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("Free because pdefrag_q ==NULL: ismfrag = %d, fragnum= %d\n", ismfrag, fragnum)); | |
2701 | } | |
2702 | ||
2703 | } | |
2704 | ||
2705 | if((ismfrag==0)&&(fragnum!=0)) | |
2706 | { | |
2707 | //the last fragment frame | |
2708 | //enqueue the last fragment | |
2709 | if(pdefrag_q != NULL) | |
2710 | { | |
2711 | //_rtw_spinlock(&pdefrag_q->lock); | |
2712 | phead = get_list_head(pdefrag_q); | |
2713 | rtw_list_insert_tail(&pfhdr->list,phead); | |
2714 | //_rtw_spinunlock(&pdefrag_q->lock); | |
2715 | ||
2716 | //call recvframe_defrag to defrag | |
2717 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("defrag: ismfrag = %d, fragnum= %d\n", ismfrag, fragnum)); | |
2718 | precv_frame = recvframe_defrag(padapter, pdefrag_q); | |
2719 | prtnframe=precv_frame; | |
2720 | ||
2721 | } | |
2722 | else | |
2723 | { | |
2724 | //can't find this ta's defrag_queue, so free this recv_frame | |
2725 | rtw_free_recvframe(precv_frame, pfree_recv_queue); | |
2726 | prtnframe=NULL; | |
2727 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("Free because pdefrag_q ==NULL: ismfrag = %d, fragnum= %d\n", ismfrag,fragnum)); | |
2728 | } | |
2729 | ||
2730 | } | |
2731 | ||
2732 | ||
2733 | if((prtnframe!=NULL)&&(prtnframe->u.hdr.attrib.privacy)) | |
2734 | { | |
2735 | //after defrag we must check tkip mic code | |
2736 | if(recvframe_chkmic(padapter, prtnframe)==_FAIL) | |
2737 | { | |
2738 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvframe_chkmic(padapter, prtnframe)==_FAIL\n")); | |
2739 | rtw_free_recvframe(prtnframe,pfree_recv_queue); | |
2740 | prtnframe=NULL; | |
2741 | } | |
2742 | } | |
2743 | ||
2744 | _func_exit_; | |
2745 | ||
2746 | return prtnframe; | |
2747 | ||
2748 | } | |
2749 | ||
2750 | #define ENDIAN_FREE 1 | |
2751 | ||
2752 | int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe); | |
2753 | int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe) | |
2754 | { | |
2755 | #if defined (PLATFORM_LINUX) || defined (PLATFORM_FREEBSD) //for amsdu TP improvement,Creator: Thomas | |
2756 | int a_len, padding_len; | |
2757 | u16 eth_type, nSubframe_Length; | |
2758 | u8 nr_subframes, i; | |
2759 | unsigned char *pdata; | |
2760 | struct rx_pkt_attrib *pattrib; | |
2761 | #ifndef PLATFORM_FREEBSD | |
2762 | unsigned char *data_ptr; | |
2763 | _pkt *sub_skb,*subframes[MAX_SUBFRAME_COUNT]; | |
2764 | #endif //PLATFORM_FREEBSD | |
2765 | struct recv_priv *precvpriv = &padapter->recvpriv; | |
2766 | _queue *pfree_recv_queue = &(precvpriv->free_recv_queue); | |
2767 | int ret = _SUCCESS; | |
2768 | #ifdef PLATFORM_FREEBSD | |
2769 | struct mbuf *sub_m=NULL, *subframes[MAX_SUBFRAME_COUNT]; | |
2770 | u8 *ptr,offset; | |
2771 | #endif //PLATFORM_FREEBSD | |
2772 | nr_subframes = 0; | |
2773 | ||
2774 | pattrib = &prframe->u.hdr.attrib; | |
2775 | ||
2776 | recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen); | |
2777 | ||
2778 | if(prframe->u.hdr.attrib.iv_len >0) | |
2779 | { | |
2780 | recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len); | |
2781 | } | |
2782 | ||
2783 | a_len = prframe->u.hdr.len; | |
2784 | ||
2785 | pdata = prframe->u.hdr.rx_data; | |
2786 | ||
2787 | while(a_len > ETH_HLEN) { | |
2788 | ||
2789 | /* Offset 12 denote 2 mac address */ | |
2790 | #ifdef ENDIAN_FREE | |
2791 | //nSubframe_Length = ntohs(*((u16*)(pdata + 12))); | |
2792 | nSubframe_Length = RTW_GET_BE16(pdata + 12); | |
2793 | #else // ENDIAN_FREE | |
2794 | nSubframe_Length = *((u16*)(pdata + 12)); | |
2795 | //==m==>change the length order | |
2796 | nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8); | |
2797 | //ntohs(nSubframe_Length); | |
2798 | #endif // ENDIAN_FREE | |
2799 | ||
2800 | if( a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length) ) { | |
2801 | DBG_871X("nRemain_Length is %d and nSubframe_Length is : %d\n",a_len,nSubframe_Length); | |
2802 | goto exit; | |
2803 | } | |
2804 | ||
2805 | #ifndef PLATFORM_FREEBSD | |
2806 | /* move the data point to data content */ | |
2807 | pdata += ETH_HLEN; | |
2808 | a_len -= ETH_HLEN; | |
2809 | ||
2810 | /* Allocate new skb for releasing to upper layer */ | |
2811 | #ifdef CONFIG_SKB_COPY | |
2812 | sub_skb = rtw_skb_alloc(nSubframe_Length + 12); | |
2813 | if(sub_skb) | |
2814 | { | |
2815 | skb_reserve(sub_skb, 12); | |
2816 | data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length); | |
2817 | _rtw_memcpy(data_ptr, pdata, nSubframe_Length); | |
2818 | } | |
2819 | else | |
2820 | #endif // CONFIG_SKB_COPY | |
2821 | { | |
2822 | sub_skb = rtw_skb_clone(prframe->u.hdr.pkt); | |
2823 | if(sub_skb) | |
2824 | { | |
2825 | sub_skb->data = pdata; | |
2826 | sub_skb->len = nSubframe_Length; | |
2827 | skb_set_tail_pointer(sub_skb, nSubframe_Length); | |
2828 | } | |
2829 | else | |
2830 | { | |
2831 | DBG_871X("rtw_skb_clone() Fail!!! , nr_subframes = %d\n",nr_subframes); | |
2832 | break; | |
2833 | } | |
2834 | } | |
2835 | ||
2836 | #else // PLATFORM_FREEBSD | |
2837 | ||
2838 | //PLATFORM_FREEBSD | |
2839 | //Allocate a mbuff, | |
2840 | //sub_m =m_devget(pdata, nSubframe_Length+12, 12, padapter->pifp,NULL); | |
2841 | sub_m =m_devget(pdata, nSubframe_Length+ETH_HLEN, ETHER_ALIGN, padapter->pifp,NULL); | |
2842 | ||
2843 | pdata += ETH_HLEN; | |
2844 | a_len -= ETH_HLEN; | |
2845 | #endif // PLATFORM_FREEBSD | |
2846 | ||
2847 | #ifndef PLATFORM_FREEBSD | |
2848 | //sub_skb->dev = padapter->pnetdev; | |
2849 | subframes[nr_subframes++] = sub_skb; | |
2850 | #else //PLATFORM_FREEBSD | |
2851 | //PLATFORM_FREEBSD | |
2852 | subframes[nr_subframes++] = sub_m; | |
2853 | #endif //PLATFORM_FREEBSD | |
2854 | ||
2855 | if(nr_subframes >= MAX_SUBFRAME_COUNT) { | |
2856 | DBG_871X("ParseSubframe(): Too many Subframes! Packets dropped!\n"); | |
2857 | break; | |
2858 | } | |
2859 | ||
2860 | pdata += nSubframe_Length; | |
2861 | a_len -= nSubframe_Length; | |
2862 | if(a_len != 0) { | |
2863 | padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4-1)); | |
2864 | if(padding_len == 4) { | |
2865 | padding_len = 0; | |
2866 | } | |
2867 | ||
2868 | if(a_len < padding_len) { | |
2869 | goto exit; | |
2870 | } | |
2871 | pdata += padding_len; | |
2872 | a_len -= padding_len; | |
2873 | } | |
2874 | } | |
2875 | ||
2876 | for(i=0; i<nr_subframes; i++){ | |
2877 | #ifndef PLATFORM_FREEBSD | |
2878 | sub_skb = subframes[i]; | |
2879 | /* convert hdr + possible LLC headers into Ethernet header */ | |
2880 | #ifdef ENDIAN_FREE | |
2881 | //eth_type = ntohs(*(u16*)&sub_skb->data[6]); | |
2882 | eth_type = RTW_GET_BE16(&sub_skb->data[6]); | |
2883 | #else // ENDIAN_FREE | |
2884 | eth_type = (sub_skb->data[6] << 8) | sub_skb->data[7]; | |
2885 | #endif // ENDIAN_FREE | |
2886 | if (sub_skb->len >= 8 && | |
2887 | ((_rtw_memcmp(sub_skb->data, rtw_rfc1042_header, SNAP_SIZE) && | |
2888 | eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || | |
2889 | _rtw_memcmp(sub_skb->data, rtw_bridge_tunnel_header, SNAP_SIZE) )) { | |
2890 | /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */ | |
2891 | skb_pull(sub_skb, SNAP_SIZE); | |
2892 | _rtw_memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); | |
2893 | _rtw_memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN); | |
2894 | } else { | |
2895 | u16 len; | |
2896 | /* Leave Ethernet header part of hdr and full payload */ | |
2897 | len = htons(sub_skb->len); | |
2898 | _rtw_memcpy(skb_push(sub_skb, 2), &len, 2); | |
2899 | _rtw_memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src, ETH_ALEN); | |
2900 | _rtw_memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst, ETH_ALEN); | |
2901 | } | |
2902 | ||
2903 | /* Indicat the packets to upper layer */ | |
2904 | if (sub_skb) { | |
2905 | //memset(sub_skb->cb, 0, sizeof(sub_skb->cb)); | |
2906 | ||
2907 | #ifdef CONFIG_BR_EXT | |
2908 | // Insert NAT2.5 RX here! | |
2909 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
2910 | void *br_port = NULL; | |
2911 | ||
2912 | #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) | |
2913 | br_port = padapter->pnetdev->br_port; | |
2914 | #else // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) | |
2915 | rcu_read_lock(); | |
2916 | br_port = rcu_dereference(padapter->pnetdev->rx_handler_data); | |
2917 | rcu_read_unlock(); | |
2918 | #endif // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) | |
2919 | ||
2920 | ||
2921 | if( br_port && (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) ) | |
2922 | { | |
2923 | int nat25_handle_frame(_adapter *priv, struct sk_buff *skb); | |
2924 | if (nat25_handle_frame(padapter, sub_skb) == -1) { | |
2925 | //priv->ext_stats.rx_data_drops++; | |
2926 | //DEBUG_ERR("RX DROP: nat25_handle_frame fail!\n"); | |
2927 | //return FAIL; | |
2928 | ||
2929 | #if 1 | |
2930 | // bypass this frame to upper layer!! | |
2931 | #else | |
2932 | rtw_skb_free(sub_skb); | |
2933 | continue; | |
2934 | #endif | |
2935 | } | |
2936 | } | |
2937 | #endif // CONFIG_BR_EXT | |
2938 | ||
2939 | sub_skb->protocol = eth_type_trans(sub_skb, padapter->pnetdev); | |
2940 | sub_skb->dev = padapter->pnetdev; | |
2941 | ||
2942 | #ifdef CONFIG_TCP_CSUM_OFFLOAD_RX | |
2943 | if ( (pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1) ) { | |
2944 | sub_skb->ip_summed = CHECKSUM_UNNECESSARY; | |
2945 | } else { | |
2946 | sub_skb->ip_summed = CHECKSUM_NONE; | |
2947 | } | |
2948 | #else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */ | |
2949 | sub_skb->ip_summed = CHECKSUM_NONE; | |
2950 | #endif //CONFIG_TCP_CSUM_OFFLOAD_RX | |
2951 | ||
2952 | rtw_netif_rx(padapter->pnetdev, sub_skb); | |
2953 | } | |
2954 | #else //PLATFORM_FREEBSD | |
2955 | ||
2956 | //PLATFORM_FREEBSD | |
2957 | sub_m = subframes[i]; | |
2958 | ptr=mtod(sub_m, u8 *); | |
2959 | offset=ETH_HLEN; | |
2960 | /* convert hdr + possible LLC headers into Ethernet header */ | |
2961 | #ifdef ENDIAN_FREE | |
2962 | eth_type = ntohs(*(u16*)&ptr[offset+6]); | |
2963 | #else // ENDIAN_FREE | |
2964 | eth_type = ( ptr[offset+6] << 8) | ptr[offset+7]; | |
2965 | #endif // ENDIAN_FREE | |
2966 | if (sub_m->m_pkthdr.len >= ETH_HLEN+8 && | |
2967 | ((_rtw_memcmp(ptr+ETH_HLEN, rtw_rfc1042_header, SNAP_SIZE) && | |
2968 | eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || | |
2969 | _rtw_memcmp(ptr+ETH_HLEN, rtw_bridge_tunnel_header, SNAP_SIZE) )) { | |
2970 | /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */ | |
2971 | offset+=SNAP_SIZE; | |
2972 | _rtw_memcpy(&ptr[offset-ETH_ALEN], pattrib->src, ETH_ALEN); | |
2973 | offset-=ETH_ALEN; | |
2974 | _rtw_memcpy(&ptr[offset-ETH_ALEN], pattrib->dst, ETH_ALEN); | |
2975 | offset-=ETH_ALEN; | |
2976 | } else { | |
2977 | u16 len; | |
2978 | /* Leave Ethernet header part of hdr and full payload */ | |
2979 | len = htons(sub_m->m_pkthdr.len-offset); | |
2980 | _rtw_memcpy(&ptr[offset- 2], &len, 2); | |
2981 | offset-=2; | |
2982 | _rtw_memcpy(&ptr[offset-ETH_ALEN], pattrib->src, ETH_ALEN); | |
2983 | offset-=ETH_ALEN; | |
2984 | _rtw_memcpy(&ptr[offset-ETH_ALEN], pattrib->dst, ETH_ALEN); | |
2985 | offset-=ETH_ALEN; | |
2986 | } | |
2987 | ||
2988 | m_adj(sub_m,offset); | |
2989 | ||
2990 | /* Indicat the packets to upper layer */ | |
2991 | if (sub_m) { | |
2992 | ||
2993 | #if 0 | |
2994 | #ifdef CONFIG_TCP_CSUM_OFFLOAD_RX | |
2995 | if ( (pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1) ) { | |
2996 | sub_skb->ip_summed = CHECKSUM_UNNECESSARY; | |
2997 | } else { | |
2998 | sub_skb->ip_summed = CHECKSUM_NONE; | |
2999 | } | |
3000 | #else /* !CONFIG_TCP_CSUM_OFFLOAD_RX */ | |
3001 | sub_skb->ip_summed = CHECKSUM_NONE; | |
3002 | #endif //CONFIG_TCP_CSUM_OFFLOAD_RX | |
3003 | #endif //0 | |
3004 | ||
3005 | if ( ((u32)(mtod(sub_m, caddr_t) + 14) % 4) != 0) | |
3006 | printf("%s()-%d: mtod(sub_m) = %p\n", __FUNCTION__, __LINE__, mtod(sub_m, caddr_t)); | |
3007 | #ifdef CONFIG_RX_INDICATE_QUEUE | |
3008 | IF_ENQUEUE(&precvpriv->rx_indicate_queue, sub_m); | |
3009 | if (_IF_QLEN(&precvpriv->rx_indicate_queue) <= 1) { | |
3010 | taskqueue_enqueue(taskqueue_thread, &precvpriv->rx_indicate_tasklet); | |
3011 | } | |
3012 | #else // CONFIG_RX_INDICATE_QUEUE | |
3013 | (*padapter->pifp->if_input)(padapter->pifp, sub_m); | |
3014 | #endif // CONFIG_RX_INDICATE_QUEUE | |
3015 | } | |
3016 | ||
3017 | #endif //PLATFORM_FREEBSD | |
3018 | } | |
3019 | ||
3020 | exit: | |
3021 | ||
3022 | prframe->u.hdr.len=0; | |
3023 | rtw_free_recvframe(prframe, pfree_recv_queue);//free this recv_frame | |
3024 | ||
3025 | return ret; | |
3026 | #else // || defined (PLATFORM_LINUX) || defined (PLATFORM_FREEBSD) | |
3027 | #ifdef PLATFORM_WINDOWS | |
3028 | _irqL irql; | |
3029 | #endif //PLATFORM_WINDOWS | |
3030 | unsigned char *ptr, *pdata, *pbuf, *psnap_type; | |
3031 | union recv_frame *pnrframe, *pnrframe_new; | |
3032 | int a_len, mv_len, padding_len; | |
3033 | u16 eth_type, type_len; | |
3034 | u8 bsnaphdr; | |
3035 | struct ieee80211_snap_hdr *psnap; | |
3036 | struct _vlan *pvlan; | |
3037 | struct recv_priv *precvpriv = &padapter->recvpriv; | |
3038 | _queue *pfree_recv_queue = &(precvpriv->free_recv_queue); | |
3039 | int ret = _SUCCESS; | |
3040 | #ifdef PLATFORM_WINDOWS | |
3041 | struct recv_buf *precvbuf = prframe->u.hdr.precvbuf; | |
3042 | #endif //PLATFORM_WINDOWS | |
3043 | a_len = prframe->u.hdr.len - prframe->u.hdr.attrib.hdrlen; | |
3044 | ||
3045 | recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen); | |
3046 | ||
3047 | if(prframe->u.hdr.attrib.iv_len >0) | |
3048 | { | |
3049 | recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len); | |
3050 | } | |
3051 | ||
3052 | pdata = prframe->u.hdr.rx_data; | |
3053 | ||
3054 | prframe->u.hdr.len=0; | |
3055 | ||
3056 | pnrframe = prframe; | |
3057 | ||
3058 | ||
3059 | do{ | |
3060 | ||
3061 | mv_len=0; | |
3062 | pnrframe->u.hdr.rx_data = pnrframe->u.hdr.rx_tail = pdata; | |
3063 | ptr = pdata; | |
3064 | ||
3065 | ||
3066 | _rtw_memcpy(pnrframe->u.hdr.attrib.dst, ptr, ETH_ALEN); | |
3067 | ptr+=ETH_ALEN; | |
3068 | _rtw_memcpy(pnrframe->u.hdr.attrib.src, ptr, ETH_ALEN); | |
3069 | ptr+=ETH_ALEN; | |
3070 | ||
3071 | _rtw_memcpy(&type_len, ptr, 2); | |
3072 | type_len= ntohs((unsigned short )type_len); | |
3073 | ptr +=2; | |
3074 | mv_len += ETH_HLEN; | |
3075 | ||
3076 | recvframe_put(pnrframe, type_len+ETH_HLEN);//update tail; | |
3077 | ||
3078 | if(pnrframe->u.hdr.rx_data >= pnrframe->u.hdr.rx_tail || type_len<8) | |
3079 | { | |
3080 | //panic("pnrframe->u.hdr.rx_data >= pnrframe->u.hdr.rx_tail || type_len<8\n"); | |
3081 | ||
3082 | rtw_free_recvframe(pnrframe, pfree_recv_queue); | |
3083 | ||
3084 | goto exit; | |
3085 | } | |
3086 | ||
3087 | psnap=(struct ieee80211_snap_hdr *)(ptr); | |
3088 | psnap_type=ptr+SNAP_SIZE; | |
3089 | if (psnap->dsap==0xaa && psnap->ssap==0xaa && psnap->ctrl==0x03) | |
3090 | { | |
3091 | if ( _rtw_memcmp(psnap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)) | |
3092 | { | |
3093 | bsnaphdr=_TRUE;//wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_RFC1042; | |
3094 | } | |
3095 | else if (_rtw_memcmp(psnap->oui, SNAP_HDR_APPLETALK_DDP, WLAN_IEEE_OUI_LEN) && | |
3096 | _rtw_memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_DDP, 2) ) | |
3097 | { | |
3098 | bsnaphdr=_TRUE; //wlan_pkt_format = WLAN_PKT_FORMAT_APPLETALK; | |
3099 | } | |
3100 | else if (_rtw_memcmp( psnap->oui, oui_8021h, WLAN_IEEE_OUI_LEN)) | |
3101 | { | |
3102 | bsnaphdr=_TRUE; //wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_TUNNEL; | |
3103 | } | |
3104 | else | |
3105 | { | |
3106 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("drop pkt due to invalid frame format!\n")); | |
3107 | ||
3108 | //KeBugCheckEx(0x87123333, 0xe0, 0x4c, 0x87, 0xdd); | |
3109 | ||
3110 | //panic("0x87123333, 0xe0, 0x4c, 0x87, 0xdd\n"); | |
3111 | ||
3112 | rtw_free_recvframe(pnrframe, pfree_recv_queue); | |
3113 | ||
3114 | goto exit; | |
3115 | } | |
3116 | ||
3117 | } | |
3118 | else | |
3119 | { | |
3120 | bsnaphdr=_FALSE;//wlan_pkt_format = WLAN_PKT_FORMAT_OTHERS; | |
3121 | } | |
3122 | ||
3123 | ptr += (bsnaphdr?SNAP_SIZE:0); | |
3124 | _rtw_memcpy(ð_type, ptr, 2); | |
3125 | eth_type= ntohs((unsigned short )eth_type); //pattrib->ether_type | |
3126 | ||
3127 | mv_len+= 2+(bsnaphdr?SNAP_SIZE:0); | |
3128 | ptr += 2;//now move to iphdr; | |
3129 | ||
3130 | pvlan = NULL; | |
3131 | if(eth_type == 0x8100) //vlan | |
3132 | { | |
3133 | pvlan = (struct _vlan *)ptr; | |
3134 | ptr+=4; | |
3135 | mv_len+=4; | |
3136 | } | |
3137 | ||
3138 | if(eth_type==0x0800)//ip | |
3139 | { | |
3140 | struct iphdr* piphdr = (struct iphdr*)ptr; | |
3141 | ||
3142 | ||
3143 | if (piphdr->protocol == 0x06) | |
3144 | { | |
3145 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("@@@===recv tcp len:%d @@@===\n", pnrframe->u.hdr.len)); | |
3146 | } | |
3147 | } | |
3148 | #ifdef PLATFORM_OS_XP | |
3149 | else | |
3150 | { | |
3151 | NDIS_PACKET_8021Q_INFO VlanPriInfo; | |
3152 | UINT32 UserPriority = pnrframe->u.hdr.attrib.priority; | |
3153 | UINT32 VlanID = (pvlan!=NULL ? get_vlan_id(pvlan) : 0 ); | |
3154 | ||
3155 | VlanPriInfo.Value = // Get current value. | |
3156 | NDIS_PER_PACKET_INFO_FROM_PACKET(pnrframe->u.hdr.pkt, Ieee8021QInfo); | |
3157 | ||
3158 | VlanPriInfo.TagHeader.UserPriority = UserPriority; | |
3159 | VlanPriInfo.TagHeader.VlanId = VlanID; | |
3160 | ||
3161 | VlanPriInfo.TagHeader.CanonicalFormatId = 0; // Should be zero. | |
3162 | VlanPriInfo.TagHeader.Reserved = 0; // Should be zero. | |
3163 | NDIS_PER_PACKET_INFO_FROM_PACKET(pnrframe->u.hdr.pkt, Ieee8021QInfo) = VlanPriInfo.Value; | |
3164 | ||
3165 | } | |
3166 | #endif //PLATFORM_OS_XP | |
3167 | ||
3168 | pbuf = recvframe_pull(pnrframe, (mv_len-sizeof(struct ethhdr))); | |
3169 | ||
3170 | _rtw_memcpy(pbuf, pnrframe->u.hdr.attrib.dst, ETH_ALEN); | |
3171 | _rtw_memcpy(pbuf+ETH_ALEN, pnrframe->u.hdr.attrib.src, ETH_ALEN); | |
3172 | ||
3173 | eth_type = htons((unsigned short)eth_type) ; | |
3174 | _rtw_memcpy(pbuf+12, ð_type, 2); | |
3175 | ||
3176 | padding_len = (4) - ((type_len + ETH_HLEN)&(4-1)); | |
3177 | ||
3178 | a_len -= (type_len + ETH_HLEN + padding_len) ; | |
3179 | ||
3180 | ||
3181 | #if 0 | |
3182 | ||
3183 | if(a_len > ETH_HLEN) | |
3184 | { | |
3185 | pnrframe_new = rtw_alloc_recvframe(pfree_recv_queue); | |
3186 | if(pnrframe_new) | |
3187 | { | |
3188 | _pkt *pskb_copy; | |
3189 | unsigned int copy_len = pnrframe->u.hdr.len; | |
3190 | ||
3191 | _rtw_init_listhead(&pnrframe_new->u.hdr.list); | |
3192 | ||
3193 | pskb_copy = rtw_skb_alloc(copy_len+64); | |
3194 | ||
3195 | if(pskb_copy==NULL) | |
3196 | { | |
3197 | DBG_871X("amsdu_to_msdu:can not all(ocate memory for skb copy\n"); | |
3198 | } | |
3199 | ||
3200 | pnrframe_new->u.hdr.pkt = pskb_copy; | |
3201 | ||
3202 | _rtw_memcpy(pskb_copy->data, pnrframe->u.hdr.rx_data, copy_len); | |
3203 | ||
3204 | pnrframe_new->u.hdr.rx_data = pnrframe->u.hdr.rx_data; | |
3205 | pnrframe_new->u.hdr.rx_tail = pnrframe->u.hdr.rx_data + copy_len; | |
3206 | ||
3207 | ||
3208 | if ((padapter->bDriverStopped ==_FALSE)&&( padapter->bSurpriseRemoved==_FALSE)) | |
3209 | { | |
3210 | rtw_recv_indicatepkt(padapter, pnrframe_new);//indicate this recv_frame | |
3211 | } | |
3212 | else | |
3213 | { | |
3214 | rtw_free_recvframe(pnrframe_new, pfree_recv_queue);//free this recv_frame | |
3215 | } | |
3216 | ||
3217 | } | |
3218 | else | |
3219 | { | |
3220 | DBG_871X("amsdu_to_msdu:can not allocate memory for pnrframe_new\n"); | |
3221 | } | |
3222 | ||
3223 | } | |
3224 | else | |
3225 | { | |
3226 | if ((padapter->bDriverStopped ==_FALSE)&&( padapter->bSurpriseRemoved==_FALSE)) | |
3227 | { | |
3228 | rtw_recv_indicatepkt(padapter, pnrframe);//indicate this recv_frame | |
3229 | } | |
3230 | else | |
3231 | { | |
3232 | rtw_free_recvframe(pnrframe, pfree_recv_queue);//free this recv_frame | |
3233 | } | |
3234 | ||
3235 | pnrframe = NULL; | |
3236 | ||
3237 | } | |
3238 | ||
3239 | #else // 0 | |
3240 | ||
3241 | //padding_len = (4) - ((type_len + ETH_HLEN)&(4-1)); | |
3242 | ||
3243 | //a_len -= (type_len + ETH_HLEN + padding_len) ; | |
3244 | ||
3245 | pnrframe_new = NULL; | |
3246 | ||
3247 | ||
3248 | if(a_len > ETH_HLEN) | |
3249 | { | |
3250 | pnrframe_new = rtw_alloc_recvframe(pfree_recv_queue); | |
3251 | ||
3252 | if(pnrframe_new) | |
3253 | { | |
3254 | ||
3255 | ||
3256 | //pnrframe_new->u.hdr.precvbuf = precvbuf;//precvbuf is assigned before call rtw_init_recvframe() | |
3257 | //rtw_init_recvframe(pnrframe_new, precvpriv); | |
3258 | { | |
3259 | #ifdef PLATFORM_LINUX | |
3260 | _pkt *pskb = pnrframe->u.hdr.pkt; | |
3261 | #endif //PLATFORM_LINUX | |
3262 | _rtw_init_listhead(&pnrframe_new->u.hdr.list); | |
3263 | ||
3264 | pnrframe_new->u.hdr.len=0; | |
3265 | ||
3266 | #ifdef PLATFORM_LINUX | |
3267 | if(pskb) | |
3268 | { | |
3269 | pnrframe_new->u.hdr.pkt = rtw_skb_clone(pskb); | |
3270 | } | |
3271 | #endif //PLATFORM_LINUX | |
3272 | ||
3273 | } | |
3274 | ||
3275 | pdata += (type_len + ETH_HLEN + padding_len); | |
3276 | pnrframe_new->u.hdr.rx_head = pnrframe_new->u.hdr.rx_data = pnrframe_new->u.hdr.rx_tail = pdata; | |
3277 | pnrframe_new->u.hdr.rx_end = pdata + a_len + padding_len;// | |
3278 | ||
3279 | #ifdef PLATFORM_WINDOWS | |
3280 | pnrframe_new->u.hdr.precvbuf=precvbuf; | |
3281 | _enter_critical_bh(&precvbuf->recvbuf_lock, &irql); | |
3282 | precvbuf->ref_cnt++; | |
3283 | _exit_critical_bh(&precvbuf->recvbuf_lock, &irql); | |
3284 | #endif //PLATFORM_WINDOWS | |
3285 | ||
3286 | } | |
3287 | else | |
3288 | { | |
3289 | //panic("pnrframe_new=%x\n", pnrframe_new); | |
3290 | } | |
3291 | } | |
3292 | ||
3293 | ||
3294 | if ((padapter->bDriverStopped ==_FALSE)&&( padapter->bSurpriseRemoved==_FALSE) ) | |
3295 | { | |
3296 | rtw_recv_indicatepkt(padapter, pnrframe);//indicate this recv_frame | |
3297 | } | |
3298 | else | |
3299 | { | |
3300 | rtw_free_recvframe(pnrframe, pfree_recv_queue);//free this recv_frame | |
3301 | } | |
3302 | ||
3303 | ||
3304 | pnrframe = NULL; | |
3305 | if(pnrframe_new) | |
3306 | { | |
3307 | pnrframe = pnrframe_new; | |
3308 | } | |
3309 | ||
3310 | ||
3311 | #endif // end defined (PLATFORM_LINUX) || defined (PLATFORM_FREEBSD) | |
3312 | ||
3313 | }while(pnrframe); | |
3314 | ||
3315 | exit: | |
3316 | ||
3317 | return ret; | |
3318 | #endif | |
3319 | } | |
3320 | ||
3321 | int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num); | |
3322 | int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num) | |
3323 | { | |
3324 | u8 wsize = preorder_ctrl->wsize_b; | |
3325 | u16 wend = (preorder_ctrl->indicate_seq + wsize -1) & 0xFFF;//% 4096; | |
3326 | ||
3327 | // Rx Reorder initialize condition. | |
3328 | if (preorder_ctrl->indicate_seq == 0xFFFF) | |
3329 | { | |
3330 | preorder_ctrl->indicate_seq = seq_num; | |
3331 | #ifdef DBG_RX_SEQ | |
3332 | DBG_871X("DBG_RX_SEQ %s:%d init IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__, | |
3333 | preorder_ctrl->indicate_seq, seq_num); | |
3334 | #endif | |
3335 | ||
3336 | //DbgPrint("check_indicate_seq, 1st->indicate_seq=%d\n", precvpriv->indicate_seq); | |
3337 | } | |
3338 | ||
3339 | //DbgPrint("enter->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); | |
3340 | ||
3341 | // Drop out the packet which SeqNum is smaller than WinStart | |
3342 | if( SN_LESS(seq_num, preorder_ctrl->indicate_seq) ) | |
3343 | { | |
3344 | //RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum)); | |
3345 | //DbgPrint("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); | |
3346 | ||
3347 | #ifdef DBG_RX_DROP_FRAME | |
3348 | DBG_871X("%s IndicateSeq: %d > NewSeq: %d\n", __FUNCTION__, | |
3349 | preorder_ctrl->indicate_seq, seq_num); | |
3350 | #endif | |
3351 | ||
3352 | ||
3353 | return _FALSE; | |
3354 | } | |
3355 | ||
3356 | // | |
3357 | // Sliding window manipulation. Conditions includes: | |
3358 | // 1. Incoming SeqNum is equal to WinStart =>Window shift 1 | |
3359 | // 2. Incoming SeqNum is larger than the WinEnd => Window shift N | |
3360 | // | |
3361 | if( SN_EQUAL(seq_num, preorder_ctrl->indicate_seq) ) | |
3362 | { | |
3363 | preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF; | |
3364 | #ifdef DBG_RX_SEQ | |
3365 | DBG_871X("DBG_RX_SEQ %s:%d SN_EQUAL IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__, | |
3366 | preorder_ctrl->indicate_seq, seq_num); | |
3367 | #endif | |
3368 | } | |
3369 | else if(SN_LESS(wend, seq_num)) | |
3370 | { | |
3371 | //RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum)); | |
3372 | //DbgPrint("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); | |
3373 | ||
3374 | // boundary situation, when seq_num cross 0xFFF | |
3375 | if(seq_num >= (wsize - 1)) | |
3376 | preorder_ctrl->indicate_seq = seq_num + 1 -wsize; | |
3377 | else | |
3378 | preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1; | |
3379 | ||
3380 | #ifdef DBG_RX_SEQ | |
3381 | DBG_871X("DBG_RX_SEQ %s:%d SN_LESS(wend, seq_num) IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__, | |
3382 | preorder_ctrl->indicate_seq, seq_num); | |
3383 | #endif | |
3384 | } | |
3385 | ||
3386 | //DbgPrint("exit->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); | |
3387 | ||
3388 | return _TRUE; | |
3389 | } | |
3390 | ||
3391 | int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe); | |
3392 | int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe) | |
3393 | { | |
3394 | struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; | |
3395 | _queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; | |
3396 | _list *phead, *plist; | |
3397 | union recv_frame *pnextrframe; | |
3398 | struct rx_pkt_attrib *pnextattrib; | |
3399 | ||
3400 | //DbgPrint("+enqueue_reorder_recvframe()\n"); | |
3401 | ||
3402 | //_enter_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3403 | //_rtw_spinlock_ex(&ppending_recvframe_queue->lock); | |
3404 | ||
3405 | ||
3406 | phead = get_list_head(ppending_recvframe_queue); | |
3407 | plist = get_next(phead); | |
3408 | ||
3409 | while(rtw_end_of_queue_search(phead, plist) == _FALSE) | |
3410 | { | |
3411 | pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u); | |
3412 | pnextattrib = &pnextrframe->u.hdr.attrib; | |
3413 | ||
3414 | if(SN_LESS(pnextattrib->seq_num, pattrib->seq_num)) | |
3415 | { | |
3416 | plist = get_next(plist); | |
3417 | } | |
3418 | else if( SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num)) | |
3419 | { | |
3420 | //Duplicate entry is found!! Do not insert current entry. | |
3421 | //RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); | |
3422 | ||
3423 | //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3424 | ||
3425 | return _FALSE; | |
3426 | } | |
3427 | else | |
3428 | { | |
3429 | break; | |
3430 | } | |
3431 | ||
3432 | //DbgPrint("enqueue_reorder_recvframe():while\n"); | |
3433 | ||
3434 | } | |
3435 | ||
3436 | ||
3437 | //_enter_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3438 | //_rtw_spinlock_ex(&ppending_recvframe_queue->lock); | |
3439 | ||
3440 | rtw_list_delete(&(prframe->u.hdr.list)); | |
3441 | ||
3442 | rtw_list_insert_tail(&(prframe->u.hdr.list), plist); | |
3443 | ||
3444 | //_rtw_spinunlock_ex(&ppending_recvframe_queue->lock); | |
3445 | //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3446 | ||
3447 | ||
3448 | //RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); | |
3449 | return _TRUE; | |
3450 | ||
3451 | } | |
3452 | ||
3453 | int recv_indicatepkts_in_order(_adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced); | |
3454 | int recv_indicatepkts_in_order(_adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced) | |
3455 | { | |
3456 | //_irqL irql; | |
3457 | //u8 bcancelled; | |
3458 | _list *phead, *plist; | |
3459 | union recv_frame *prframe; | |
3460 | struct rx_pkt_attrib *pattrib; | |
3461 | //u8 index = 0; | |
3462 | int bPktInBuf = _FALSE; | |
3463 | struct recv_priv *precvpriv = &padapter->recvpriv; | |
3464 | _queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; | |
3465 | ||
3466 | //DbgPrint("+recv_indicatepkts_in_order\n"); | |
3467 | ||
3468 | //_enter_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3469 | //_rtw_spinlock_ex(&ppending_recvframe_queue->lock); | |
3470 | ||
3471 | phead = get_list_head(ppending_recvframe_queue); | |
3472 | plist = get_next(phead); | |
3473 | ||
3474 | #if 0 | |
3475 | // Check if there is any other indication thread running. | |
3476 | if(pTS->RxIndicateState == RXTS_INDICATE_PROCESSING) | |
3477 | return; | |
3478 | #endif | |
3479 | ||
3480 | // Handling some condition for forced indicate case. | |
3481 | if(bforced==_TRUE) | |
3482 | { | |
3483 | if(rtw_is_list_empty(phead)) | |
3484 | { | |
3485 | // _exit_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3486 | //_rtw_spinunlock_ex(&ppending_recvframe_queue->lock); | |
3487 | return _TRUE; | |
3488 | } | |
3489 | ||
3490 | prframe = LIST_CONTAINOR(plist, union recv_frame, u); | |
3491 | pattrib = &prframe->u.hdr.attrib; | |
3492 | preorder_ctrl->indicate_seq = pattrib->seq_num; | |
3493 | #ifdef DBG_RX_SEQ | |
3494 | DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__, | |
3495 | preorder_ctrl->indicate_seq, pattrib->seq_num); | |
3496 | #endif | |
3497 | } | |
3498 | ||
3499 | // Prepare indication list and indication. | |
3500 | // Check if there is any packet need indicate. | |
3501 | while(!rtw_is_list_empty(phead)) | |
3502 | { | |
3503 | ||
3504 | prframe = LIST_CONTAINOR(plist, union recv_frame, u); | |
3505 | pattrib = &prframe->u.hdr.attrib; | |
3506 | ||
3507 | if(!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) | |
3508 | { | |
3509 | RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, | |
3510 | ("recv_indicatepkts_in_order: indicate=%d seq=%d amsdu=%d\n", | |
3511 | preorder_ctrl->indicate_seq, pattrib->seq_num, pattrib->amsdu)); | |
3512 | ||
3513 | #if 0 | |
3514 | // This protect buffer from overflow. | |
3515 | if(index >= REORDER_WIN_SIZE) | |
3516 | { | |
3517 | RT_ASSERT(FALSE, ("IndicateRxReorderList(): Buffer overflow!! \n")); | |
3518 | bPktInBuf = TRUE; | |
3519 | break; | |
3520 | } | |
3521 | #endif | |
3522 | ||
3523 | plist = get_next(plist); | |
3524 | rtw_list_delete(&(prframe->u.hdr.list)); | |
3525 | ||
3526 | if(SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num)) | |
3527 | { | |
3528 | preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF; | |
3529 | #ifdef DBG_RX_SEQ | |
3530 | DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__, | |
3531 | preorder_ctrl->indicate_seq, pattrib->seq_num); | |
3532 | #endif | |
3533 | } | |
3534 | ||
3535 | #if 0 | |
3536 | index++; | |
3537 | if(index==1) | |
3538 | { | |
3539 | //Cancel previous pending timer. | |
3540 | //PlatformCancelTimer(Adapter, &pTS->RxPktPendingTimer); | |
3541 | if(bforced!=_TRUE) | |
3542 | { | |
3543 | //DBG_871X("_cancel_timer(&preorder_ctrl->reordering_ctrl_timer, &bcancelled);\n"); | |
3544 | _cancel_timer(&preorder_ctrl->reordering_ctrl_timer, &bcancelled); | |
3545 | } | |
3546 | } | |
3547 | #endif | |
3548 | ||
3549 | //Set this as a lock to make sure that only one thread is indicating packet. | |
3550 | //pTS->RxIndicateState = RXTS_INDICATE_PROCESSING; | |
3551 | ||
3552 | // Indicate packets | |
3553 | //RT_ASSERT((index<=REORDER_WIN_SIZE), ("RxReorderIndicatePacket(): Rx Reorder buffer full!! \n")); | |
3554 | ||
3555 | ||
3556 | //indicate this recv_frame | |
3557 | //DbgPrint("recv_indicatepkts_in_order, indicate_seq=%d, seq_num=%d\n", precvpriv->indicate_seq, pattrib->seq_num); | |
3558 | if(!pattrib->amsdu) | |
3559 | { | |
3560 | //DBG_871X("recv_indicatepkts_in_order, amsdu!=1, indicate_seq=%d, seq_num=%d\n", preorder_ctrl->indicate_seq, pattrib->seq_num); | |
3561 | ||
3562 | if ((padapter->bDriverStopped == _FALSE) && | |
3563 | (padapter->bSurpriseRemoved == _FALSE)) | |
3564 | { | |
3565 | ||
3566 | rtw_recv_indicatepkt(padapter, prframe);//indicate this recv_frame | |
3567 | ||
3568 | } | |
3569 | } | |
3570 | else if(pattrib->amsdu==1) | |
3571 | { | |
3572 | if(amsdu_to_msdu(padapter, prframe)!=_SUCCESS) | |
3573 | { | |
3574 | rtw_free_recvframe(prframe, &precvpriv->free_recv_queue); | |
3575 | } | |
3576 | } | |
3577 | else | |
3578 | { | |
3579 | //error condition; | |
3580 | } | |
3581 | ||
3582 | ||
3583 | //Update local variables. | |
3584 | bPktInBuf = _FALSE; | |
3585 | ||
3586 | } | |
3587 | else | |
3588 | { | |
3589 | bPktInBuf = _TRUE; | |
3590 | break; | |
3591 | } | |
3592 | ||
3593 | //DbgPrint("recv_indicatepkts_in_order():while\n"); | |
3594 | ||
3595 | } | |
3596 | ||
3597 | //_rtw_spinunlock_ex(&ppending_recvframe_queue->lock); | |
3598 | //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3599 | ||
3600 | /* | |
3601 | //Release the indication lock and set to new indication step. | |
3602 | if(bPktInBuf) | |
3603 | { | |
3604 | // Set new pending timer. | |
3605 | //pTS->RxIndicateState = RXTS_INDICATE_REORDER; | |
3606 | //PlatformSetTimer(Adapter, &pTS->RxPktPendingTimer, pHTInfo->RxReorderPendingTime); | |
3607 | //DBG_871X("_set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME)\n"); | |
3608 | _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME); | |
3609 | } | |
3610 | else | |
3611 | { | |
3612 | //pTS->RxIndicateState = RXTS_INDICATE_IDLE; | |
3613 | } | |
3614 | */ | |
3615 | //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3616 | ||
3617 | //return _TRUE; | |
3618 | return bPktInBuf; | |
3619 | ||
3620 | } | |
3621 | ||
3622 | int recv_indicatepkt_reorder(_adapter *padapter, union recv_frame *prframe); | |
3623 | int recv_indicatepkt_reorder(_adapter *padapter, union recv_frame *prframe) | |
3624 | { | |
3625 | _irqL irql; | |
3626 | int retval = _SUCCESS; | |
3627 | struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; | |
3628 | struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl; | |
3629 | _queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; | |
3630 | ||
3631 | if(!pattrib->amsdu) | |
3632 | { | |
3633 | //s1. | |
3634 | wlanhdr_to_ethhdr(prframe); | |
3635 | ||
3636 | //if ((pattrib->qos!=1) /*|| pattrib->priority!=0 || IS_MCAST(pattrib->ra)*/ | |
3637 | // || (pattrib->eth_type==0x0806) || (pattrib->ack_policy!=0)) | |
3638 | if (pattrib->qos!=1) | |
3639 | { | |
3640 | if ((padapter->bDriverStopped == _FALSE) && | |
3641 | (padapter->bSurpriseRemoved == _FALSE)) | |
3642 | { | |
3643 | RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("@@@@ recv_indicatepkt_reorder -recv_func recv_indicatepkt\n" )); | |
3644 | ||
3645 | rtw_recv_indicatepkt(padapter, prframe); | |
3646 | return _SUCCESS; | |
3647 | ||
3648 | } | |
3649 | ||
3650 | #ifdef DBG_RX_DROP_FRAME | |
3651 | DBG_871X("DBG_RX_DROP_FRAME %s pattrib->qos !=1\n", __FUNCTION__); | |
3652 | #endif | |
3653 | ||
3654 | return _FAIL; | |
3655 | ||
3656 | } | |
3657 | ||
3658 | if (preorder_ctrl->enable == _FALSE) | |
3659 | { | |
3660 | //indicate this recv_frame | |
3661 | preorder_ctrl->indicate_seq = pattrib->seq_num; | |
3662 | #ifdef DBG_RX_SEQ | |
3663 | DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__, | |
3664 | preorder_ctrl->indicate_seq, pattrib->seq_num); | |
3665 | #endif | |
3666 | ||
3667 | rtw_recv_indicatepkt(padapter, prframe); | |
3668 | ||
3669 | preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096; | |
3670 | #ifdef DBG_RX_SEQ | |
3671 | DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__, | |
3672 | preorder_ctrl->indicate_seq, pattrib->seq_num); | |
3673 | #endif | |
3674 | ||
3675 | return _SUCCESS; | |
3676 | } | |
3677 | ||
3678 | #ifndef CONFIG_RECV_REORDERING_CTRL | |
3679 | //indicate this recv_frame | |
3680 | rtw_recv_indicatepkt(padapter, prframe); | |
3681 | return _SUCCESS; | |
3682 | #endif | |
3683 | ||
3684 | } | |
3685 | else if(pattrib->amsdu==1) //temp filter -> means didn't support A-MSDUs in a A-MPDU | |
3686 | { | |
3687 | if (preorder_ctrl->enable == _FALSE) | |
3688 | { | |
3689 | preorder_ctrl->indicate_seq = pattrib->seq_num; | |
3690 | #ifdef DBG_RX_SEQ | |
3691 | DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__, | |
3692 | preorder_ctrl->indicate_seq, pattrib->seq_num); | |
3693 | #endif | |
3694 | ||
3695 | retval = amsdu_to_msdu(padapter, prframe); | |
3696 | ||
3697 | preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096; | |
3698 | #ifdef DBG_RX_SEQ | |
3699 | DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__, | |
3700 | preorder_ctrl->indicate_seq, pattrib->seq_num); | |
3701 | #endif | |
3702 | ||
3703 | if(retval != _SUCCESS){ | |
3704 | #ifdef DBG_RX_DROP_FRAME | |
3705 | DBG_871X("DBG_RX_DROP_FRAME %s amsdu_to_msdu fail\n", __FUNCTION__); | |
3706 | #endif | |
3707 | } | |
3708 | ||
3709 | return retval; | |
3710 | } | |
3711 | } | |
3712 | else | |
3713 | { | |
3714 | ||
3715 | } | |
3716 | ||
3717 | _enter_critical_bh(&ppending_recvframe_queue->lock, &irql); | |
3718 | ||
3719 | RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, | |
3720 | ("recv_indicatepkt_reorder: indicate=%d seq=%d\n", | |
3721 | preorder_ctrl->indicate_seq, pattrib->seq_num)); | |
3722 | ||
3723 | //s2. check if winstart_b(indicate_seq) needs to been updated | |
3724 | if(!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) | |
3725 | { | |
3726 | //pHTInfo->RxReorderDropCounter++; | |
3727 | //ReturnRFDList(Adapter, pRfd); | |
3728 | //RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("RxReorderIndicatePacket() ==> Packet Drop!!\n")); | |
3729 | //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3730 | //return _FAIL; | |
3731 | ||
3732 | #ifdef DBG_RX_DROP_FRAME | |
3733 | DBG_871X("DBG_RX_DROP_FRAME %s check_indicate_seq fail\n", __FUNCTION__); | |
3734 | #endif | |
3735 | #if 0 | |
3736 | rtw_recv_indicatepkt(padapter, prframe); | |
3737 | ||
3738 | _exit_critical_bh(&ppending_recvframe_queue->lock, &irql); | |
3739 | ||
3740 | goto _success_exit; | |
3741 | #else | |
3742 | goto _err_exit; | |
3743 | #endif | |
3744 | } | |
3745 | ||
3746 | ||
3747 | //s3. Insert all packet into Reorder Queue to maintain its ordering. | |
3748 | if(!enqueue_reorder_recvframe(preorder_ctrl, prframe)) | |
3749 | { | |
3750 | //DbgPrint("recv_indicatepkt_reorder, enqueue_reorder_recvframe fail!\n"); | |
3751 | //_exit_critical_ex(&ppending_recvframe_queue->lock, &irql); | |
3752 | //return _FAIL; | |
3753 | #ifdef DBG_RX_DROP_FRAME | |
3754 | DBG_871X("DBG_RX_DROP_FRAME %s enqueue_reorder_recvframe fail\n", __FUNCTION__); | |
3755 | #endif | |
3756 | goto _err_exit; | |
3757 | } | |
3758 | ||
3759 | ||
3760 | //s4. | |
3761 | // Indication process. | |
3762 | // After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets | |
3763 | // with the SeqNum smaller than latest WinStart and buffer other packets. | |
3764 | // | |
3765 | // For Rx Reorder condition: | |
3766 | // 1. All packets with SeqNum smaller than WinStart => Indicate | |
3767 | // 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. | |
3768 | // | |
3769 | ||
3770 | //recv_indicatepkts_in_order(padapter, preorder_ctrl, _TRUE); | |
3771 | if(recv_indicatepkts_in_order(padapter, preorder_ctrl, _FALSE)==_TRUE) | |
3772 | { | |
3773 | _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME); | |
3774 | _exit_critical_bh(&ppending_recvframe_queue->lock, &irql); | |
3775 | } | |
3776 | else | |
3777 | { | |
3778 | _exit_critical_bh(&ppending_recvframe_queue->lock, &irql); | |
3779 | _cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer); | |
3780 | } | |
3781 | ||
3782 | ||
3783 | _success_exit: | |
3784 | ||
3785 | return _SUCCESS; | |
3786 | ||
3787 | _err_exit: | |
3788 | ||
3789 | _exit_critical_bh(&ppending_recvframe_queue->lock, &irql); | |
3790 | ||
3791 | return _FAIL; | |
3792 | } | |
3793 | ||
3794 | ||
3795 | void rtw_reordering_ctrl_timeout_handler(void *pcontext) | |
3796 | { | |
3797 | _irqL irql; | |
3798 | struct recv_reorder_ctrl *preorder_ctrl = (struct recv_reorder_ctrl *)pcontext; | |
3799 | _adapter *padapter = preorder_ctrl->padapter; | |
3800 | _queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; | |
3801 | ||
3802 | ||
3803 | if(padapter->bDriverStopped ||padapter->bSurpriseRemoved) | |
3804 | { | |
3805 | return; | |
3806 | } | |
3807 | ||
3808 | //DBG_871X("+rtw_reordering_ctrl_timeout_handler()=>\n"); | |
3809 | ||
3810 | _enter_critical_bh(&ppending_recvframe_queue->lock, &irql); | |
3811 | ||
3812 | if(recv_indicatepkts_in_order(padapter, preorder_ctrl, _TRUE)==_TRUE) | |
3813 | { | |
3814 | _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME); | |
3815 | } | |
3816 | ||
3817 | _exit_critical_bh(&ppending_recvframe_queue->lock, &irql); | |
3818 | ||
3819 | } | |
3820 | ||
3821 | int process_recv_indicatepkts(_adapter *padapter, union recv_frame *prframe); | |
3822 | int process_recv_indicatepkts(_adapter *padapter, union recv_frame *prframe) | |
3823 | { | |
3824 | int retval = _SUCCESS; | |
3825 | //struct recv_priv *precvpriv = &padapter->recvpriv; | |
3826 | //struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; | |
3827 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
3828 | #ifdef CONFIG_TDLS | |
3829 | struct sta_info *psta = prframe->u.hdr.psta; | |
3830 | #endif //CONFIG_TDLS | |
3831 | ||
3832 | #ifdef CONFIG_80211N_HT | |
3833 | ||
3834 | struct ht_priv *phtpriv = &pmlmepriv->htpriv; | |
3835 | ||
3836 | #ifdef CONFIG_TDLS | |
3837 | if( (phtpriv->ht_option==_TRUE) || | |
3838 | ((psta->tdls_sta_state & TDLS_LINKED_STATE) && | |
3839 | (psta->htpriv.ht_option==_TRUE) && | |
3840 | (psta->htpriv.ampdu_enable==_TRUE))) //B/G/N Mode | |
3841 | #else | |
3842 | if(phtpriv->ht_option==_TRUE) //B/G/N Mode | |
3843 | #endif //CONFIG_TDLS | |
3844 | { | |
3845 | //prframe->u.hdr.preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; | |
3846 | ||
3847 | if(recv_indicatepkt_reorder(padapter, prframe)!=_SUCCESS)// including perform A-MPDU Rx Ordering Buffer Control | |
3848 | { | |
3849 | #ifdef DBG_RX_DROP_FRAME | |
3850 | DBG_871X("DBG_RX_DROP_FRAME %s recv_indicatepkt_reorder error!\n", __FUNCTION__); | |
3851 | #endif | |
3852 | ||
3853 | if ((padapter->bDriverStopped == _FALSE) && | |
3854 | (padapter->bSurpriseRemoved == _FALSE)) | |
3855 | { | |
3856 | retval = _FAIL; | |
3857 | return retval; | |
3858 | } | |
3859 | } | |
3860 | } | |
3861 | else //B/G mode | |
3862 | #endif | |
3863 | { | |
3864 | retval=wlanhdr_to_ethhdr (prframe); | |
3865 | if(retval != _SUCCESS) | |
3866 | { | |
3867 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("wlanhdr_to_ethhdr: drop pkt \n")); | |
3868 | #ifdef DBG_RX_DROP_FRAME | |
3869 | DBG_871X("DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr error!\n", __FUNCTION__); | |
3870 | #endif | |
3871 | return retval; | |
3872 | } | |
3873 | ||
3874 | if ((padapter->bDriverStopped ==_FALSE)&&( padapter->bSurpriseRemoved==_FALSE)) | |
3875 | { | |
3876 | //indicate this recv_frame | |
3877 | RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ process_recv_indicatepkts- recv_func recv_indicatepkt\n" )); | |
3878 | rtw_recv_indicatepkt(padapter, prframe); | |
3879 | ||
3880 | ||
3881 | } | |
3882 | else | |
3883 | { | |
3884 | RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ process_recv_indicatepkts- recv_func free_indicatepkt\n" )); | |
3885 | ||
3886 | RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved)); | |
3887 | retval = _FAIL; | |
3888 | return retval; | |
3889 | } | |
3890 | ||
3891 | } | |
3892 | ||
3893 | return retval; | |
3894 | ||
3895 | } | |
3896 | ||
1130c632 | 3897 | static int recv_func_prehandle(_adapter *padapter, union recv_frame *rframe) |
abb3b3dc | 3898 | { |
3899 | int ret = _SUCCESS; | |
3900 | struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib; | |
3901 | struct recv_priv *precvpriv = &padapter->recvpriv; | |
3902 | _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; | |
3903 | ||
3904 | #ifdef CONFIG_MP_INCLUDED | |
3905 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
3906 | #endif //CONFIG_MP_INCLUDED | |
3907 | ||
3908 | #ifdef CONFIG_MP_INCLUDED | |
3909 | if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE))//&&(padapter->mppriv.check_mp_pkt == 0)) | |
3910 | { | |
3911 | if (pattrib->crc_err == 1) | |
3912 | padapter->mppriv.rx_crcerrpktcount++; | |
3913 | else | |
3914 | padapter->mppriv.rx_pktcount++; | |
3915 | ||
3916 | if (check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE) == _FALSE) { | |
3917 | RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("MP - Not in loopback mode , drop pkt \n")); | |
3918 | ret = _FAIL; | |
3919 | rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame | |
3920 | goto exit; | |
3921 | } | |
3922 | } | |
3923 | #endif | |
3924 | ||
3925 | //check the frame crtl field and decache | |
3926 | ret = validate_recv_frame(padapter, rframe); | |
3927 | if (ret != _SUCCESS) | |
3928 | { | |
3929 | RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n")); | |
3930 | rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame | |
3931 | goto exit; | |
3932 | } | |
3933 | ||
3934 | exit: | |
3935 | return ret; | |
3936 | } | |
3937 | ||
1130c632 | 3938 | static int recv_func_posthandle(_adapter *padapter, union recv_frame *prframe) |
abb3b3dc | 3939 | { |
3940 | int ret = _SUCCESS; | |
3941 | union recv_frame *orig_prframe = prframe; | |
3942 | struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; | |
3943 | struct recv_priv *precvpriv = &padapter->recvpriv; | |
3944 | _queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; | |
3945 | ||
3946 | #ifdef CONFIG_MP_INCLUDED | |
3947 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; | |
3948 | #endif //CONFIG_MP_INCLUDED | |
3949 | ||
3950 | #ifdef CONFIG_TDLS | |
3951 | u8 *psnap_type, *pcategory; | |
3952 | struct sta_info *ptdls_sta = NULL; | |
3953 | #endif //CONFIG_TDLS | |
3954 | ||
3955 | ||
3956 | // DATA FRAME | |
3957 | rtw_led_control(padapter, LED_CTL_RX); | |
3958 | ||
3959 | prframe = decryptor(padapter, prframe); | |
3960 | if (prframe == NULL) { | |
3961 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("decryptor: drop pkt\n")); | |
3962 | #ifdef DBG_RX_DROP_FRAME | |
3963 | DBG_871X("DBG_RX_DROP_FRAME %s decryptor: drop pkt\n", __FUNCTION__); | |
3964 | #endif | |
3965 | ret = _FAIL; | |
3966 | goto _recv_data_drop; | |
3967 | } | |
3968 | ||
3969 | #if 0 | |
3970 | if ( padapter->adapter_type == PRIMARY_ADAPTER ) | |
3971 | { | |
3972 | DBG_871X("+++\n"); | |
3973 | { | |
3974 | int i; | |
3975 | u8 *ptr = get_recvframe_data(prframe); | |
3976 | for(i=0; i<140;i=i+8) | |
3977 | DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:", *(ptr+i), | |
3978 | *(ptr+i+1), *(ptr+i+2) ,*(ptr+i+3) ,*(ptr+i+4),*(ptr+i+5), *(ptr+i+6), *(ptr+i+7)); | |
3979 | ||
3980 | } | |
3981 | DBG_871X("---\n"); | |
3982 | } | |
3983 | #endif //RTK_DMP_PLATFORM | |
3984 | ||
3985 | #ifdef CONFIG_TDLS | |
3986 | //check TDLS frame | |
3987 | psnap_type = get_recvframe_data(orig_prframe); | |
3988 | psnap_type+=pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE; | |
3989 | pcategory = psnap_type + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN; | |
3990 | ||
3991 | if((_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_TDLS, ETH_TYPE_LEN)) && | |
3992 | ((*pcategory==RTW_WLAN_CATEGORY_TDLS) || (*pcategory==RTW_WLAN_CATEGORY_P2P))){ | |
3993 | ret = OnTDLS(padapter, prframe); //all of functions will return _FAIL | |
3994 | goto _exit_recv_func; | |
3995 | } | |
3996 | #endif //CONFIG_TDLS | |
3997 | ||
3998 | prframe = recvframe_chk_defrag(padapter, prframe); | |
3999 | if(prframe==NULL) { | |
4000 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvframe_chk_defrag: drop pkt\n")); | |
4001 | #ifdef DBG_RX_DROP_FRAME | |
4002 | DBG_871X("DBG_RX_DROP_FRAME %s recvframe_chk_defrag: drop pkt\n", __FUNCTION__); | |
4003 | #endif | |
4004 | goto _recv_data_drop; | |
4005 | } | |
4006 | ||
4007 | prframe=portctrl(padapter, prframe); | |
4008 | if (prframe == NULL) { | |
4009 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("portctrl: drop pkt \n")); | |
4010 | #ifdef DBG_RX_DROP_FRAME | |
4011 | DBG_871X("DBG_RX_DROP_FRAME %s portctrl: drop pkt\n", __FUNCTION__); | |
4012 | #endif | |
4013 | ret = _FAIL; | |
4014 | goto _recv_data_drop; | |
4015 | } | |
4016 | ||
4017 | #ifdef CONFIG_TDLS | |
4018 | if(padapter->tdlsinfo.setup_state == TDLS_LINKED_STATE) | |
4019 | ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->src); | |
4020 | count_rx_stats(padapter, prframe, ptdls_sta); | |
4021 | #else | |
4022 | count_rx_stats(padapter, prframe, NULL); | |
4023 | #endif //CONFIG_TDLS | |
4024 | ||
4025 | #ifdef CONFIG_80211N_HT | |
4026 | ||
4027 | ret = process_recv_indicatepkts(padapter, prframe); | |
4028 | if (ret != _SUCCESS) | |
4029 | { | |
4030 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recv_func: process_recv_indicatepkts fail! \n")); | |
4031 | #ifdef DBG_RX_DROP_FRAME | |
4032 | DBG_871X("DBG_RX_DROP_FRAME %s recv_func: process_recv_indicatepkts fail!\n", __FUNCTION__); | |
4033 | #endif | |
4034 | rtw_free_recvframe(orig_prframe, pfree_recv_queue);//free this recv_frame | |
4035 | goto _recv_data_drop; | |
4036 | } | |
4037 | ||
4038 | #else // CONFIG_80211N_HT | |
4039 | ||
4040 | if (!pattrib->amsdu) | |
4041 | { | |
4042 | ret = wlanhdr_to_ethhdr (prframe); | |
4043 | if (ret != _SUCCESS) | |
4044 | { | |
4045 | RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("wlanhdr_to_ethhdr: drop pkt \n")); | |
4046 | #ifdef DBG_RX_DROP_FRAME | |
4047 | DBG_871X("DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr: drop pkt\n", __FUNCTION__); | |
4048 | #endif | |
4049 | rtw_free_recvframe(orig_prframe, pfree_recv_queue);//free this recv_frame | |
4050 | goto _recv_data_drop; | |
4051 | } | |
4052 | ||
4053 | if ((padapter->bDriverStopped == _FALSE) && (padapter->bSurpriseRemoved == _FALSE)) | |
4054 | { | |
4055 | RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("@@@@ recv_func: recv_func rtw_recv_indicatepkt\n" )); | |
4056 | //indicate this recv_frame | |
4057 | ret = rtw_recv_indicatepkt(padapter, prframe); | |
4058 | if (ret != _SUCCESS) | |
4059 | { | |
4060 | #ifdef DBG_RX_DROP_FRAME | |
4061 | DBG_871X("DBG_RX_DROP_FRAME %s rtw_recv_indicatepkt fail!\n", __FUNCTION__); | |
4062 | #endif | |
4063 | goto _recv_data_drop; | |
4064 | } | |
4065 | } | |
4066 | else | |
4067 | { | |
4068 | RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("@@@@ recv_func: rtw_free_recvframe\n" )); | |
4069 | RT_TRACE(_module_rtl871x_recv_c_, _drv_debug_, ("recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved)); | |
4070 | #ifdef DBG_RX_DROP_FRAME | |
4071 | DBG_871X("DBG_RX_DROP_FRAME %s ecv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)\n", __FUNCTION__, | |
4072 | padapter->bDriverStopped, padapter->bSurpriseRemoved); | |
4073 | #endif | |
4074 | ret = _FAIL; | |
4075 | rtw_free_recvframe(orig_prframe, pfree_recv_queue); //free this recv_frame | |
4076 | } | |
4077 | ||
4078 | } | |
4079 | else if(pattrib->amsdu==1) | |
4080 | { | |
4081 | ||
4082 | ret = amsdu_to_msdu(padapter, prframe); | |
4083 | if(ret != _SUCCESS) | |
4084 | { | |
4085 | #ifdef DBG_RX_DROP_FRAME | |
4086 | DBG_871X("DBG_RX_DROP_FRAME %s amsdu_to_msdu fail\n", __FUNCTION__); | |
4087 | #endif | |
4088 | rtw_free_recvframe(orig_prframe, pfree_recv_queue); | |
4089 | goto _recv_data_drop; | |
4090 | } | |
4091 | } | |
4092 | else | |
4093 | { | |
4094 | #ifdef DBG_RX_DROP_FRAME | |
4095 | DBG_871X("DBG_RX_DROP_FRAME %s what is this condition??\n", __FUNCTION__); | |
4096 | #endif | |
4097 | goto _recv_data_drop; | |
4098 | } | |
4099 | #endif // CONFIG_80211N_HT | |
4100 | ||
4101 | _exit_recv_func: | |
4102 | return ret; | |
4103 | ||
4104 | _recv_data_drop: | |
4105 | precvpriv->rx_drop++; | |
4106 | return ret; | |
4107 | } | |
4108 | ||
4109 | ||
1130c632 | 4110 | static int recv_func(_adapter *padapter, union recv_frame *rframe) |
abb3b3dc | 4111 | { |
4112 | int ret; | |
4113 | struct rx_pkt_attrib *prxattrib = &rframe->u.hdr.attrib; | |
4114 | struct recv_priv *recvpriv = &padapter->recvpriv; | |
4115 | struct security_priv *psecuritypriv=&padapter->securitypriv; | |
4116 | struct mlme_priv *mlmepriv = &padapter->mlmepriv; | |
4117 | ||
4118 | /* check if need to handle uc_swdec_pending_queue*/ | |
4119 | if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) | |
4120 | { | |
4121 | union recv_frame *pending_frame; | |
4122 | _irqL irqL; | |
4123 | ||
4124 | while((pending_frame=rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) { | |
4125 | if (recv_func_posthandle(padapter, pending_frame) == _SUCCESS) | |
4126 | DBG_871X("%s: dequeue uc_swdec_pending_queue\n", __func__); | |
4127 | } | |
4128 | } | |
4129 | ||
4130 | ret = recv_func_prehandle(padapter, rframe); | |
4131 | ||
4132 | if(ret == _SUCCESS) { | |
4133 | ||
4134 | /* check if need to enqueue into uc_swdec_pending_queue*/ | |
4135 | if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && | |
4136 | !IS_MCAST(prxattrib->ra) && prxattrib->encrypt>0 && | |
4137 | (prxattrib->bdecrypted == 0 ||psecuritypriv->sw_decrypt == _TRUE) && | |
4138 | !is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm) && | |
4139 | !psecuritypriv->busetkipkey) { | |
4140 | rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue); | |
4141 | DBG_871X("%s: no key, enqueue uc_swdec_pending_queue\n", __func__); | |
4142 | goto exit; | |
4143 | } | |
4144 | ||
4145 | ret = recv_func_posthandle(padapter, rframe); | |
4146 | } | |
4147 | ||
4148 | exit: | |
4149 | return ret; | |
4150 | } | |
4151 | ||
4152 | ||
4153 | s32 rtw_recv_entry(union recv_frame *precvframe) | |
4154 | { | |
4155 | _adapter *padapter; | |
4156 | struct recv_priv *precvpriv; | |
4157 | s32 ret=_SUCCESS; | |
4158 | ||
4159 | _func_enter_; | |
4160 | ||
4161 | // RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("+rtw_recv_entry\n")); | |
4162 | ||
4163 | padapter = precvframe->u.hdr.adapter; | |
4164 | ||
4165 | precvpriv = &padapter->recvpriv; | |
4166 | ||
4167 | ||
4168 | if ((ret = recv_func(padapter, precvframe)) == _FAIL) | |
4169 | { | |
4170 | RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("rtw_recv_entry: recv_func return fail!!!\n")); | |
4171 | goto _recv_entry_drop; | |
4172 | } | |
4173 | ||
4174 | ||
4175 | precvpriv->rx_pkts++; | |
4176 | ||
4177 | _func_exit_; | |
4178 | ||
4179 | return ret; | |
4180 | ||
4181 | _recv_entry_drop: | |
4182 | ||
4183 | #ifdef CONFIG_MP_INCLUDED | |
4184 | padapter->mppriv.rx_pktloss = precvpriv->rx_drop; | |
4185 | #endif | |
4186 | ||
4187 | //RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("_recv_entry_drop\n")); | |
4188 | ||
4189 | _func_exit_; | |
4190 | ||
4191 | return ret; | |
4192 | } | |
4193 | ||
4194 | #ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS | |
4195 | void rtw_signal_stat_timer_hdl(RTW_TIMER_HDL_ARGS){ | |
4196 | _adapter *adapter = (_adapter *)FunctionContext; | |
4197 | struct recv_priv *recvpriv = &adapter->recvpriv; | |
4198 | ||
4199 | u32 tmp_s, tmp_q; | |
4200 | u8 avg_signal_strength = 0; | |
4201 | u8 avg_signal_qual = 0; | |
4202 | u32 num_signal_strength = 0; | |
4203 | u32 num_signal_qual = 0; | |
4204 | u8 _alpha = 3; // this value is based on converging_constant = 5000 and sampling_interval = 1000 | |
4205 | ||
4206 | if(adapter->recvpriv.is_signal_dbg) { | |
4207 | //update the user specific value, signal_strength_dbg, to signal_strength, rssi | |
4208 | adapter->recvpriv.signal_strength= adapter->recvpriv.signal_strength_dbg; | |
4209 | adapter->recvpriv.rssi=(s8)translate_percentage_to_dbm((u8)adapter->recvpriv.signal_strength_dbg); | |
4210 | } else { | |
4211 | ||
4212 | if(recvpriv->signal_strength_data.update_req == 0) {// update_req is clear, means we got rx | |
4213 | avg_signal_strength = recvpriv->signal_strength_data.avg_val; | |
4214 | num_signal_strength = recvpriv->signal_strength_data.total_num; | |
4215 | // after avg_vals are accquired, we can re-stat the signal values | |
4216 | recvpriv->signal_strength_data.update_req = 1; | |
4217 | } | |
4218 | ||
4219 | if(recvpriv->signal_qual_data.update_req == 0) {// update_req is clear, means we got rx | |
4220 | avg_signal_qual = recvpriv->signal_qual_data.avg_val; | |
4221 | num_signal_qual = recvpriv->signal_qual_data.total_num; | |
4222 | // after avg_vals are accquired, we can re-stat the signal values | |
4223 | recvpriv->signal_qual_data.update_req = 1; | |
4224 | } | |
4225 | ||
4226 | if (num_signal_strength == 0) { | |
4227 | if (rtw_get_on_cur_ch_time(adapter) == 0 | |
4228 | || rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) < 2 * adapter->mlmeextpriv.mlmext_info.bcn_interval | |
4229 | ) { | |
4230 | goto set_timer; | |
4231 | } | |
4232 | } | |
4233 | ||
4234 | if(check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == _TRUE | |
4235 | || check_fwstate(&adapter->mlmepriv, _FW_LINKED) == _FALSE | |
4236 | ) { | |
4237 | goto set_timer; | |
4238 | } | |
4239 | ||
4240 | #ifdef CONFIG_CONCURRENT_MODE | |
4241 | if (check_buddy_fwstate(adapter, _FW_UNDER_SURVEY) == _TRUE) | |
4242 | goto set_timer; | |
4243 | #endif | |
4244 | ||
4245 | //update value of signal_strength, rssi, signal_qual | |
4246 | tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength); | |
4247 | if(tmp_s %_alpha) | |
4248 | tmp_s = tmp_s/_alpha + 1; | |
4249 | else | |
4250 | tmp_s = tmp_s/_alpha; | |
4251 | if(tmp_s>100) | |
4252 | tmp_s = 100; | |
4253 | ||
4254 | tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual); | |
4255 | if(tmp_q %_alpha) | |
4256 | tmp_q = tmp_q/_alpha + 1; | |
4257 | else | |
4258 | tmp_q = tmp_q/_alpha; | |
4259 | if(tmp_q>100) | |
4260 | tmp_q = 100; | |
4261 | ||
4262 | recvpriv->signal_strength = tmp_s; | |
4263 | recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s); | |
4264 | recvpriv->signal_qual = tmp_q; | |
4265 | ||
4266 | #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1 | |
4267 | DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u" | |
4268 | ", num_signal_strength:%u, num_signal_qual:%u" | |
4269 | ", on_cur_ch_ms:%d" | |
4270 | "\n" | |
4271 | , FUNC_ADPT_ARG(adapter) | |
4272 | , recvpriv->signal_strength | |
4273 | , recvpriv->rssi | |
4274 | , recvpriv->signal_qual | |
4275 | , num_signal_strength, num_signal_qual | |
4276 | , rtw_get_on_cur_ch_time(adapter) ? rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) : 0 | |
4277 | ); | |
4278 | #endif | |
4279 | } | |
4280 | ||
4281 | set_timer: | |
4282 | rtw_set_signal_stat_timer(recvpriv); | |
4283 | ||
4284 | } | |
4285 | #endif //CONFIG_NEW_SIGNAL_STAT_PROCESS |