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