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