File Index
Files and directories
Sign in
FILE

rx.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/intel/iwlwifi/mld/tests/rx.c C
  1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2/*
  3 * KUnit tests for channel helper functions
  4 *
  5 * Copyright (C) 2024 Intel Corporation
  6 */
  7#include <kunit/test.h>
  8#include "utils.h"
  9#include "iwl-trans.h"
 10#include "mld.h"
 11#include "sta.h"
 12
 13static const struct is_dup_case {
 14	const char *desc;
 15	struct {
 16		/* ieee80211_hdr fields */
 17		__le16 fc;
 18		__le16 seq;
 19		u8 tid;
 20		bool multicast;
 21		/* iwl_rx_mpdu_desc fields */
 22		bool is_amsdu;
 23		u8 sub_frame_idx;
 24	} rx_pkt;
 25	struct {
 26		__le16 last_seq;
 27		u8 last_sub_frame_idx;
 28		u8 tid;
 29	} dup_data_state;
 30	struct {
 31		bool is_dup;
 32		u32 rx_status_flag;
 33	} result;
 34} is_dup_cases[] = {
 35	{
 36		.desc = "Control frame",
 37		.rx_pkt = {
 38			.fc = __cpu_to_le16(IEEE80211_FTYPE_CTL),
 39		},
 40		.result = {
 41			.is_dup = false,
 42			.rx_status_flag = 0,
 43		}
 44	},
 45	{
 46		.desc = "Null func frame",
 47		.rx_pkt = {
 48			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
 49					    IEEE80211_STYPE_NULLFUNC),
 50		},
 51		.result = {
 52			.is_dup = false,
 53			.rx_status_flag = 0,
 54		}
 55	},
 56	{
 57		.desc = "Multicast data",
 58		.rx_pkt = {
 59			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA),
 60			.multicast = true,
 61		},
 62		.result = {
 63			.is_dup = false,
 64			.rx_status_flag = 0,
 65		}
 66	},
 67	{
 68		.desc = "QoS null func frame",
 69		.rx_pkt = {
 70			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
 71					    IEEE80211_STYPE_QOS_NULLFUNC),
 72		},
 73		.result = {
 74			.is_dup = false,
 75			.rx_status_flag = 0,
 76		}
 77	},
 78	{
 79		.desc = "QoS data new sequence",
 80		.rx_pkt = {
 81			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
 82					    IEEE80211_STYPE_QOS_DATA),
 83			.seq = __cpu_to_le16(0x101),
 84		},
 85		.dup_data_state = {
 86			.last_seq = __cpu_to_le16(0x100),
 87			.last_sub_frame_idx = 0,
 88		},
 89		.result = {
 90			.is_dup = false,
 91			.rx_status_flag = RX_FLAG_DUP_VALIDATED,
 92		},
 93	},
 94	{
 95		.desc = "QoS data same sequence, no retry",
 96		.rx_pkt = {
 97			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
 98					    IEEE80211_STYPE_QOS_DATA),
 99			.seq = __cpu_to_le16(0x100),
100		},
101		.dup_data_state = {
102			.last_seq = __cpu_to_le16(0x100),
103			.last_sub_frame_idx = 0,
104		},
105		.result = {
106			.is_dup = false,
107			.rx_status_flag = RX_FLAG_DUP_VALIDATED,
108		},
109	},
110	{
111		.desc = "QoS data same sequence, has retry",
112		.rx_pkt = {
113			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
114					    IEEE80211_STYPE_QOS_DATA |
115					    IEEE80211_FCTL_RETRY),
116			.seq = __cpu_to_le16(0x100),
117		},
118		.dup_data_state = {
119			.last_seq = __cpu_to_le16(0x100),
120			.last_sub_frame_idx = 0,
121		},
122		.result = {
123			.is_dup = true,
124			.rx_status_flag = 0,
125		},
126	},
127	{
128		.desc = "QoS data invalid tid",
129		.rx_pkt = {
130			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
131					    IEEE80211_STYPE_QOS_DATA),
132			.seq = __cpu_to_le16(0x100),
133			.tid = IWL_MAX_TID_COUNT + 1,
134		},
135		.result = {
136			.is_dup = true,
137			.rx_status_flag = 0,
138		},
139	},
140	{
141		.desc = "non-QoS data, same sequence, same tid, no retry",
142		.rx_pkt = {
143			/* Driver will use tid = IWL_MAX_TID_COUNT */
144			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA),
145			.seq = __cpu_to_le16(0x100),
146		},
147		.dup_data_state = {
148			.tid = IWL_MAX_TID_COUNT,
149			.last_seq = __cpu_to_le16(0x100),
150			.last_sub_frame_idx = 0,
151		},
152		.result = {
153			.is_dup = false,
154			.rx_status_flag = RX_FLAG_DUP_VALIDATED,
155		},
156	},
157	{
158		.desc = "non-QoS data, same sequence, same tid, has retry",
159		.rx_pkt = {
160			/* Driver will use tid = IWL_MAX_TID_COUNT */
161			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
162					    IEEE80211_FCTL_RETRY),
163			.seq = __cpu_to_le16(0x100),
164		},
165		.dup_data_state = {
166			.tid = IWL_MAX_TID_COUNT,
167			.last_seq = __cpu_to_le16(0x100),
168			.last_sub_frame_idx = 0,
169		},
170		.result = {
171			.is_dup = true,
172			.rx_status_flag = 0,
173		},
174	},
175	{
176		.desc = "non-QoS data, same sequence on different tid's",
177		.rx_pkt = {
178			/* Driver will use tid = IWL_MAX_TID_COUNT */
179			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA),
180			.seq = __cpu_to_le16(0x100),
181		},
182		.dup_data_state = {
183			.tid = 7,
184			.last_seq = __cpu_to_le16(0x100),
185			.last_sub_frame_idx = 0,
186		},
187		.result = {
188			.is_dup = false,
189			.rx_status_flag = RX_FLAG_DUP_VALIDATED,
190		},
191	},
192	{
193		.desc = "A-MSDU new subframe, allow same PN",
194		.rx_pkt = {
195			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
196					    IEEE80211_STYPE_QOS_DATA),
197			.seq = __cpu_to_le16(0x100),
198			.is_amsdu = true,
199			.sub_frame_idx = 1,
200		},
201		.dup_data_state = {
202			.last_seq = __cpu_to_le16(0x100),
203			.last_sub_frame_idx = 0,
204		},
205		.result = {
206			.is_dup = false,
207			.rx_status_flag = RX_FLAG_ALLOW_SAME_PN |
208					  RX_FLAG_DUP_VALIDATED,
209		},
210	},
211	{
212		.desc = "A-MSDU subframe with smaller idx, disallow same PN",
213		.rx_pkt = {
214			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
215					    IEEE80211_STYPE_QOS_DATA),
216			.seq = __cpu_to_le16(0x100),
217			.is_amsdu = true,
218			.sub_frame_idx = 1,
219		},
220		.dup_data_state = {
221			.last_seq = __cpu_to_le16(0x100),
222			.last_sub_frame_idx = 2,
223		},
224		.result = {
225			.is_dup = false,
226			.rx_status_flag = RX_FLAG_DUP_VALIDATED,
227		},
228	},
229	{
230		.desc = "A-MSDU same subframe, no retry, disallow same PN",
231		.rx_pkt = {
232			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
233					    IEEE80211_STYPE_QOS_DATA),
234			.seq = __cpu_to_le16(0x100),
235			.is_amsdu = true,
236			.sub_frame_idx = 0,
237		},
238		.dup_data_state = {
239			.last_seq = __cpu_to_le16(0x100),
240			.last_sub_frame_idx = 0,
241		},
242		.result = {
243			.is_dup = false,
244			.rx_status_flag = RX_FLAG_DUP_VALIDATED,
245		},
246	},
247	{
248		.desc = "A-MSDU same subframe, has retry",
249		.rx_pkt = {
250			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA |
251					    IEEE80211_STYPE_QOS_DATA |
252					    IEEE80211_FCTL_RETRY),
253			.seq = __cpu_to_le16(0x100),
254			.is_amsdu = true,
255			.sub_frame_idx = 0,
256		},
257		.dup_data_state = {
258			.last_seq = __cpu_to_le16(0x100),
259			.last_sub_frame_idx = 0,
260		},
261		.result = {
262			.is_dup = true,
263			.rx_status_flag = 0,
264		},
265	},
266};
267
268KUNIT_ARRAY_PARAM_DESC(test_is_dup, is_dup_cases, desc);
269
270static void
271setup_dup_data_state(struct ieee80211_sta *sta)
272{
273	struct kunit *test = kunit_get_current_test();
274	const struct is_dup_case *param = (const void *)(test->param_value);
275	struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta);
276	u8 tid = param->dup_data_state.tid;
277	struct iwl_mld_rxq_dup_data *dup_data;
278
279	/* Allocate dup_data only for 1 queue */
280	KUNIT_ALLOC_AND_ASSERT(test, dup_data);
281
282	/* Initialize dup data, see iwl_mld_alloc_dup_data */
283	memset(dup_data->last_seq, 0xff, sizeof(dup_data->last_seq));
284
285	dup_data->last_seq[tid] = param->dup_data_state.last_seq;
286	dup_data->last_sub_frame_idx[tid] =
287		param->dup_data_state.last_sub_frame_idx;
288
289	mld_sta->dup_data = dup_data;
290}
291
292static void setup_rx_pkt(const struct is_dup_case *param,
293			 struct ieee80211_hdr *hdr,
294			 struct iwl_rx_mpdu_desc *mpdu_desc)
295{
296	u8 tid = param->rx_pkt.tid;
297
298	/* Set "new rx packet" header */
299	hdr->frame_control = param->rx_pkt.fc;
300	hdr->seq_ctrl = param->rx_pkt.seq;
301
302	if (ieee80211_is_data_qos(hdr->frame_control)) {
303		u8 *qc = ieee80211_get_qos_ctl(hdr);
304
305		qc[0] = tid & IEEE80211_QOS_CTL_TID_MASK;
306	}
307
308	if (param->rx_pkt.multicast)
309		hdr->addr1[0] = 0x1;
310
311	/* Set mpdu_desc */
312	mpdu_desc->amsdu_info = param->rx_pkt.sub_frame_idx &
313				IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK;
314	if (param->rx_pkt.is_amsdu)
315		mpdu_desc->mac_flags2 |= IWL_RX_MPDU_MFLG2_AMSDU;
316}
317
318static void test_is_dup(struct kunit *test)
319{
320	const struct is_dup_case *param = (const void *)(test->param_value);
321	struct iwl_mld *mld = test->priv;
322	struct iwl_rx_mpdu_desc mpdu_desc = { };
323	struct ieee80211_rx_status rx_status = { };
324	struct ieee80211_vif *vif;
325	struct ieee80211_sta *sta;
326	struct ieee80211_hdr hdr;
327
328	vif = iwlmld_kunit_add_vif(false, NL80211_IFTYPE_STATION);
329	sta = iwlmld_kunit_setup_sta(vif, IEEE80211_STA_AUTHORIZED, -1);
330
331	/* Prepare test case state */
332	setup_dup_data_state(sta);
333	setup_rx_pkt(param, &hdr, &mpdu_desc);
334
335	KUNIT_EXPECT_EQ(test,
336			iwl_mld_is_dup(mld, sta, &hdr, &mpdu_desc, &rx_status,
337				       0), /* assuming only 1 queue */
338			param->result.is_dup);
339	KUNIT_EXPECT_EQ(test, rx_status.flag, param->result.rx_status_flag);
340}
341
342static struct kunit_case is_dup_test_cases[] = {
343	KUNIT_CASE_PARAM(test_is_dup, test_is_dup_gen_params),
344	{},
345};
346
347static struct kunit_suite is_dup = {
348	.name = "iwlmld-rx-is-dup",
349	.test_cases = is_dup_test_cases,
350	.init = iwlmld_kunit_test_init,
351};
352
353kunit_test_suite(is_dup);
~/ Read-only file preview.