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