1 /** @file mlan_11n_aggr.c
2  *
3  *  @brief  This file provides contains functions for 11n Aggregation
4  *
5  *  Copyright 2008-2024 NXP
6  *
7  *  SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 
11 /********************************************************
12 Change log:
13     11/10/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 /********************************************************
28     Global Variables
29 ********************************************************/
30 
31 /********************************************************
32     Local Functions
33 ********************************************************/
34 
35 void wrapper_deliver_amsdu_subframe(pmlan_buffer amsdu_pmbuf, t_u8 *data, t_u16 pkt_len);
36 
37 /**
38  *  @brief Get number of aggregated packets
39  *
40  *  @param data			A pointer to packet data
41  *  @param total_pkt_len	Total packet length
42  *
43  *  @return			Number of packets
44  */
wlan_11n_get_num_aggrpkts(t_u8 * data,t_s32 total_pkt_len)45 static int wlan_11n_get_num_aggrpkts(t_u8 *data, t_s32 total_pkt_len)
46 {
47     int pkt_count = 0;
48     t_u32 pkt_len, pad;
49 
50     ENTER();
51     while (total_pkt_len > 0)
52     {
53         /* Length will be in network format, change it to host */
54         pkt_len = mlan_ntohs((*(t_u16 *)(void *)(data + (2 * MLAN_MAC_ADDR_LENGTH))));
55         pad     = (((pkt_len + sizeof(Eth803Hdr_t)) & 3U)) ? (4U - ((pkt_len + sizeof(Eth803Hdr_t)) & 3U)) : 0U;
56         data += pkt_len + pad + sizeof(Eth803Hdr_t);
57         total_pkt_len -= (t_s32)pkt_len + (t_s32)pad + (t_s32)sizeof(Eth803Hdr_t);
58         ++pkt_count;
59     }
60     LEAVE();
61     return pkt_count;
62 }
63 
64 /********************************************************
65     Global Functions
66 ********************************************************/
67 
68 /**
69  *  @brief Deaggregate the received AMSDU packet
70  *
71  *  @param priv		A pointer to mlan_private structure
72  *  @param pmbuf	A pointer to aggregated data packet
73  *
74  *  @return		MLAN_STATUS_SUCCESS --success, otherwise fail
75  */
wlan_11n_deaggregate_pkt(mlan_private * priv,pmlan_buffer pmbuf)76 mlan_status wlan_11n_deaggregate_pkt(mlan_private *priv, pmlan_buffer pmbuf)
77 {
78     t_u16 pkt_len;
79     t_s32 total_pkt_len;
80     t_u8 *data;
81     int pad;
82     mlan_status ret = MLAN_STATUS_FAILURE;
83     RxPacketHdr_t *prx_pkt;
84     /* mlan_adapter *pmadapter = priv->adapter; */
85     t_u8 rfc1042_eth_hdr[MLAN_MAC_ADDR_LENGTH] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
86 
87     ENTER();
88 
89     data          = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
90     total_pkt_len = (t_s32)pmbuf->data_len;
91 
92     /* Sanity test */
93     if (total_pkt_len > MLAN_RX_DATA_BUF_SIZE)
94     {
95         PRINTM(MERROR,
96                "Total packet length greater than tx buffer"
97                " size %d\n",
98                total_pkt_len);
99         goto done;
100     }
101 
102     pmbuf->use_count = wlan_11n_get_num_aggrpkts(data, total_pkt_len);
103 
104     while (total_pkt_len > 0)
105     {
106         prx_pkt = (RxPacketHdr_t *)(void *)data;
107         /* Length will be in network format, change it to host */
108         pkt_len = mlan_ntohs((*(t_u16 *)(void *)(data + (2 * MLAN_MAC_ADDR_LENGTH))));
109         if ((t_s32)pkt_len > total_pkt_len)
110         {
111             PRINTM(MERROR, "Error in packet length: total_pkt_len = %d, pkt_len = %d\n", total_pkt_len, pkt_len);
112             break;
113         }
114 
115         pad = (((pkt_len + sizeof(Eth803Hdr_t)) & 3)) ? (4 - ((pkt_len + sizeof(Eth803Hdr_t)) & 3)) : 0;
116 
117         total_pkt_len -= (t_s32)pkt_len + pad + (t_s32)sizeof(Eth803Hdr_t);
118 
119         if (__memcmp(pmadapter, &prx_pkt->rfc1042_hdr, rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0)
120         {
121             (void)__memmove(pmadapter, data + LLC_SNAP_LEN, data, (2 * MLAN_MAC_ADDR_LENGTH));
122             data += LLC_SNAP_LEN;
123             pkt_len += sizeof(Eth803Hdr_t) - LLC_SNAP_LEN;
124         }
125         else
126         {
127             *(t_u16 *)(void *)(data + (2 * MLAN_MAC_ADDR_LENGTH)) = (t_u16)0;
128             pkt_len += sizeof(Eth803Hdr_t);
129         }
130 
131         /* This part is customized for WMSDK. We do not need and will not
132            allocate the mlan buffer. */
133         wrapper_deliver_amsdu_subframe(pmbuf, data, pkt_len);
134         ret = MLAN_STATUS_SUCCESS;
135 
136         switch (ret)
137         {
138             case MLAN_STATUS_SUCCESS:
139                 break;
140             default:
141                 PRINTM(MINFO, "Unexpected MLAN STATUS deaggregate pkt\n");
142                 break;
143         }
144 
145         data += pkt_len + pad;
146     }
147 
148 done:
149     LEAVE();
150     return ret;
151 }
152 
153 #if CONFIG_AMSDU_IN_AMPDU
wlan_11n_form_amsdu_pkt(t_u8 * amsdu_buf,t_u8 * data,int pkt_len,int * pad)154 int wlan_11n_form_amsdu_pkt(t_u8 *amsdu_buf, t_u8 *data, int pkt_len, int *pad)
155 {
156     int dt_offset, amsdu_buf_offset;
157     Rfc1042Hdr_t snap = {
158         0xaa,               /* LLC DSAP */
159         0xaa,               /* LLC SSAP */
160         0x03,               /* LLC CTRL */
161         {0x00, 0x00, 0x00}, /* SNAP OUI */
162         0x0000              /* SNAP type */
163         /*
164          * This field will be overwritten
165          * later with ethertype
166          */
167     };
168 
169     ENTER();
170 
171     memcpy(amsdu_buf, data, (MLAN_MAC_ADDR_LENGTH)*2);
172     dt_offset = amsdu_buf_offset = (MLAN_MAC_ADDR_LENGTH)*2;
173 
174     snap.snap_type = *(t_u16 *)(data + dt_offset);
175     dt_offset += sizeof(t_u16);
176     *(t_u16 *)(amsdu_buf + amsdu_buf_offset) =
177         mlan_htons(pkt_len + LLC_SNAP_LEN - ((2 * MLAN_MAC_ADDR_LENGTH) + sizeof(t_u16)));
178     amsdu_buf_offset += sizeof(t_u16);
179     memcpy(amsdu_buf + amsdu_buf_offset, &snap, LLC_SNAP_LEN);
180     amsdu_buf_offset += LLC_SNAP_LEN;
181 #if CONFIG_IMU_GDMA
182     HAL_ImuGdmaCopyData(amsdu_buf + amsdu_buf_offset, data + dt_offset, pkt_len - dt_offset);
183 #else
184     memcpy(amsdu_buf + amsdu_buf_offset, data + dt_offset, pkt_len - dt_offset);
185 #endif
186     *pad = (((pkt_len + LLC_SNAP_LEN) & 3)) ? (4 - (((pkt_len + LLC_SNAP_LEN)) & 3)) : 0;
187     if (*pad)
188         memset(amsdu_buf + pkt_len + LLC_SNAP_LEN, 0, *pad);
189 
190     LEAVE();
191     return pkt_len + LLC_SNAP_LEN + *pad;
192 }
193 #endif
194