diff options
Diffstat (limited to 'sys/contrib/dev/iwlwifi/mld/tests/rx.c')
| -rw-r--r-- | sys/contrib/dev/iwlwifi/mld/tests/rx.c | 353 | 
1 files changed, 353 insertions, 0 deletions
| diff --git a/sys/contrib/dev/iwlwifi/mld/tests/rx.c b/sys/contrib/dev/iwlwifi/mld/tests/rx.c new file mode 100644 index 000000000000..20cb4e03ab41 --- /dev/null +++ b/sys/contrib/dev/iwlwifi/mld/tests/rx.c @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* + * KUnit tests for channel helper functions + * + * Copyright (C) 2024 Intel Corporation + */ +#include <kunit/test.h> +#include "utils.h" +#include "iwl-trans.h" +#include "mld.h" +#include "sta.h" + +static const struct is_dup_case { +	const char *desc; +	struct { +		/* ieee80211_hdr fields */ +		__le16 fc; +		__le16 seq; +		u8 tid; +		bool multicast; +		/* iwl_rx_mpdu_desc fields */ +		bool is_amsdu; +		u8 sub_frame_idx; +	} rx_pkt; +	struct { +		__le16 last_seq; +		u8 last_sub_frame_idx; +		u8 tid; +	} dup_data_state; +	struct { +		bool is_dup; +		u32 rx_status_flag; +	} result; +} is_dup_cases[] = { +	{ +		.desc = "Control frame", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_CTL), +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = 0, +		} +	}, +	{ +		.desc = "Null func frame", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_NULLFUNC), +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = 0, +		} +	}, +	{ +		.desc = "Multicast data", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA), +			.multicast = true, +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = 0, +		} +	}, +	{ +		.desc = "QoS null func frame", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_QOS_NULLFUNC), +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = 0, +		} +	}, +	{ +		.desc = "QoS data new sequence", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_QOS_DATA), +			.seq = __cpu_to_le16(0x101), +		}, +		.dup_data_state = { +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 0, +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = RX_FLAG_DUP_VALIDATED, +		}, +	}, +	{ +		.desc = "QoS data same sequence, no retry", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_QOS_DATA), +			.seq = __cpu_to_le16(0x100), +		}, +		.dup_data_state = { +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 0, +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = RX_FLAG_DUP_VALIDATED, +		}, +	}, +	{ +		.desc = "QoS data same sequence, has retry", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_QOS_DATA | +					    IEEE80211_FCTL_RETRY), +			.seq = __cpu_to_le16(0x100), +		}, +		.dup_data_state = { +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 0, +		}, +		.result = { +			.is_dup = true, +			.rx_status_flag = 0, +		}, +	}, +	{ +		.desc = "QoS data invalid tid", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_QOS_DATA), +			.seq = __cpu_to_le16(0x100), +			.tid = IWL_MAX_TID_COUNT + 1, +		}, +		.result = { +			.is_dup = true, +			.rx_status_flag = 0, +		}, +	}, +	{ +		.desc = "non-QoS data, same sequence, same tid, no retry", +		.rx_pkt = { +			/* Driver will use tid = IWL_MAX_TID_COUNT */ +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA), +			.seq = __cpu_to_le16(0x100), +		}, +		.dup_data_state = { +			.tid = IWL_MAX_TID_COUNT, +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 0, +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = RX_FLAG_DUP_VALIDATED, +		}, +	}, +	{ +		.desc = "non-QoS data, same sequence, same tid, has retry", +		.rx_pkt = { +			/* Driver will use tid = IWL_MAX_TID_COUNT */ +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_FCTL_RETRY), +			.seq = __cpu_to_le16(0x100), +		}, +		.dup_data_state = { +			.tid = IWL_MAX_TID_COUNT, +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 0, +		}, +		.result = { +			.is_dup = true, +			.rx_status_flag = 0, +		}, +	}, +	{ +		.desc = "non-QoS data, same sequence on different tid's", +		.rx_pkt = { +			/* Driver will use tid = IWL_MAX_TID_COUNT */ +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA), +			.seq = __cpu_to_le16(0x100), +		}, +		.dup_data_state = { +			.tid = 7, +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 0, +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = RX_FLAG_DUP_VALIDATED, +		}, +	}, +	{ +		.desc = "A-MSDU new subframe, allow same PN", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_QOS_DATA), +			.seq = __cpu_to_le16(0x100), +			.is_amsdu = true, +			.sub_frame_idx = 1, +		}, +		.dup_data_state = { +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 0, +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = RX_FLAG_ALLOW_SAME_PN | +					  RX_FLAG_DUP_VALIDATED, +		}, +	}, +	{ +		.desc = "A-MSDU subframe with smaller idx, disallow same PN", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_QOS_DATA), +			.seq = __cpu_to_le16(0x100), +			.is_amsdu = true, +			.sub_frame_idx = 1, +		}, +		.dup_data_state = { +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 2, +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = RX_FLAG_DUP_VALIDATED, +		}, +	}, +	{ +		.desc = "A-MSDU same subframe, no retry, disallow same PN", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_QOS_DATA), +			.seq = __cpu_to_le16(0x100), +			.is_amsdu = true, +			.sub_frame_idx = 0, +		}, +		.dup_data_state = { +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 0, +		}, +		.result = { +			.is_dup = false, +			.rx_status_flag = RX_FLAG_DUP_VALIDATED, +		}, +	}, +	{ +		.desc = "A-MSDU same subframe, has retry", +		.rx_pkt = { +			.fc = __cpu_to_le16(IEEE80211_FTYPE_DATA | +					    IEEE80211_STYPE_QOS_DATA | +					    IEEE80211_FCTL_RETRY), +			.seq = __cpu_to_le16(0x100), +			.is_amsdu = true, +			.sub_frame_idx = 0, +		}, +		.dup_data_state = { +			.last_seq = __cpu_to_le16(0x100), +			.last_sub_frame_idx = 0, +		}, +		.result = { +			.is_dup = true, +			.rx_status_flag = 0, +		}, +	}, +}; + +KUNIT_ARRAY_PARAM_DESC(test_is_dup, is_dup_cases, desc); + +static void +setup_dup_data_state(struct ieee80211_sta *sta) +{ +	struct kunit *test = kunit_get_current_test(); +	const struct is_dup_case *param = (const void *)(test->param_value); +	struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta); +	u8 tid = param->dup_data_state.tid; +	struct iwl_mld_rxq_dup_data *dup_data; + +	/* Allocate dup_data only for 1 queue */ +	KUNIT_ALLOC_AND_ASSERT(test, dup_data); + +	/* Initialize dup data, see iwl_mld_alloc_dup_data */ +	memset(dup_data->last_seq, 0xff, sizeof(dup_data->last_seq)); + +	dup_data->last_seq[tid] = param->dup_data_state.last_seq; +	dup_data->last_sub_frame_idx[tid] = +		param->dup_data_state.last_sub_frame_idx; + +	mld_sta->dup_data = dup_data; +} + +static void setup_rx_pkt(const struct is_dup_case *param, +			 struct ieee80211_hdr *hdr, +			 struct iwl_rx_mpdu_desc *mpdu_desc) +{ +	u8 tid = param->rx_pkt.tid; + +	/* Set "new rx packet" header */ +	hdr->frame_control = param->rx_pkt.fc; +	hdr->seq_ctrl = param->rx_pkt.seq; + +	if (ieee80211_is_data_qos(hdr->frame_control)) { +		u8 *qc = ieee80211_get_qos_ctl(hdr); + +		qc[0] = tid & IEEE80211_QOS_CTL_TID_MASK; +	} + +	if (param->rx_pkt.multicast) +		hdr->addr1[0] = 0x1; + +	/* Set mpdu_desc */ +	mpdu_desc->amsdu_info = param->rx_pkt.sub_frame_idx & +				IWL_RX_MPDU_AMSDU_SUBFRAME_IDX_MASK; +	if (param->rx_pkt.is_amsdu) +		mpdu_desc->mac_flags2 |= IWL_RX_MPDU_MFLG2_AMSDU; +} + +static void test_is_dup(struct kunit *test) +{ +	const struct is_dup_case *param = (const void *)(test->param_value); +	struct iwl_mld *mld = test->priv; +	struct iwl_rx_mpdu_desc mpdu_desc = { }; +	struct ieee80211_rx_status rx_status = { }; +	struct ieee80211_vif *vif; +	struct ieee80211_sta *sta; +	struct ieee80211_hdr hdr; + +	vif = iwlmld_kunit_add_vif(false, NL80211_IFTYPE_STATION); +	sta = iwlmld_kunit_setup_sta(vif, IEEE80211_STA_AUTHORIZED, -1); + +	/* Prepare test case state */ +	setup_dup_data_state(sta); +	setup_rx_pkt(param, &hdr, &mpdu_desc); + +	KUNIT_EXPECT_EQ(test, +			iwl_mld_is_dup(mld, sta, &hdr, &mpdu_desc, &rx_status, +				       0), /* assuming only 1 queue */ +			param->result.is_dup); +	KUNIT_EXPECT_EQ(test, rx_status.flag, param->result.rx_status_flag); +} + +static struct kunit_case is_dup_test_cases[] = { +	KUNIT_CASE_PARAM(test_is_dup, test_is_dup_gen_params), +	{}, +}; + +static struct kunit_suite is_dup = { +	.name = "iwlmld-rx-is-dup", +	.test_cases = is_dup_test_cases, +	.init = iwlmld_kunit_test_init, +}; + +kunit_test_suite(is_dup); | 
