1 /** @file mlan_sta_rx.c
2  *
3  *  @brief  This file provides  handling of RX in MLA  module.
4  *
5  *  Copyright 2008-2024 NXP
6  *
7  *  SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 
11 /********************************************************
12 Change log:
13     10/27/2008: initial version
14 ********************************************************/
15 #include <mlan_api.h>
16 
17 /* Additional WMSDK header files */
18 #include <wmerrno.h>
19 #include <osa.h>
20 
21 /* Always keep this include at the end of all include files */
22 #include <mlan_remap_mem_operations.h>
23 /********************************************************
24   Local Variables
25 ********************************************************/
26 
27 /** Ethernet II header */
28 typedef struct
29 {
30     /** Ethernet II header destination address */
31     t_u8 dest_addr[MLAN_MAC_ADDR_LENGTH];
32     /** Ethernet II header source address */
33     t_u8 src_addr[MLAN_MAC_ADDR_LENGTH];
34     /** Ethernet II header length */
35     t_u16 ethertype;
36 
37 } EthII_Hdr_t;
38 
39 /** IPv4 ARP request header */
40 typedef MLAN_PACK_START struct
41 {
42     /** Hardware type */
43     t_u16 Htype;
44     /** Protocol type */
45     t_u16 Ptype;
46     /** Hardware address length */
47     t_u8 addr_len;
48     /** Protocol address length */
49     t_u8 proto_len;
50     /** Operation code */
51     t_u16 op_code;
52     /** Source mac address */
53     t_u8 src_mac[MLAN_MAC_ADDR_LENGTH];
54     /** Sender IP address */
55     t_u8 src_ip[4];
56     /** Destination mac address */
57     t_u8 dst_mac[MLAN_MAC_ADDR_LENGTH];
58     /** Destination IP address */
59     t_u8 dst_ip[4];
60 } MLAN_PACK_END IPv4_ARP_t;
61 
62 /** IPv6 Nadv packet header */
63 typedef MLAN_PACK_START struct
64 {
65     /** IP protocol version */
66     t_u8 version;
67     /** flow label */
68     t_u8 flow_lab[3];
69     /** Payload length */
70     t_u16 payload_len;
71     /** Next header type */
72     t_u8 next_hdr;
73     /** Hot limit */
74     t_u8 hop_limit;
75     /** Source address */
76     t_u8 src_addr[16];
77     /** Destination address */
78     t_u8 dst_addr[16];
79     /** ICMP type */
80     t_u8 icmp_type;
81     /** IPv6 Code */
82     t_u8 ipv6_code;
83     /** IPv6 Checksum */
84     t_u16 ipv6_checksum;
85     /** Flags */
86     t_u32 flags;
87     /** Target address */
88     t_u8 taget_addr[16];
89     /** Reserved */
90     t_u8 rev[8];
91 } MLAN_PACK_END IPv6_Nadv_t;
92 
93 /********************************************************
94   Global Variables
95 ********************************************************/
96 
97 /********************************************************
98   Local Functions
99 ********************************************************/
100 
101 /********************************************************
102   Global functions
103 ********************************************************/
104 /**
105  *  @brief This function processes received packet and forwards it
106  *  		to kernel/upper layer
107  *
108  *  @param pmadapter A pointer to mlan_adapter
109  *  @param pmbuf     A pointer to mlan_buffer which includes the received packet
110  *
111  *  @return 	   MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
112  */
wlan_process_rx_packet(pmlan_adapter pmadapter,pmlan_buffer pmbuf)113 mlan_status wlan_process_rx_packet(pmlan_adapter pmadapter, pmlan_buffer pmbuf)
114 {
115     mlan_status ret    = MLAN_STATUS_SUCCESS;
116     pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
117     /* RxPacketHdr_t *prx_pkt; */
118     RxPD *prx_pd;
119     ENTER();
120 
121     prx_pd = (RxPD *)(void *)(pmbuf->pbuf + pmbuf->data_offset);
122     /* Note: Important. We do not have actual data @ prx_pd->rx_pkt_offset */
123     /* prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */
124     /* prx_pkt = (RxPacketHdr_t *)pmbuf->pdesc; */
125 
126 /** Small debug type */
127 #define DBG_TYPE_SMALL 2
128 /** Size of debugging structure */
129 #define SIZE_OF_DBG_STRUCT 4
130     /*
131        This additional processing does not seem to be required by us for
132        the moment. Let skip it for now. They seem to be doing some kind of
133        ethernet header processing.
134     */
135     priv->rxpd_rate = prx_pd->rx_rate;
136 #ifdef SD8801
137     priv->rxpd_htinfo = prx_pd->ht_info;
138 #else
139     priv->rxpd_rate_info = prx_pd->rate_info;
140 #endif
141 
142 #if CONFIG_WIFI_PKT_FWD
143     if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) && priv->pkt_fwd)
144     {
145         /* Check if needs to do packet forwarding */
146         ret = wlan_process_uap_rx_packet(priv, pmbuf);
147         goto done;
148     }
149 #endif
150     ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf);
151     if (ret == MLAN_STATUS_FAILURE)
152     {
153         pmbuf->status_code = (t_u32)MLAN_ERROR_PKT_INVALID;
154         PRINTM(MERROR, "Rx Error: moal_recv_packet returned error\n");
155     }
156 
157 #if CONFIG_WIFI_PKT_FWD
158 done:
159 #endif
160     if (ret != MLAN_STATUS_PENDING)
161     {
162         wlan_free_mlan_buffer(pmadapter, pmbuf);
163     }
164     LEAVE();
165 
166     return ret;
167 }
168 
169 /**
170  *   @brief This function processes the received buffer
171  *
172  *   @param adapter A pointer to mlan_adapter
173  *   @param pmbuf     A pointer to the received buffer
174  *
175  *   @return        MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
176  */
wlan_ops_process_rx_packet(IN t_void * adapter,IN pmlan_buffer pmbuf)177 mlan_status wlan_ops_process_rx_packet(IN t_void *adapter, IN pmlan_buffer pmbuf)
178 {
179     pmlan_adapter pmadapter = (pmlan_adapter)adapter;
180     mlan_status ret         = MLAN_STATUS_SUCCESS;
181     RxPD *prx_pd;
182     RxPacketHdr_t *prx_pkt;
183     pmlan_private priv            = pmadapter->priv[pmbuf->bss_index];
184     t_u8 ta[MLAN_MAC_ADDR_LENGTH] = {0};
185     t_u16 rx_pkt_type             = 0;
186 #if CONFIG_P2P
187     wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL;
188 #endif /* CONFIG_P2P */
189     ENTER();
190     TxBAStreamTbl *ptx_tbl = NULL;
191 
192     prx_pd = (RxPD *)(void *)(pmbuf->pbuf + pmbuf->data_offset);
193     /* Endian conversion */
194     endian_convert_RxPD(prx_pd);
195     rx_pkt_type = prx_pd->rx_pkt_type;
196 
197     /* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */
198     /* prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */
199     prx_pkt = (RxPacketHdr_t *)pmbuf->pdesc;
200 
201     /* PRINTM(MMSG, "%p + %d: O: %d PL: %d DL: %d\n\r", */
202     /* 	     pmbuf->pbuf, pmbuf->data_offset, */
203     /* 	     prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length, pmbuf->data_len); */
204 
205     if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16)pmbuf->data_len)
206     {
207         PRINTM(MERROR,
208                "Wrong rx packet: len=%d,rx_pkt_offset=%d,"
209                " rx_pkt_length=%d\n",
210                pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length);
211         pmbuf->status_code = (t_u32)MLAN_ERROR_PKT_SIZE_INVALID;
212         ret                = MLAN_STATUS_FAILURE;
213         wlan_free_mlan_buffer(pmadapter, pmbuf);
214         goto done;
215     }
216     pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length;
217 
218     if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME)
219     {
220         /* Check if this is mgmt packet and needs to forwarded to app as an
221            event */
222 #if CONFIG_P2P
223         /* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */
224         /* pmgmt_pkt_hdr = */
225         /*     (wlan_mgmt_pkt *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */
226         pmgmt_pkt_hdr = (wlan_mgmt_pkt *)pmbuf->pdesc;
227 
228         pmgmt_pkt_hdr->frm_len = wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len);
229 
230         if ((pmgmt_pkt_hdr->wlan_header.frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0)
231         {
232             ret = wlan_process_802dot11_mgmt_pkt(
233                 pmadapter->priv[pmbuf->bss_index], (t_u8 *)&pmgmt_pkt_hdr->wlan_header,
234                 pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr->frm_len), prx_pd);
235         }
236         wlan_free_mlan_buffer(pmadapter, pmbuf);
237         /* Free RxPD */
238         OSA_MemoryFree(pmbuf->pbuf);
239         OSA_MemoryFree(pmbuf);
240         goto done;
241 #else
242         /* fixme */
243         wifi_e("Is a management packet expected here?");
244         while (true)
245         {
246             OSA_TimeDelay(10);
247         }
248 #endif /* CONFIG_P2P */
249     }
250 
251 #ifdef DUMP_PACKET_MAC
252     dump_mac_addr("Own: ", priv->curr_addr);
253     dump_mac_addr("Dest: ", prx_pkt->eth803_hdr.dest_addr);
254 #endif /* DUMP_PACKET_MAC */
255 
256     if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
257     {
258         /* txbastream table also is used as connected STAs data base */
259         ptx_tbl = wlan_11n_get_txbastream_tbl(priv, prx_pkt->eth803_hdr.src_addr);
260     }
261 
262     /*
263      * If 11n isn't enabled, or if the packet is not an unicast packet for STA case,
264      * then send the packet directly to os. Don't pass thru rx reordering
265      */
266     if (((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
267          ((!IS_11N_ENABLED(priv)) ||
268           __memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH))) ||
269         ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) && ptx_tbl && (!ptx_tbl->ampdu_supported[0])))
270     {
271         (void)wlan_process_rx_packet(pmadapter, pmbuf);
272         goto done;
273     }
274 
275     if (queuing_ra_based(priv) == MTRUE)
276     {
277         if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) && ptx_tbl && (rx_pkt_type != PKT_TYPE_BAR) &&
278             (prx_pd->priority < MAX_NUM_TID))
279         {
280             ptx_tbl->rx_seq[prx_pd->priority] = prx_pd->seq_num;
281         }
282         (void)__memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH);
283     }
284     else
285     {
286         if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID))
287         {
288             priv->rx_seq[prx_pd->priority] = prx_pd->seq_num;
289         }
290         (void)__memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH);
291     }
292 
293     /* Reorder and send to OS */
294     if ((ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8)prx_pd->rx_pkt_type,
295                                       (void *)pmbuf)) ||
296         (rx_pkt_type == PKT_TYPE_BAR))
297     {
298         wlan_free_mlan_buffer(pmadapter, pmbuf);
299     }
300 
301 done:
302 
303     LEAVE();
304     return (ret);
305 }
306