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 ret = pmadapter->callbacks.moal_recv_packet(pmadapter->pmoal_handle, pmbuf);
142 if (ret == MLAN_STATUS_FAILURE)
143 {
144 pmbuf->status_code = (t_u32)MLAN_ERROR_PKT_INVALID;
145 PRINTM(MERROR, "STA Rx Error: moal_recv_packet returned error\n");
146 }
147 /* done: */
148 if (ret != MLAN_STATUS_PENDING)
149 {
150 wlan_free_mlan_buffer(pmadapter, pmbuf);
151 }
152 LEAVE();
153
154 return ret;
155 }
156
157 /**
158 * @brief This function processes the received buffer
159 *
160 * @param adapter A pointer to mlan_adapter
161 * @param pmbuf A pointer to the received buffer
162 *
163 * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
164 */
wlan_ops_process_rx_packet(IN t_void * adapter,IN pmlan_buffer pmbuf)165 mlan_status wlan_ops_process_rx_packet(IN t_void *adapter, IN pmlan_buffer pmbuf)
166 {
167 pmlan_adapter pmadapter = (pmlan_adapter)adapter;
168 mlan_status ret = MLAN_STATUS_SUCCESS;
169 RxPD *prx_pd;
170 RxPacketHdr_t *prx_pkt;
171 pmlan_private priv = pmadapter->priv[pmbuf->bss_index];
172 t_u8 ta[MLAN_MAC_ADDR_LENGTH] = {0};
173 t_u16 rx_pkt_type = 0;
174 #if CONFIG_P2P
175 wlan_mgmt_pkt *pmgmt_pkt_hdr = MNULL;
176 #endif /* CONFIG_P2P */
177 ENTER();
178 TxBAStreamTbl *ptx_tbl = NULL;
179
180 prx_pd = (RxPD *)(void *)(pmbuf->pbuf + pmbuf->data_offset);
181 /* Endian conversion */
182 endian_convert_RxPD(prx_pd);
183 rx_pkt_type = prx_pd->rx_pkt_type;
184
185 /* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */
186 /* prx_pkt = (RxPacketHdr_t *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */
187 prx_pkt = (RxPacketHdr_t *)pmbuf->pdesc;
188
189 /* PRINTM(MMSG, "%p + %d: O: %d PL: %d DL: %d\n\r", */
190 /* pmbuf->pbuf, pmbuf->data_offset, */
191 /* prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length, pmbuf->data_len); */
192
193 if ((prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length) > (t_u16)pmbuf->data_len)
194 {
195 PRINTM(MERROR,
196 "Wrong rx packet: len=%d,rx_pkt_offset=%d,"
197 " rx_pkt_length=%d\n",
198 pmbuf->data_len, prx_pd->rx_pkt_offset, prx_pd->rx_pkt_length);
199 pmbuf->status_code = (t_u32)MLAN_ERROR_PKT_SIZE_INVALID;
200 ret = MLAN_STATUS_FAILURE;
201 wlan_free_mlan_buffer(pmadapter, pmbuf);
202 goto done;
203 }
204 pmbuf->data_len = prx_pd->rx_pkt_offset + prx_pd->rx_pkt_length;
205
206 if (pmadapter->priv[pmbuf->bss_index]->mgmt_frame_passthru_mask && prx_pd->rx_pkt_type == PKT_TYPE_MGMT_FRAME)
207 {
208 /* Check if this is mgmt packet and needs to forwarded to app as an
209 event */
210 #if CONFIG_P2P
211 /* Note: We do not have data @ some offset of pbuf. pbuf only has RxPD */
212 /* pmgmt_pkt_hdr = */
213 /* (wlan_mgmt_pkt *) ((t_u8 *) prx_pd + prx_pd->rx_pkt_offset); */
214 pmgmt_pkt_hdr = (wlan_mgmt_pkt *)pmbuf->pdesc;
215
216 pmgmt_pkt_hdr->frm_len = wlan_le16_to_cpu(pmgmt_pkt_hdr->frm_len);
217
218 if ((pmgmt_pkt_hdr->wlan_header.frm_ctl & IEEE80211_FC_MGMT_FRAME_TYPE_MASK) == 0)
219 {
220 ret = wlan_process_802dot11_mgmt_pkt(
221 pmadapter->priv[pmbuf->bss_index], (t_u8 *)&pmgmt_pkt_hdr->wlan_header,
222 pmgmt_pkt_hdr->frm_len + sizeof(wlan_mgmt_pkt) - sizeof(pmgmt_pkt_hdr->frm_len), prx_pd);
223 }
224 wlan_free_mlan_buffer(pmadapter, pmbuf);
225 /* Free RxPD */
226 OSA_MemoryFree(pmbuf->pbuf);
227 OSA_MemoryFree(pmbuf);
228 goto done;
229 #else
230 /* fixme */
231 wifi_e("Is a management packet expected here?");
232 while (true)
233 {
234 OSA_TimeDelay(10);
235 }
236 #endif /* CONFIG_P2P */
237 }
238
239 #ifdef DUMP_PACKET_MAC
240 dump_mac_addr("Own: ", priv->curr_addr);
241 dump_mac_addr("Dest: ", prx_pkt->eth803_hdr.dest_addr);
242 #endif /* DUMP_PACKET_MAC */
243
244 if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
245 {
246 /* txbastream table also is used as connected STAs data base */
247 ptx_tbl = wlan_11n_get_txbastream_tbl(priv, prx_pkt->eth803_hdr.src_addr);
248 }
249
250 /*
251 * If 11n isn't enabled, or if the packet is not an unicast packet for STA case,
252 * then send the packet directly to os. Don't pass thru rx reordering
253 */
254 if (((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_STA) &&
255 ((!IS_11N_ENABLED(priv)) ||
256 __memcmp(priv->adapter, priv->curr_addr, prx_pkt->eth803_hdr.dest_addr, MLAN_MAC_ADDR_LENGTH))) ||
257 ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) && ptx_tbl && (!ptx_tbl->ampdu_supported[0])))
258 {
259 (void)wlan_process_rx_packet(pmadapter, pmbuf);
260 goto done;
261 }
262
263 if (queuing_ra_based(priv) == MTRUE)
264 {
265 if ((GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) && ptx_tbl && (rx_pkt_type != PKT_TYPE_BAR) &&
266 (prx_pd->priority < MAX_NUM_TID))
267 {
268 ptx_tbl->rx_seq[prx_pd->priority] = prx_pd->seq_num;
269 }
270 (void)__memcpy(pmadapter, ta, prx_pkt->eth803_hdr.src_addr, MLAN_MAC_ADDR_LENGTH);
271 }
272 else
273 {
274 if ((rx_pkt_type != PKT_TYPE_BAR) && (prx_pd->priority < MAX_NUM_TID))
275 {
276 priv->rx_seq[prx_pd->priority] = prx_pd->seq_num;
277 }
278 (void)__memcpy(pmadapter, ta, priv->curr_bss_params.bss_descriptor.mac_address, MLAN_MAC_ADDR_LENGTH);
279 }
280
281 /* Reorder and send to OS */
282 if ((ret = mlan_11n_rxreorder_pkt(priv, prx_pd->seq_num, prx_pd->priority, ta, (t_u8)prx_pd->rx_pkt_type,
283 (void *)pmbuf)) ||
284 (rx_pkt_type == PKT_TYPE_BAR))
285 {
286 wlan_free_mlan_buffer(pmadapter, pmbuf);
287 }
288
289 done:
290
291 LEAVE();
292 return (ret);
293 }
294