2023-12-20 15:24:30

by Benjamin Berg

[permalink] [raw]
Subject: [PATCH 0/6] Add some more cfg80211 and mac80211 kunit tests

From: Benjamin Berg <[email protected]>

This patchset adds a couple of helpers for kunit as well as tests for
cfg80211 and mac80211 that use them.

Benjamin Berg (3):
kunit: add parameter generation macro using description from array
kunit: add a convenience allocation wrapper for SKBs
wifi: cfg80211: tests: add some scanning related tests

Johannes Berg (3):
wifi: mac80211: add kunit tests for public action handling
wifi: mac80211: kunit: generalize public action test
wifi: mac80211: kunit: extend MFP tests

Documentation/dev-tools/kunit/usage.rst | 12 +-
include/kunit/skbuff.h | 56 +++
include/kunit/test.h | 19 +
net/mac80211/ieee80211_i.h | 10 +
net/mac80211/rx.c | 4 +-
net/mac80211/tests/Makefile | 2 +-
net/mac80211/tests/mfp.c | 286 +++++++++++
net/wireless/core.h | 13 +-
net/wireless/scan.c | 9 +-
net/wireless/tests/Makefile | 2 +-
net/wireless/tests/scan.c | 625 ++++++++++++++++++++++++
net/wireless/tests/util.c | 56 +++
net/wireless/tests/util.h | 66 +++
13 files changed, 1145 insertions(+), 15 deletions(-)
create mode 100644 include/kunit/skbuff.h
create mode 100644 net/mac80211/tests/mfp.c
create mode 100644 net/wireless/tests/scan.c
create mode 100644 net/wireless/tests/util.c
create mode 100644 net/wireless/tests/util.h

--
2.43.0



2023-12-20 15:24:32

by Benjamin Berg

[permalink] [raw]
Subject: [PATCH 2/6] kunit: add a convenience allocation wrapper for SKBs

From: Benjamin Berg <[email protected]>

Add a simple convenience helper to allocate and zero fill an SKB for the
use by a kunit test. Also provide a way to free it again in case that
may be desirable.

This simply mirrors the kunit_kmalloc API.

Signed-off-by: Benjamin Berg <[email protected]>
---
include/kunit/skbuff.h | 56 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
create mode 100644 include/kunit/skbuff.h

diff --git a/include/kunit/skbuff.h b/include/kunit/skbuff.h
new file mode 100644
index 000000000000..2144d01e556f
--- /dev/null
+++ b/include/kunit/skbuff.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Base unit test (KUnit) API.
+ *
+ * Copyright (C) 2023 Intel Corporation
+ */
+
+#ifndef _KUNIT_SKBUFF_H
+#define _KUNIT_SKBUFF_H
+
+#include <kunit/resource.h>
+#include <linux/skbuff.h>
+
+static void kunit_action_kfree_skb(void *p)
+{
+ kfree_skb((struct sk_buff *)p);
+}
+
+/**
+ * kunit_zalloc_skb() - Allocate and initialize a resource managed skb.
+ * @test: The test case to which the skb belongs
+ * @len: size to allocate
+ *
+ * Allocate a new struct sk_buff with GFP_KERNEL, zero fill the give length
+ * and add it as a resource to the kunit test for automatic cleanup.
+ *
+ * Returns: newly allocated SKB, or %NULL on error
+ */
+static inline struct sk_buff *kunit_zalloc_skb(struct kunit *test, int len,
+ gfp_t gfp)
+{
+ struct sk_buff *res = alloc_skb(len, GFP_KERNEL);
+
+ if (!res || skb_pad(res, len))
+ return NULL;
+
+ if (kunit_add_action_or_reset(test, kunit_action_kfree_skb, res))
+ return NULL;
+
+ return res;
+}
+
+/**
+ * kunit_kfree_skb() - Like kfree_skb except for allocations managed by KUnit.
+ * @test: The test case to which the resource belongs.
+ * @skb: The SKB to free.
+ */
+static inline void kunit_kfree_skb(struct kunit *test, struct sk_buff *skb)
+{
+ if (!skb)
+ return;
+
+ kunit_release_action(test, kunit_action_kfree_skb, (void *)skb);
+}
+
+#endif /* _KUNIT_SKBUFF_H */
--
2.43.0


2023-12-20 15:24:39

by Benjamin Berg

[permalink] [raw]
Subject: [PATCH 1/6] kunit: add parameter generation macro using description from array

From: Benjamin Berg <[email protected]>

The existing KUNIT_ARRAY_PARAM macro requires a separate function to
get the description. However, in a lot of cases the description can
just be copied directly from the array. Add a second macro that
avoids having to write a static function just for a single strscpy.

Signed-off-by: Benjamin Berg <[email protected]>
---
Documentation/dev-tools/kunit/usage.rst | 12 ++++--------
include/kunit/test.h | 19 +++++++++++++++++++
2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst
index c27e1646ecd9..b959e5befcbe 100644
--- a/Documentation/dev-tools/kunit/usage.rst
+++ b/Documentation/dev-tools/kunit/usage.rst
@@ -566,13 +566,9 @@ By reusing the same ``cases`` array from above, we can write the test as a
},
};

- // Need a helper function to generate a name for each test case.
- static void case_to_desc(const struct sha1_test_case *t, char *desc)
- {
- strcpy(desc, t->str);
- }
- // Creates `sha1_gen_params()` to iterate over `cases`.
- KUNIT_ARRAY_PARAM(sha1, cases, case_to_desc);
+ // Creates `sha1_gen_params()` to iterate over `cases` while using
+ // the struct member `str` for the case description.
+ KUNIT_ARRAY_PARAM_DESC(sha1, cases, str);

// Looks no different from a normal test.
static void sha1_test(struct kunit *test)
@@ -588,7 +584,7 @@ By reusing the same ``cases`` array from above, we can write the test as a
}

// Instead of KUNIT_CASE, we use KUNIT_CASE_PARAM and pass in the
- // function declared by KUNIT_ARRAY_PARAM.
+ // function declared by KUNIT_ARRAY_PARAM or KUNIT_ARRAY_PARAM_DESC.
static struct kunit_case sha1_test_cases[] = {
KUNIT_CASE_PARAM(sha1_test, sha1_gen_params),
{}
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 20ed9f9275c9..2dfa851e1f88 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -1514,6 +1514,25 @@ do { \
return NULL; \
}

+/**
+ * KUNIT_ARRAY_PARAM_DESC() - Define test parameter generator from an array.
+ * @name: prefix for the test parameter generator function.
+ * @array: array of test parameters.
+ * @desc_member: structure member from array element to use as description
+ *
+ * Define function @name_gen_params which uses @array to generate parameters.
+ */
+#define KUNIT_ARRAY_PARAM_DESC(name, array, desc_member) \
+ static const void *name##_gen_params(const void *prev, char *desc) \
+ { \
+ typeof((array)[0]) *__next = prev ? ((typeof(__next)) prev) + 1 : (array); \
+ if (__next - (array) < ARRAY_SIZE((array))) { \
+ strscpy(desc, __next->desc_member, KUNIT_PARAM_DESC_SIZE); \
+ return __next; \
+ } \
+ return NULL; \
+ }
+
// TODO([email protected]): consider eventually migrating users to explicitly
// include resource.h themselves if they need it.
#include <kunit/resource.h>
--
2.43.0


2023-12-20 15:24:40

by Benjamin Berg

[permalink] [raw]
Subject: [PATCH 3/6] wifi: mac80211: add kunit tests for public action handling

From: Johannes Berg <[email protected]>

Check the logic in ieee80211_drop_unencrypted_mgmt()
according to a list of test cases derived from the
spec.

Signed-off-by: Johannes Berg <[email protected]>
Reviewed-by: Benjamin Berg <[email protected]>
---
net/mac80211/ieee80211_i.h | 10 ++
net/mac80211/rx.c | 4 +-
net/mac80211/tests/Makefile | 2 +-
net/mac80211/tests/mfp.c | 184 ++++++++++++++++++++++++++++++++++++
4 files changed, 198 insertions(+), 2 deletions(-)
create mode 100644 net/mac80211/tests/mfp.c

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 29312f6638a1..71fafcd6a36e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -2610,4 +2610,14 @@ void ieee80211_check_wbrf_support(struct ieee80211_local *local);
void ieee80211_add_wbrf(struct ieee80211_local *local, struct cfg80211_chan_def *chandef);
void ieee80211_remove_wbrf(struct ieee80211_local *local, struct cfg80211_chan_def *chandef);

+#if IS_ENABLED(CONFIG_MAC80211_KUNIT_TEST)
+#define EXPORT_SYMBOL_IF_MAC80211_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym)
+#define VISIBLE_IF_MAC80211_KUNIT
+ieee80211_rx_result
+ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx);
+#else
+#define EXPORT_SYMBOL_IF_MAC80211_KUNIT(sym)
+#define VISIBLE_IF_MAC80211_KUNIT static
+#endif
+
#endif /* IEEE80211_I_H */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index bbfdcb0ade72..d294787feed0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -19,6 +19,7 @@
#include <linux/export.h>
#include <linux/kcov.h>
#include <linux/bitops.h>
+#include <kunit/visibility.h>
#include <net/mac80211.h>
#include <net/ieee80211_radiotap.h>
#include <asm/unaligned.h>
@@ -2405,7 +2406,7 @@ static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
return 0;
}

-static ieee80211_rx_result
+VISIBLE_IF_MAC80211_KUNIT ieee80211_rx_result
ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
@@ -2484,6 +2485,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)

return RX_CONTINUE;
}
+EXPORT_SYMBOL_IF_MAC80211_KUNIT(ieee80211_drop_unencrypted_mgmt);

static ieee80211_rx_result
__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
diff --git a/net/mac80211/tests/Makefile b/net/mac80211/tests/Makefile
index 4814584f8a14..4fdaf3feaca3 100644
--- a/net/mac80211/tests/Makefile
+++ b/net/mac80211/tests/Makefile
@@ -1,3 +1,3 @@
-mac80211-tests-y += module.o elems.o
+mac80211-tests-y += module.o elems.o mfp.o

obj-$(CONFIG_MAC80211_KUNIT_TEST) += mac80211-tests.o
diff --git a/net/mac80211/tests/mfp.c b/net/mac80211/tests/mfp.c
new file mode 100644
index 000000000000..629a5801c08f
--- /dev/null
+++ b/net/mac80211/tests/mfp.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KUnit tests for management frame acceptance
+ *
+ * Copyright (C) 2023 Intel Corporation
+ */
+#include <kunit/test.h>
+#include <kunit/skbuff.h>
+#include "../ieee80211_i.h"
+#include "../sta_info.h"
+
+MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+
+static const struct mfp_test_case {
+ const char *desc;
+ bool sta, mfp, decrypted, unicast, protected_dual;
+ ieee80211_rx_result result;
+} accept_public_action_cases[] = {
+ /* regular public action */
+ {
+ .desc = "public action: accept unicast from unknown peer",
+ .unicast = true,
+ .result = RX_CONTINUE,
+ },
+ {
+ .desc = "public action: accept multicast from unknown peer",
+ .unicast = false,
+ .result = RX_CONTINUE,
+ },
+ {
+ .desc = "public action: accept unicast without MFP",
+ .unicast = true,
+ .sta = true,
+ .result = RX_CONTINUE,
+ },
+ {
+ .desc = "public action: accept multicast without MFP",
+ .unicast = false,
+ .sta = true,
+ .result = RX_CONTINUE,
+ },
+ {
+ .desc = "public action: drop unicast with MFP",
+ .unicast = true,
+ .sta = true,
+ .mfp = true,
+ .result = RX_DROP_U_UNPROT_UNICAST_PUB_ACTION,
+ },
+ {
+ .desc = "public action: accept multicast with MFP",
+ .unicast = false,
+ .sta = true,
+ .mfp = true,
+ .result = RX_CONTINUE,
+ },
+ /* protected dual of public action */
+ {
+ .desc = "protected dual: drop unicast from unknown peer",
+ .protected_dual = true,
+ .unicast = true,
+ .result = RX_DROP_U_UNPROT_DUAL,
+ },
+ {
+ .desc = "protected dual: drop multicast from unknown peer",
+ .protected_dual = true,
+ .unicast = false,
+ .result = RX_DROP_U_UNPROT_DUAL,
+ },
+ {
+ .desc = "protected dual: drop unicast without MFP",
+ .protected_dual = true,
+ .unicast = true,
+ .sta = true,
+ .result = RX_DROP_U_UNPROT_DUAL,
+ },
+ {
+ .desc = "protected dual: drop multicast without MFP",
+ .protected_dual = true,
+ .unicast = false,
+ .sta = true,
+ .result = RX_DROP_U_UNPROT_DUAL,
+ },
+ {
+ .desc = "protected dual: drop undecrypted unicast with MFP",
+ .protected_dual = true,
+ .unicast = true,
+ .sta = true,
+ .mfp = true,
+ .result = RX_DROP_U_UNPROT_DUAL,
+ },
+ {
+ .desc = "protected dual: drop undecrypted multicast with MFP",
+ .protected_dual = true,
+ .unicast = false,
+ .sta = true,
+ .mfp = true,
+ .result = RX_DROP_U_UNPROT_DUAL,
+ },
+ {
+ .desc = "protected dual: accept unicast with MFP",
+ .protected_dual = true,
+ .decrypted = true,
+ .unicast = true,
+ .sta = true,
+ .mfp = true,
+ .result = RX_CONTINUE,
+ },
+ {
+ .desc = "protected dual: accept multicast with MFP",
+ .protected_dual = true,
+ .decrypted = true,
+ .unicast = false,
+ .sta = true,
+ .mfp = true,
+ .result = RX_CONTINUE,
+ },
+};
+
+KUNIT_ARRAY_PARAM_DESC(accept_public_action,
+ accept_public_action_cases,
+ desc);
+
+static void accept_public_action(struct kunit *test)
+{
+ static struct sta_info sta = {};
+ const struct mfp_test_case *params = test->param_value;
+ struct ieee80211_rx_data rx = {
+ .sta = params->sta ? &sta : NULL,
+ };
+ struct ieee80211_rx_status *status;
+ struct ieee80211_hdr_3addr hdr = {
+ .frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION),
+ .addr1 = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+ .addr2 = { 0x12, 0x22, 0x33, 0x44, 0x55, 0x66 },
+ /* A3/BSSID doesn't matter here */
+ };
+
+ if (!params->sta) {
+ KUNIT_ASSERT_FALSE(test, params->mfp);
+ KUNIT_ASSERT_FALSE(test, params->decrypted);
+ }
+
+ if (params->mfp)
+ set_sta_flag(&sta, WLAN_STA_MFP);
+
+ rx.skb = kunit_zalloc_skb(test, 128, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, rx.skb);
+ status = IEEE80211_SKB_RXCB(rx.skb);
+
+ if (params->decrypted) {
+ status->flag |= RX_FLAG_DECRYPTED;
+ if (params->unicast)
+ hdr.frame_control |=
+ cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ }
+
+ if (params->unicast)
+ hdr.addr1[0] = 0x02;
+
+ skb_put_data(rx.skb, &hdr, sizeof(hdr));
+
+ if (params->protected_dual)
+ skb_put_u8(rx.skb, WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION);
+ else
+ skb_put_u8(rx.skb, WLAN_CATEGORY_PUBLIC);
+ skb_put_u8(rx.skb, WLAN_PUB_ACTION_DSE_ENABLEMENT);
+
+ KUNIT_EXPECT_EQ(test,
+ ieee80211_drop_unencrypted_mgmt(&rx),
+ params->result);
+}
+
+static struct kunit_case mfp_test_cases[] = {
+ KUNIT_CASE_PARAM(accept_public_action, accept_public_action_gen_params),
+ {}
+};
+
+static struct kunit_suite mfp = {
+ .name = "mac80211-mfp",
+ .test_cases = mfp_test_cases,
+};
+
+kunit_test_suite(mfp);
--
2.43.0


2023-12-20 15:24:52

by Benjamin Berg

[permalink] [raw]
Subject: [PATCH 4/6] wifi: mac80211: kunit: generalize public action test

From: Johannes Berg <[email protected]>

Generalize the test to be able to handle arbitrary
action categories and non-action frames, for further
test expansion.

Signed-off-by: Johannes Berg <[email protected]>
Reviewed-by: Gregory Greenman <[email protected]>
---
net/mac80211/tests/mfp.c | 78 +++++++++++++++++++++++++++++-----------
1 file changed, 57 insertions(+), 21 deletions(-)

diff --git a/net/mac80211/tests/mfp.c b/net/mac80211/tests/mfp.c
index 629a5801c08f..6ec31386c0df 100644
--- a/net/mac80211/tests/mfp.c
+++ b/net/mac80211/tests/mfp.c
@@ -13,34 +13,52 @@ MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);

static const struct mfp_test_case {
const char *desc;
- bool sta, mfp, decrypted, unicast, protected_dual;
+ bool sta, mfp, decrypted, unicast;
+ u8 category;
+ u8 stype;
+ u8 action;
ieee80211_rx_result result;
-} accept_public_action_cases[] = {
+} accept_mfp_cases[] = {
/* regular public action */
{
.desc = "public action: accept unicast from unknown peer",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PUBLIC,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = true,
.result = RX_CONTINUE,
},
{
.desc = "public action: accept multicast from unknown peer",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PUBLIC,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = false,
.result = RX_CONTINUE,
},
{
.desc = "public action: accept unicast without MFP",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PUBLIC,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = true,
.sta = true,
.result = RX_CONTINUE,
},
{
.desc = "public action: accept multicast without MFP",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PUBLIC,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = false,
.sta = true,
.result = RX_CONTINUE,
},
{
.desc = "public action: drop unicast with MFP",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PUBLIC,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = true,
.sta = true,
.mfp = true,
@@ -48,6 +66,9 @@ static const struct mfp_test_case {
},
{
.desc = "public action: accept multicast with MFP",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PUBLIC,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = false,
.sta = true,
.mfp = true,
@@ -56,33 +77,43 @@ static const struct mfp_test_case {
/* protected dual of public action */
{
.desc = "protected dual: drop unicast from unknown peer",
- .protected_dual = true,
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = true,
.result = RX_DROP_U_UNPROT_DUAL,
},
{
.desc = "protected dual: drop multicast from unknown peer",
- .protected_dual = true,
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = false,
.result = RX_DROP_U_UNPROT_DUAL,
},
{
.desc = "protected dual: drop unicast without MFP",
- .protected_dual = true,
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = true,
.sta = true,
.result = RX_DROP_U_UNPROT_DUAL,
},
{
.desc = "protected dual: drop multicast without MFP",
- .protected_dual = true,
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = false,
.sta = true,
.result = RX_DROP_U_UNPROT_DUAL,
},
{
.desc = "protected dual: drop undecrypted unicast with MFP",
- .protected_dual = true,
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = true,
.sta = true,
.mfp = true,
@@ -90,7 +121,9 @@ static const struct mfp_test_case {
},
{
.desc = "protected dual: drop undecrypted multicast with MFP",
- .protected_dual = true,
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.unicast = false,
.sta = true,
.mfp = true,
@@ -98,7 +131,9 @@ static const struct mfp_test_case {
},
{
.desc = "protected dual: accept unicast with MFP",
- .protected_dual = true,
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.decrypted = true,
.unicast = true,
.sta = true,
@@ -107,7 +142,9 @@ static const struct mfp_test_case {
},
{
.desc = "protected dual: accept multicast with MFP",
- .protected_dual = true,
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION,
+ .action = WLAN_PUB_ACTION_DSE_ENABLEMENT,
.decrypted = true,
.unicast = false,
.sta = true,
@@ -116,11 +153,9 @@ static const struct mfp_test_case {
},
};

-KUNIT_ARRAY_PARAM_DESC(accept_public_action,
- accept_public_action_cases,
- desc);
+KUNIT_ARRAY_PARAM_DESC(accept_mfp, accept_mfp_cases, desc);

-static void accept_public_action(struct kunit *test)
+static void accept_mfp(struct kunit *test)
{
static struct sta_info sta = {};
const struct mfp_test_case *params = test->param_value;
@@ -130,7 +165,7 @@ static void accept_public_action(struct kunit *test)
struct ieee80211_rx_status *status;
struct ieee80211_hdr_3addr hdr = {
.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_ACTION),
+ params->stype),
.addr1 = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
.addr2 = { 0x12, 0x22, 0x33, 0x44, 0x55, 0x66 },
/* A3/BSSID doesn't matter here */
@@ -160,11 +195,12 @@ static void accept_public_action(struct kunit *test)

skb_put_data(rx.skb, &hdr, sizeof(hdr));

- if (params->protected_dual)
- skb_put_u8(rx.skb, WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION);
- else
- skb_put_u8(rx.skb, WLAN_CATEGORY_PUBLIC);
- skb_put_u8(rx.skb, WLAN_PUB_ACTION_DSE_ENABLEMENT);
+ switch (params->stype) {
+ case IEEE80211_STYPE_ACTION:
+ skb_put_u8(rx.skb, params->category);
+ skb_put_u8(rx.skb, params->action);
+ break;
+ }

KUNIT_EXPECT_EQ(test,
ieee80211_drop_unencrypted_mgmt(&rx),
@@ -172,7 +208,7 @@ static void accept_public_action(struct kunit *test)
}

static struct kunit_case mfp_test_cases[] = {
- KUNIT_CASE_PARAM(accept_public_action, accept_public_action_gen_params),
+ KUNIT_CASE_PARAM(accept_mfp, accept_mfp_gen_params),
{}
};

--
2.43.0


2023-12-20 15:24:53

by Benjamin Berg

[permalink] [raw]
Subject: [PATCH 5/6] wifi: mac80211: kunit: extend MFP tests

From: Johannes Berg <[email protected]>

Extend the MFP tests to handle the case of deauth/disassoc
and robust action frames (that are not protected dual of
public action frames).

Signed-off-by: Johannes Berg <[email protected]>
Reviewed-by: Gregory Greenman <[email protected]>
---
net/mac80211/tests/mfp.c | 74 +++++++++++++++++++++++++++++++++++++---
1 file changed, 70 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/tests/mfp.c b/net/mac80211/tests/mfp.c
index 6ec31386c0df..a8dc1601da60 100644
--- a/net/mac80211/tests/mfp.c
+++ b/net/mac80211/tests/mfp.c
@@ -13,7 +13,7 @@ MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);

static const struct mfp_test_case {
const char *desc;
- bool sta, mfp, decrypted, unicast;
+ bool sta, mfp, decrypted, unicast, assoc;
u8 category;
u8 stype;
u8 action;
@@ -151,13 +151,67 @@ static const struct mfp_test_case {
.mfp = true,
.result = RX_CONTINUE,
},
+ /* deauth/disassoc before keys are set */
+ {
+ .desc = "deauth: accept unicast with MFP but w/o key",
+ .stype = IEEE80211_STYPE_DEAUTH,
+ .sta = true,
+ .mfp = true,
+ .unicast = true,
+ .result = RX_CONTINUE,
+ },
+ {
+ .desc = "disassoc: accept unicast with MFP but w/o key",
+ .stype = IEEE80211_STYPE_DEAUTH,
+ .sta = true,
+ .mfp = true,
+ .unicast = true,
+ .result = RX_CONTINUE,
+ },
+ /* non-public robust action frame ... */
+ {
+ .desc = "BA action: drop unicast before assoc",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_BACK,
+ .unicast = true,
+ .sta = true,
+ .result = RX_DROP_U_UNPROT_ROBUST_ACTION,
+ },
+ {
+ .desc = "BA action: drop unprotected after assoc",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_BACK,
+ .unicast = true,
+ .sta = true,
+ .mfp = true,
+ .result = RX_DROP_U_UNPROT_UCAST_MGMT,
+ },
+ {
+ .desc = "BA action: accept unprotected without MFP",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_BACK,
+ .unicast = true,
+ .sta = true,
+ .assoc = true,
+ .mfp = false,
+ .result = RX_CONTINUE,
+ },
+ {
+ .desc = "BA action: drop unprotected with MFP",
+ .stype = IEEE80211_STYPE_ACTION,
+ .category = WLAN_CATEGORY_BACK,
+ .unicast = true,
+ .sta = true,
+ .mfp = true,
+ .result = RX_DROP_U_UNPROT_UCAST_MGMT,
+ },
};

KUNIT_ARRAY_PARAM_DESC(accept_mfp, accept_mfp_cases, desc);

static void accept_mfp(struct kunit *test)
{
- static struct sta_info sta = {};
+ static struct sta_info sta;
const struct mfp_test_case *params = test->param_value;
struct ieee80211_rx_data rx = {
.sta = params->sta ? &sta : NULL,
@@ -171,6 +225,8 @@ static void accept_mfp(struct kunit *test)
/* A3/BSSID doesn't matter here */
};

+ memset(&sta, 0, sizeof(sta));
+
if (!params->sta) {
KUNIT_ASSERT_FALSE(test, params->mfp);
KUNIT_ASSERT_FALSE(test, params->decrypted);
@@ -179,6 +235,9 @@ static void accept_mfp(struct kunit *test)
if (params->mfp)
set_sta_flag(&sta, WLAN_STA_MFP);

+ if (params->assoc)
+ set_bit(WLAN_STA_ASSOC, &sta._flags);
+
rx.skb = kunit_zalloc_skb(test, 128, GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, rx.skb);
status = IEEE80211_SKB_RXCB(rx.skb);
@@ -200,11 +259,18 @@ static void accept_mfp(struct kunit *test)
skb_put_u8(rx.skb, params->category);
skb_put_u8(rx.skb, params->action);
break;
+ case IEEE80211_STYPE_DEAUTH:
+ case IEEE80211_STYPE_DISASSOC: {
+ __le16 reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
+
+ skb_put_data(rx.skb, &reason, sizeof(reason));
+ }
+ break;
}

KUNIT_EXPECT_EQ(test,
- ieee80211_drop_unencrypted_mgmt(&rx),
- params->result);
+ (__force u32)ieee80211_drop_unencrypted_mgmt(&rx),
+ (__force u32)params->result);
}

static struct kunit_case mfp_test_cases[] = {
--
2.43.0


2023-12-20 15:25:01

by Benjamin Berg

[permalink] [raw]
Subject: [PATCH 6/6] wifi: cfg80211: tests: add some scanning related tests

From: Benjamin Berg <[email protected]>

This adds some scanning related tests, mainly exercising the ML element
parsing and inheritance.

Signed-off-by: Benjamin Berg <[email protected]>
Reviewed-by: Johannes Berg <[email protected]>
---
net/wireless/core.h | 13 +-
net/wireless/scan.c | 9 +-
net/wireless/tests/Makefile | 2 +-
net/wireless/tests/scan.c | 625 ++++++++++++++++++++++++++++++++++++
net/wireless/tests/util.c | 56 ++++
net/wireless/tests/util.h | 66 ++++
6 files changed, 766 insertions(+), 5 deletions(-)
create mode 100644 net/wireless/tests/scan.c
create mode 100644 net/wireless/tests/util.c
create mode 100644 net/wireless/tests/util.h

diff --git a/net/wireless/core.h b/net/wireless/core.h
index 1963958263d2..13657a85cf61 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -3,7 +3,7 @@
* Wireless configuration interface internals.
*
* Copyright 2006-2010 Johannes Berg <[email protected]>
- * Copyright (C) 2018-2022 Intel Corporation
+ * Copyright (C) 2018-2023 Intel Corporation
*/
#ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H
@@ -549,4 +549,15 @@ int cfg80211_remove_virtual_intf(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);
void cfg80211_wdev_release_link_bsses(struct wireless_dev *wdev, u16 link_mask);

+#if IS_ENABLED(CONFIG_CFG80211_KUNIT_TEST)
+#define EXPORT_SYMBOL_IF_CFG80211_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym)
+#define VISIBLE_IF_CFG80211_KUNIT
+size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
+ const u8 *subie, size_t subie_len,
+ u8 *new_ie, size_t new_ie_len);
+#else
+#define EXPORT_SYMBOL_IF_CFG80211_KUNIT(sym)
+#define VISIBLE_IF_CFG80211_KUNIT static
+#endif /* IS_ENABLED(CONFIG_CFG80211_KUNIT_TEST) */
+
#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 3d260c99c348..f6c0421f4d77 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -20,6 +20,7 @@
#include <net/cfg80211.h>
#include <net/cfg80211-wext.h>
#include <net/iw_handler.h>
+#include <kunit/visibility.h>
#include "core.h"
#include "nl80211.h"
#include "wext-compat.h"
@@ -303,9 +304,10 @@ static size_t cfg80211_copy_elem_with_frags(const struct element *elem,
return *pos - buf;
}

-static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
- const u8 *subie, size_t subie_len,
- u8 *new_ie, size_t new_ie_len)
+VISIBLE_IF_CFG80211_KUNIT size_t
+cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
+ const u8 *subie, size_t subie_len,
+ u8 *new_ie, size_t new_ie_len)
{
const struct element *non_inherit_elem, *parent, *sub;
u8 *pos = new_ie;
@@ -413,6 +415,7 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,

return pos - new_ie;
}
+EXPORT_SYMBOL_IF_CFG80211_KUNIT(cfg80211_gen_new_ie);

static bool is_bss(struct cfg80211_bss *a, const u8 *bssid,
const u8 *ssid, size_t ssid_len)
diff --git a/net/wireless/tests/Makefile b/net/wireless/tests/Makefile
index fa8e297bbc5e..1f6622fcb758 100644
--- a/net/wireless/tests/Makefile
+++ b/net/wireless/tests/Makefile
@@ -1,3 +1,3 @@
-cfg80211-tests-y += module.o fragmentation.o
+cfg80211-tests-y += module.o fragmentation.o scan.o util.o

obj-$(CONFIG_CFG80211_KUNIT_TEST) += cfg80211-tests.o
diff --git a/net/wireless/tests/scan.c b/net/wireless/tests/scan.c
new file mode 100644
index 000000000000..77854161cd22
--- /dev/null
+++ b/net/wireless/tests/scan.c
@@ -0,0 +1,625 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KUnit tests for inform_bss functions
+ *
+ * Copyright (C) 2023 Intel Corporation
+ */
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <kunit/test.h>
+#include <kunit/skbuff.h>
+#include "../core.h"
+#include "util.h"
+
+/* mac80211 helpers for element building */
+#include "../../mac80211/ieee80211_i.h"
+
+MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+
+struct test_elem {
+ u8 id;
+ u8 len;
+ union {
+ u8 data[255];
+ struct {
+ u8 eid;
+ u8 edata[254];
+ };
+ };
+};
+
+static struct gen_new_ie_case {
+ const char *desc;
+ struct test_elem parent_ies[16];
+ struct test_elem child_ies[16];
+ struct test_elem result_ies[16];
+} gen_new_ie_cases[] = {
+ {
+ .desc = "ML not inherited",
+ .parent_ies = {
+ { .id = WLAN_EID_EXTENSION, .len = 255,
+ .eid = WLAN_EID_EXT_EHT_MULTI_LINK },
+ },
+ .child_ies = {
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ .result_ies = {
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ },
+ {
+ .desc = "fragments are ignored if previous len not 255",
+ .parent_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 254, },
+ { .id = WLAN_EID_FRAGMENT, .len = 125, },
+ },
+ .child_ies = {
+ { .id = WLAN_EID_SSID, .len = 2 },
+ { .id = WLAN_EID_FRAGMENT, .len = 125, },
+ },
+ .result_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 254, },
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ },
+ {
+ .desc = "fragments inherited",
+ .parent_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
+ { .id = WLAN_EID_FRAGMENT, .len = 125, },
+ },
+ .child_ies = {
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ .result_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
+ { .id = WLAN_EID_FRAGMENT, .len = 125, },
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ },
+ {
+ .desc = "fragments copied",
+ .parent_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
+ { .id = WLAN_EID_FRAGMENT, .len = 125, },
+ },
+ .child_ies = {
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ .result_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
+ { .id = WLAN_EID_FRAGMENT, .len = 125, },
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ },
+ {
+ .desc = "multiple elements inherit",
+ .parent_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
+ { .id = WLAN_EID_FRAGMENT, .len = 125, },
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 123, },
+ },
+ .child_ies = {
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ .result_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
+ { .id = WLAN_EID_FRAGMENT, .len = 125, },
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 123, },
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ },
+ {
+ .desc = "one child element overrides",
+ .parent_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 255, },
+ { .id = WLAN_EID_FRAGMENT, .len = 125, },
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 123, },
+ },
+ .child_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 127, },
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ .result_ies = {
+ { .id = WLAN_EID_REDUCED_NEIGHBOR_REPORT, .len = 127, },
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ },
+ {
+ .desc = "empty elements from parent",
+ .parent_ies = {
+ { .id = 0x1, .len = 0, },
+ { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 },
+ },
+ .child_ies = {
+ },
+ .result_ies = {
+ { .id = 0x1, .len = 0, },
+ { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 },
+ },
+ },
+ {
+ .desc = "empty elements from child",
+ .parent_ies = {
+ },
+ .child_ies = {
+ { .id = 0x1, .len = 0, },
+ { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 },
+ },
+ .result_ies = {
+ { .id = 0x1, .len = 0, },
+ { .id = WLAN_EID_EXTENSION, .len = 1, .eid = 0x10 },
+ },
+ },
+ {
+ .desc = "invalid extended elements ignored",
+ .parent_ies = {
+ { .id = WLAN_EID_EXTENSION, .len = 0 },
+ },
+ .child_ies = {
+ { .id = WLAN_EID_EXTENSION, .len = 0 },
+ },
+ .result_ies = {
+ },
+ },
+ {
+ .desc = "multiple extended elements",
+ .parent_ies = {
+ { .id = WLAN_EID_EXTENSION, .len = 3,
+ .eid = WLAN_EID_EXT_HE_CAPABILITY },
+ { .id = WLAN_EID_EXTENSION, .len = 5,
+ .eid = WLAN_EID_EXT_ASSOC_DELAY_INFO },
+ { .id = WLAN_EID_EXTENSION, .len = 7,
+ .eid = WLAN_EID_EXT_HE_OPERATION },
+ { .id = WLAN_EID_EXTENSION, .len = 11,
+ .eid = WLAN_EID_EXT_FILS_REQ_PARAMS },
+ },
+ .child_ies = {
+ { .id = WLAN_EID_SSID, .len = 13 },
+ { .id = WLAN_EID_EXTENSION, .len = 17,
+ .eid = WLAN_EID_EXT_HE_CAPABILITY },
+ { .id = WLAN_EID_EXTENSION, .len = 11,
+ .eid = WLAN_EID_EXT_FILS_KEY_CONFIRM },
+ { .id = WLAN_EID_EXTENSION, .len = 19,
+ .eid = WLAN_EID_EXT_HE_OPERATION },
+ },
+ .result_ies = {
+ { .id = WLAN_EID_EXTENSION, .len = 17,
+ .eid = WLAN_EID_EXT_HE_CAPABILITY },
+ { .id = WLAN_EID_EXTENSION, .len = 5,
+ .eid = WLAN_EID_EXT_ASSOC_DELAY_INFO },
+ { .id = WLAN_EID_EXTENSION, .len = 19,
+ .eid = WLAN_EID_EXT_HE_OPERATION },
+ { .id = WLAN_EID_EXTENSION, .len = 11,
+ .eid = WLAN_EID_EXT_FILS_REQ_PARAMS },
+ { .id = WLAN_EID_SSID, .len = 13 },
+ { .id = WLAN_EID_EXTENSION, .len = 11,
+ .eid = WLAN_EID_EXT_FILS_KEY_CONFIRM },
+ },
+ },
+ {
+ .desc = "non-inherit element",
+ .parent_ies = {
+ { .id = 0x1, .len = 7, },
+ { .id = 0x2, .len = 11, },
+ { .id = 0x3, .len = 13, },
+ { .id = WLAN_EID_EXTENSION, .len = 17, .eid = 0x10 },
+ { .id = WLAN_EID_EXTENSION, .len = 19, .eid = 0x11 },
+ { .id = WLAN_EID_EXTENSION, .len = 23, .eid = 0x12 },
+ { .id = WLAN_EID_EXTENSION, .len = 29, .eid = 0x14 },
+ },
+ .child_ies = {
+ { .id = WLAN_EID_EXTENSION,
+ .eid = WLAN_EID_EXT_NON_INHERITANCE,
+ .len = 10,
+ .edata = { 0x3, 0x1, 0x2, 0x3,
+ 0x4, 0x10, 0x11, 0x13, 0x14 } },
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ .result_ies = {
+ { .id = WLAN_EID_EXTENSION, .len = 23, .eid = 0x12 },
+ { .id = WLAN_EID_SSID, .len = 2 },
+ },
+ },
+};
+KUNIT_ARRAY_PARAM_DESC(gen_new_ie, gen_new_ie_cases, desc)
+
+static void test_gen_new_ie(struct kunit *test)
+{
+ const struct gen_new_ie_case *params = test->param_value;
+ struct sk_buff *parent = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
+ struct sk_buff *child = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
+ struct sk_buff *reference = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
+ u8 *out = kunit_kzalloc(test, IEEE80211_MAX_DATA_LEN, GFP_KERNEL);
+ size_t len;
+ int i;
+
+ KUNIT_ASSERT_NOT_NULL(test, parent);
+ KUNIT_ASSERT_NOT_NULL(test, child);
+ KUNIT_ASSERT_NOT_NULL(test, reference);
+ KUNIT_ASSERT_NOT_NULL(test, out);
+
+ for (i = 0; i < ARRAY_SIZE(params->parent_ies); i++) {
+ if (params->parent_ies[i].len != 0) {
+ skb_put_u8(parent, params->parent_ies[i].id);
+ skb_put_u8(parent, params->parent_ies[i].len);
+ skb_put_data(parent, params->parent_ies[i].data,
+ params->parent_ies[i].len);
+ }
+
+ if (params->child_ies[i].len != 0) {
+ skb_put_u8(child, params->child_ies[i].id);
+ skb_put_u8(child, params->child_ies[i].len);
+ skb_put_data(child, params->child_ies[i].data,
+ params->child_ies[i].len);
+ }
+
+ if (params->result_ies[i].len != 0) {
+ skb_put_u8(reference, params->result_ies[i].id);
+ skb_put_u8(reference, params->result_ies[i].len);
+ skb_put_data(reference, params->result_ies[i].data,
+ params->result_ies[i].len);
+ }
+ }
+
+ len = cfg80211_gen_new_ie(parent->data, parent->len,
+ child->data, child->len,
+ out, IEEE80211_MAX_DATA_LEN);
+ KUNIT_EXPECT_EQ(test, len, reference->len);
+ KUNIT_EXPECT_MEMEQ(test, out, reference->data, reference->len);
+ memset(out, 0, IEEE80211_MAX_DATA_LEN);
+
+ /* Exactly enough space */
+ len = cfg80211_gen_new_ie(parent->data, parent->len,
+ child->data, child->len,
+ out, reference->len);
+ KUNIT_EXPECT_EQ(test, len, reference->len);
+ KUNIT_EXPECT_MEMEQ(test, out, reference->data, reference->len);
+ memset(out, 0, IEEE80211_MAX_DATA_LEN);
+
+ /* Not enough space (or expected zero length) */
+ len = cfg80211_gen_new_ie(parent->data, parent->len,
+ child->data, child->len,
+ out, reference->len - 1);
+ KUNIT_EXPECT_EQ(test, len, 0);
+}
+
+static void test_gen_new_ie_malformed(struct kunit *test)
+{
+ struct sk_buff *malformed = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
+ u8 *out = kunit_kzalloc(test, IEEE80211_MAX_DATA_LEN, GFP_KERNEL);
+ size_t len;
+
+ KUNIT_ASSERT_NOT_NULL(test, malformed);
+ KUNIT_ASSERT_NOT_NULL(test, out);
+
+ skb_put_u8(malformed, WLAN_EID_SSID);
+ skb_put_u8(malformed, 3);
+ skb_put(malformed, 3);
+ skb_put_u8(malformed, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
+ skb_put_u8(malformed, 10);
+ skb_put(malformed, 9);
+
+ len = cfg80211_gen_new_ie(malformed->data, malformed->len,
+ out, 0,
+ out, IEEE80211_MAX_DATA_LEN);
+ KUNIT_EXPECT_EQ(test, len, 5);
+
+ len = cfg80211_gen_new_ie(out, 0,
+ malformed->data, malformed->len,
+ out, IEEE80211_MAX_DATA_LEN);
+ KUNIT_EXPECT_EQ(test, len, 5);
+}
+
+struct inform_bss {
+ struct kunit *test;
+
+ int inform_bss_count;
+};
+
+static void inform_bss_inc_counter(struct wiphy *wiphy,
+ struct cfg80211_bss *bss,
+ const struct cfg80211_bss_ies *ies,
+ void *drv_data)
+{
+ struct inform_bss *ctx = t_wiphy_ctx(wiphy);
+
+ ctx->inform_bss_count++;
+
+ rcu_read_lock();
+ KUNIT_EXPECT_PTR_EQ(ctx->test, drv_data, ctx);
+ KUNIT_EXPECT_PTR_EQ(ctx->test, ies, rcu_dereference(bss->ies));
+ rcu_read_unlock();
+}
+
+static void test_inform_bss_ssid_only(struct kunit *test)
+{
+ struct inform_bss ctx = {
+ .test = test,
+ };
+ struct wiphy *wiphy = T_WIPHY(test, ctx);
+ struct t_wiphy_priv *w_priv = wiphy_priv(wiphy);
+ struct cfg80211_inform_bss inform_bss = {
+ .signal = 50,
+ .drv_data = &ctx,
+ };
+ const u8 bssid[ETH_ALEN] = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x66 };
+ u64 tsf = 0x1000000000000000ULL;
+ int beacon_int = 100;
+ u16 capability = 0x1234;
+ static const u8 input[] = {
+ [0] = WLAN_EID_SSID,
+ [1] = 4,
+ [2] = 'T', 'E', 'S', 'T'
+ };
+ struct cfg80211_bss *bss, *other;
+ const struct cfg80211_bss_ies *ies;
+
+ w_priv->ops->inform_bss = inform_bss_inc_counter;
+
+ inform_bss.chan = ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(2412));
+ KUNIT_ASSERT_NOT_NULL(test, inform_bss.chan);
+
+ bss = cfg80211_inform_bss_data(wiphy, &inform_bss,
+ CFG80211_BSS_FTYPE_PRESP, bssid, tsf,
+ capability, beacon_int,
+ input, sizeof(input),
+ GFP_KERNEL);
+ KUNIT_EXPECT_NOT_NULL(test, bss);
+ KUNIT_EXPECT_EQ(test, ctx.inform_bss_count, 1);
+
+ /* Check values in returned bss are correct */
+ KUNIT_EXPECT_EQ(test, bss->signal, inform_bss.signal);
+ KUNIT_EXPECT_EQ(test, bss->beacon_interval, beacon_int);
+ KUNIT_EXPECT_EQ(test, bss->capability, capability);
+ KUNIT_EXPECT_EQ(test, bss->bssid_index, 0);
+ KUNIT_EXPECT_PTR_EQ(test, bss->channel, inform_bss.chan);
+ KUNIT_EXPECT_MEMEQ(test, bssid, bss->bssid, sizeof(bssid));
+
+ /* Check the IEs have the expected value */
+ rcu_read_lock();
+ ies = rcu_dereference(bss->ies);
+ KUNIT_EXPECT_NOT_NULL(test, ies);
+ KUNIT_EXPECT_EQ(test, ies->tsf, tsf);
+ KUNIT_EXPECT_EQ(test, ies->len, sizeof(input));
+ KUNIT_EXPECT_MEMEQ(test, ies->data, input, sizeof(input));
+ rcu_read_unlock();
+
+ /* Check we can look up the BSS - by SSID */
+ other = cfg80211_get_bss(wiphy, NULL, NULL, "TEST", 4,
+ IEEE80211_BSS_TYPE_ANY,
+ IEEE80211_PRIVACY_ANY);
+ KUNIT_EXPECT_PTR_EQ(test, bss, other);
+ cfg80211_put_bss(wiphy, other);
+
+ /* Check we can look up the BSS - by BSSID */
+ other = cfg80211_get_bss(wiphy, NULL, bssid, NULL, 0,
+ IEEE80211_BSS_TYPE_ANY,
+ IEEE80211_PRIVACY_ANY);
+ KUNIT_EXPECT_PTR_EQ(test, bss, other);
+ cfg80211_put_bss(wiphy, other);
+
+ cfg80211_put_bss(wiphy, bss);
+}
+
+static struct inform_bss_ml_sta_case {
+ const char *desc;
+ int mld_id;
+ bool sta_prof_vendor_elems;
+} inform_bss_ml_sta_cases[] = {
+ { .desc = "no_mld_id", .mld_id = 0, .sta_prof_vendor_elems = false },
+ { .desc = "mld_id_eq_1", .mld_id = 1, .sta_prof_vendor_elems = true },
+};
+KUNIT_ARRAY_PARAM_DESC(inform_bss_ml_sta, inform_bss_ml_sta_cases, desc)
+
+static void test_inform_bss_ml_sta(struct kunit *test)
+{
+ const struct inform_bss_ml_sta_case *params = test->param_value;
+ struct inform_bss ctx = {
+ .test = test,
+ };
+ struct wiphy *wiphy = T_WIPHY(test, ctx);
+ struct t_wiphy_priv *w_priv = wiphy_priv(wiphy);
+ struct cfg80211_inform_bss inform_bss = {
+ .signal = 50,
+ .drv_data = &ctx,
+ };
+ struct cfg80211_bss *bss, *link_bss;
+ const struct cfg80211_bss_ies *ies;
+
+ /* sending station */
+ const u8 bssid[ETH_ALEN] = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x66 };
+ u64 tsf = 0x1000000000000000ULL;
+ int beacon_int = 100;
+ u16 capability = 0x1234;
+
+ /* Building the frame *************************************************/
+ struct sk_buff *input = kunit_zalloc_skb(test, 1024, GFP_KERNEL);
+ u8 *len_mle, *len_prof;
+ u8 link_id = 2;
+ struct {
+ struct ieee80211_neighbor_ap_info info;
+ struct ieee80211_tbtt_info_ge_11 ap;
+ } __packed rnr = {
+ .info = {
+ .tbtt_info_hdr = u8_encode_bits(0, IEEE80211_AP_INFO_TBTT_HDR_COUNT),
+ .tbtt_info_len = sizeof(struct ieee80211_tbtt_info_ge_11),
+ .op_class = 81,
+ .channel = 11,
+ },
+ .ap = {
+ .tbtt_offset = 0xff,
+ .bssid = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x67 },
+ .short_ssid = 0, /* unused */
+ .bss_params = 0,
+ .psd_20 = 0,
+ .mld_params.mld_id = params->mld_id,
+ .mld_params.params =
+ le16_encode_bits(link_id,
+ IEEE80211_RNR_MLD_PARAMS_LINK_ID),
+ }
+ };
+ struct {
+ __le16 control;
+ u8 var_len;
+ u8 mld_mac_addr[ETH_ALEN];
+ u8 link_id_info;
+ u8 params_change_count;
+ __le16 mld_caps_and_ops;
+ u8 mld_id;
+ __le16 ext_mld_caps_and_ops;
+ } __packed mle_basic_common_info = {
+ .control =
+ cpu_to_le16(IEEE80211_ML_CONTROL_TYPE_BASIC |
+ IEEE80211_MLC_BASIC_PRES_BSS_PARAM_CH_CNT |
+ IEEE80211_MLC_BASIC_PRES_LINK_ID |
+ (params->mld_id ? IEEE80211_MLC_BASIC_PRES_MLD_ID : 0) |
+ IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP),
+ .mld_id = params->mld_id,
+ .mld_caps_and_ops = cpu_to_le16(0x0102),
+ .ext_mld_caps_and_ops = cpu_to_le16(0x0304),
+ .var_len = sizeof(mle_basic_common_info) - 2 -
+ (params->mld_id ? 0 : 1),
+ .mld_mac_addr = { 0x10, 0x22, 0x33, 0x44, 0x55, 0x60 },
+ };
+ struct {
+ __le16 control;
+ u8 var_len;
+ u8 bssid[ETH_ALEN];
+ __le16 beacon_int;
+ __le64 tsf_offset;
+ __le16 capabilities; /* already part of payload */
+ } __packed sta_prof = {
+ .control =
+ cpu_to_le16(IEEE80211_MLE_STA_CONTROL_COMPLETE_PROFILE |
+ IEEE80211_MLE_STA_CONTROL_STA_MAC_ADDR_PRESENT |
+ IEEE80211_MLE_STA_CONTROL_BEACON_INT_PRESENT |
+ IEEE80211_MLE_STA_CONTROL_TSF_OFFS_PRESENT |
+ u16_encode_bits(link_id,
+ IEEE80211_MLE_STA_CONTROL_LINK_ID)),
+ .var_len = sizeof(sta_prof) - 2 - 2,
+ .bssid = { *rnr.ap.bssid },
+ .beacon_int = cpu_to_le16(101),
+ .tsf_offset = cpu_to_le64(-123ll),
+ .capabilities = cpu_to_le16(0xdead),
+ };
+
+ KUNIT_ASSERT_NOT_NULL(test, input);
+
+ w_priv->ops->inform_bss = inform_bss_inc_counter;
+
+ inform_bss.chan = ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(2412));
+ KUNIT_ASSERT_NOT_NULL(test, inform_bss.chan);
+
+ skb_put_u8(input, WLAN_EID_SSID);
+ skb_put_u8(input, 4);
+ skb_put_data(input, "TEST", 4);
+
+ skb_put_u8(input, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
+ skb_put_u8(input, sizeof(rnr));
+ skb_put_data(input, &rnr, sizeof(rnr));
+
+ /* build a multi-link element */
+ skb_put_u8(input, WLAN_EID_EXTENSION);
+ len_mle = skb_put(input, 1);
+ skb_put_u8(input, WLAN_EID_EXT_EHT_MULTI_LINK);
+ skb_put_data(input, &mle_basic_common_info, sizeof(mle_basic_common_info));
+ if (!params->mld_id)
+ t_skb_remove_member(input, typeof(mle_basic_common_info), mld_id);
+ /* with a STA profile inside */
+ skb_put_u8(input, IEEE80211_MLE_SUBELEM_PER_STA_PROFILE);
+ len_prof = skb_put(input, 1);
+ skb_put_data(input, &sta_prof, sizeof(sta_prof));
+
+ if (params->sta_prof_vendor_elems) {
+ /* Put two (vendor) element into sta_prof */
+ skb_put_u8(input, WLAN_EID_VENDOR_SPECIFIC);
+ skb_put_u8(input, 160);
+ skb_put(input, 160);
+
+ skb_put_u8(input, WLAN_EID_VENDOR_SPECIFIC);
+ skb_put_u8(input, 165);
+ skb_put(input, 165);
+ }
+
+ /* fragment STA profile */
+ ieee80211_fragment_element(input, len_prof,
+ IEEE80211_MLE_SUBELEM_FRAGMENT);
+ /* fragment MLE */
+ ieee80211_fragment_element(input, len_mle, WLAN_EID_FRAGMENT);
+
+ /* Put a (vendor) element after the ML element */
+ skb_put_u8(input, WLAN_EID_VENDOR_SPECIFIC);
+ skb_put_u8(input, 155);
+ skb_put(input, 155);
+
+ /* Submit *************************************************************/
+ bss = cfg80211_inform_bss_data(wiphy, &inform_bss,
+ CFG80211_BSS_FTYPE_PRESP, bssid, tsf,
+ capability, beacon_int,
+ input->data, input->len,
+ GFP_KERNEL);
+ KUNIT_EXPECT_NOT_NULL(test, bss);
+ KUNIT_EXPECT_EQ(test, ctx.inform_bss_count, 2);
+
+ /* Check link_bss *****************************************************/
+ link_bss = cfg80211_get_bss(wiphy, NULL, sta_prof.bssid, NULL, 0,
+ IEEE80211_BSS_TYPE_ANY,
+ IEEE80211_PRIVACY_ANY);
+ KUNIT_ASSERT_NOT_NULL(test, link_bss);
+ KUNIT_EXPECT_EQ(test, link_bss->signal, 0);
+ KUNIT_EXPECT_EQ(test, link_bss->beacon_interval,
+ le16_to_cpu(sta_prof.beacon_int));
+ KUNIT_EXPECT_EQ(test, link_bss->capability,
+ le16_to_cpu(sta_prof.capabilities));
+ KUNIT_EXPECT_EQ(test, link_bss->bssid_index, 0);
+ KUNIT_EXPECT_PTR_EQ(test, link_bss->channel,
+ ieee80211_get_channel_khz(wiphy, MHZ_TO_KHZ(2462)));
+
+ rcu_read_lock();
+ ies = rcu_dereference(link_bss->ies);
+ KUNIT_EXPECT_NOT_NULL(test, ies);
+ KUNIT_EXPECT_EQ(test, ies->tsf, tsf + le64_to_cpu(sta_prof.tsf_offset));
+ /* Resulting length should be:
+ * SSID (inherited) + RNR (inherited) + vendor element(s) +
+ * MLE common info + MLE header and control
+ */
+ if (params->sta_prof_vendor_elems)
+ KUNIT_EXPECT_EQ(test, ies->len,
+ 6 + 2 + sizeof(rnr) + 2 + 160 + 2 + 165 +
+ mle_basic_common_info.var_len + 5);
+ else
+ KUNIT_EXPECT_EQ(test, ies->len,
+ 6 + 2 + sizeof(rnr) + 2 + 155 +
+ mle_basic_common_info.var_len + 5);
+ rcu_read_unlock();
+
+ cfg80211_put_bss(wiphy, bss);
+ cfg80211_put_bss(wiphy, link_bss);
+}
+
+static struct kunit_case gen_new_ie_test_cases[] = {
+ KUNIT_CASE_PARAM(test_gen_new_ie, gen_new_ie_gen_params),
+ KUNIT_CASE(test_gen_new_ie_malformed),
+ {}
+};
+
+static struct kunit_suite gen_new_ie = {
+ .name = "cfg80211-ie-generation",
+ .test_cases = gen_new_ie_test_cases,
+};
+
+kunit_test_suite(gen_new_ie);
+
+static struct kunit_case inform_bss_test_cases[] = {
+ KUNIT_CASE(test_inform_bss_ssid_only),
+ KUNIT_CASE_PARAM(test_inform_bss_ml_sta, inform_bss_ml_sta_gen_params),
+ {}
+};
+
+static struct kunit_suite inform_bss = {
+ .name = "cfg80211-inform-bss",
+ .test_cases = inform_bss_test_cases,
+};
+
+kunit_test_suite(inform_bss);
diff --git a/net/wireless/tests/util.c b/net/wireless/tests/util.c
new file mode 100644
index 000000000000..8abdaeb820ce
--- /dev/null
+++ b/net/wireless/tests/util.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KUnit fixture to have a (configurable) wiphy
+ *
+ * Copyright (C) 2023 Intel Corporation
+ */
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <kunit/test.h>
+#include <kunit/test-bug.h>
+#include "util.h"
+
+int t_wiphy_init(struct kunit_resource *resource, void *ctx)
+{
+ struct kunit *test = kunit_get_current_test();
+ struct cfg80211_ops *ops;
+ struct wiphy *wiphy;
+ struct t_wiphy_priv *priv;
+
+ ops = kzalloc(sizeof(*ops), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, ops);
+
+ wiphy = wiphy_new_nm(ops, sizeof(*priv), "kunit");
+ KUNIT_ASSERT_NOT_NULL(test, wiphy);
+
+ priv = wiphy_priv(wiphy);
+ priv->ctx = ctx;
+ priv->ops = ops;
+
+ /* Initialize channels, feel free to add more here channels/bands */
+ memcpy(priv->channels_2ghz, channels_2ghz, sizeof(channels_2ghz));
+ wiphy->bands[NL80211_BAND_2GHZ] = &priv->band_2ghz;
+ priv->band_2ghz.channels = priv->channels_2ghz;
+ priv->band_2ghz.n_channels = ARRAY_SIZE(channels_2ghz);
+
+ resource->data = wiphy;
+ resource->name = "wiphy";
+
+ return 0;
+}
+
+void t_wiphy_exit(struct kunit_resource *resource)
+{
+ struct t_wiphy_priv *priv;
+ struct cfg80211_ops *ops;
+
+ priv = wiphy_priv(resource->data);
+ ops = priv->ops;
+
+ /* Should we ensure anything about the state here?
+ * e.g. full destruction or no calls to any ops on destruction?
+ */
+
+ wiphy_free(resource->data);
+ kfree(ops);
+}
diff --git a/net/wireless/tests/util.h b/net/wireless/tests/util.h
new file mode 100644
index 000000000000..6de712e0d432
--- /dev/null
+++ b/net/wireless/tests/util.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Utilities for cfg80211 unit testing
+ *
+ * Copyright (C) 2023 Intel Corporation
+ */
+#ifndef __CFG80211_UTILS_H
+#define __CFG80211_UTILS_H
+
+#define CHAN2G(_freq) { \
+ .band = NL80211_BAND_2GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_freq), \
+}
+
+static const struct ieee80211_channel channels_2ghz[] = {
+ CHAN2G(2412), /* Channel 1 */
+ CHAN2G(2417), /* Channel 2 */
+ CHAN2G(2422), /* Channel 3 */
+ CHAN2G(2427), /* Channel 4 */
+ CHAN2G(2432), /* Channel 5 */
+ CHAN2G(2437), /* Channel 6 */
+ CHAN2G(2442), /* Channel 7 */
+ CHAN2G(2447), /* Channel 8 */
+ CHAN2G(2452), /* Channel 9 */
+ CHAN2G(2457), /* Channel 10 */
+ CHAN2G(2462), /* Channel 11 */
+ CHAN2G(2467), /* Channel 12 */
+ CHAN2G(2472), /* Channel 13 */
+ CHAN2G(2484), /* Channel 14 */
+};
+
+struct t_wiphy_priv {
+ struct kunit *test;
+ struct cfg80211_ops *ops;
+
+ void *ctx;
+
+ struct ieee80211_supported_band band_2ghz;
+ struct ieee80211_channel channels_2ghz[ARRAY_SIZE(channels_2ghz)];
+};
+
+#define T_WIPHY(test, ctx) ({ \
+ struct wiphy *__wiphy = \
+ kunit_alloc_resource(test, t_wiphy_init, \
+ t_wiphy_exit, \
+ GFP_KERNEL, &(ctx)); \
+ \
+ KUNIT_ASSERT_NOT_NULL(test, __wiphy); \
+ __wiphy; \
+ })
+#define t_wiphy_ctx(wiphy) (((struct t_wiphy_priv *)wiphy_priv(wiphy))->ctx)
+
+int t_wiphy_init(struct kunit_resource *resource, void *data);
+void t_wiphy_exit(struct kunit_resource *resource);
+
+#define t_skb_remove_member(skb, type, member) do { \
+ memmove((skb)->data + (skb)->len - sizeof(type) + \
+ offsetof(type, member), \
+ (skb)->data + (skb)->len - sizeof(type) + \
+ offsetofend(type, member), \
+ offsetofend(type, member)); \
+ skb_trim(skb, (skb)->len - sizeof_field(type, member)); \
+ } while (0)
+
+#endif /* __CFG80211_UTILS_H */
--
2.43.0


2023-12-21 19:39:25

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/6] Add some more cfg80211 and mac80211 kunit tests

>
> This patchset adds a couple of helpers for kunit as well as tests for
> cfg80211 and mac80211 that use them.

I can take this through the wireless tree, but then I'd like to have
ACKs from kunit folks for the kunit patches:

> kunit: add parameter generation macro using description from array
> kunit: add a convenience allocation wrapper for SKBs
>

Thanks,
johannes

2023-12-21 20:08:00

by Shuah Khan

[permalink] [raw]
Subject: Re: [PATCH 0/6] Add some more cfg80211 and mac80211 kunit tests

On 12/21/23 12:39, Johannes Berg wrote:
>>
>> This patchset adds a couple of helpers for kunit as well as tests for
>> cfg80211 and mac80211 that use them.
>
> I can take this through the wireless tree, but then I'd like to have
> ACKs from kunit folks for the kunit patches:
>

We have run into conflicts in the past with the kunit tree. I take the
kunit patches through linux-kselftest tree. I do want to make sure there
are no conflicts. I don't mind taking these through my tree.


>> kunit: add parameter generation macro using description from array
>> kunit: add a convenience allocation wrapper for SKBs
>>
>

Adding David and Brendan to the thread for their review.

thanks,
-- Shuah



2023-12-21 20:40:59

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/6] Add some more cfg80211 and mac80211 kunit tests

On Thu, 2023-12-21 at 13:06 -0700, Shuah Khan wrote:
> On 12/21/23 12:39, Johannes Berg wrote:
> > >
> > > This patchset adds a couple of helpers for kunit as well as tests for
> > > cfg80211 and mac80211 that use them.
> >
> > I can take this through the wireless tree, but then I'd like to have
> > ACKs from kunit folks for the kunit patches:
> >
>
> We have run into conflicts in the past with the kunit tree. I take the
> kunit patches through linux-kselftest tree. I do want to make sure there
> are no conflicts. I don't mind taking these through my tree.

OK, fair enough.

If you can still put it into 6.8, then I think you can also take the
wireless tests, assuming they pass (I haven't run them in the posted
version). I don't think we'll have conflicts there, we don't have much
work in wireless that's likely to land for 6.8.

johannes

2023-12-21 21:47:10

by Shuah Khan

[permalink] [raw]
Subject: Re: [PATCH 0/6] Add some more cfg80211 and mac80211 kunit tests

On 12/21/23 13:40, Johannes Berg wrote:
> On Thu, 2023-12-21 at 13:06 -0700, Shuah Khan wrote:
>> On 12/21/23 12:39, Johannes Berg wrote:
>>>>
>>>> This patchset adds a couple of helpers for kunit as well as tests for
>>>> cfg80211 and mac80211 that use them.
>>>
>>> I can take this through the wireless tree, but then I'd like to have
>>> ACKs from kunit folks for the kunit patches:
>>>
>>
>> We have run into conflicts in the past with the kunit tree. I take the
>> kunit patches through linux-kselftest tree. I do want to make sure there
>> are no conflicts. I don't mind taking these through my tree.
>
> OK, fair enough.
>
> If you can still put it into 6.8, then I think you can also take the
> wireless tests, assuming they pass (I haven't run them in the posted
> version). I don't think we'll have conflicts there, we don't have much
> work in wireless that's likely to land for 6.8.
>

Sounds good.

David, will you be able to look at these patches and let me know if
I can apply for Linux 6.8-rc1.

thanks,
-- Shuah


2023-12-22 10:03:31

by David Gow

[permalink] [raw]
Subject: Re: [PATCH 1/6] kunit: add parameter generation macro using description from array

On Wed, 20 Dec 2023 at 23:20, <[email protected]> wrote:
>
> From: Benjamin Berg <[email protected]>
>
> The existing KUNIT_ARRAY_PARAM macro requires a separate function to
> get the description. However, in a lot of cases the description can
> just be copied directly from the array. Add a second macro that
> avoids having to write a static function just for a single strscpy.
>
> Signed-off-by: Benjamin Berg <[email protected]>
> ---

I'm generally pretty happy with this, though note the checkpatch warning below.

There was some discussion at plumbers about expanding the
parameterised test APIs, so we may need to adjust the implementation
of this down the line, but I don't think that'll happen for a while,
so don't worry.

With the warnings fixed, this is:

Reviewed-by: David Gow <[email protected]>

I'm okay with this going in via the wireless tree if that's easier;
certainly there are some conflicts with the later patches in this
series and the kunit one.

Cheers,
-- David

> Documentation/dev-tools/kunit/usage.rst | 12 ++++--------
> include/kunit/test.h | 19 +++++++++++++++++++
> 2 files changed, 23 insertions(+), 8 deletions(-)
>
> diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst
> index c27e1646ecd9..b959e5befcbe 100644
> --- a/Documentation/dev-tools/kunit/usage.rst
> +++ b/Documentation/dev-tools/kunit/usage.rst
> @@ -566,13 +566,9 @@ By reusing the same ``cases`` array from above, we can write the test as a
> },
> };
>
> - // Need a helper function to generate a name for each test case.
> - static void case_to_desc(const struct sha1_test_case *t, char *desc)
> - {
> - strcpy(desc, t->str);
> - }
> - // Creates `sha1_gen_params()` to iterate over `cases`.
> - KUNIT_ARRAY_PARAM(sha1, cases, case_to_desc);
> + // Creates `sha1_gen_params()` to iterate over `cases` while using
> + // the struct member `str` for the case description.
> + KUNIT_ARRAY_PARAM_DESC(sha1, cases, str);
>
> // Looks no different from a normal test.
> static void sha1_test(struct kunit *test)
> @@ -588,7 +584,7 @@ By reusing the same ``cases`` array from above, we can write the test as a
> }
>
> // Instead of KUNIT_CASE, we use KUNIT_CASE_PARAM and pass in the
> - // function declared by KUNIT_ARRAY_PARAM.
> + // function declared by KUNIT_ARRAY_PARAM or KUNIT_ARRAY_PARAM_DESC.
> static struct kunit_case sha1_test_cases[] = {
> KUNIT_CASE_PARAM(sha1_test, sha1_gen_params),
> {}
> diff --git a/include/kunit/test.h b/include/kunit/test.h
> index 20ed9f9275c9..2dfa851e1f88 100644
> --- a/include/kunit/test.h
> +++ b/include/kunit/test.h
> @@ -1514,6 +1514,25 @@ do { \
> return NULL; \
> }
>
> +/**
> + * KUNIT_ARRAY_PARAM_DESC() - Define test parameter generator from an array.
> + * @name: prefix for the test parameter generator function.
> + * @array: array of test parameters.
> + * @desc_member: structure member from array element to use as description
> + *
> + * Define function @name_gen_params which uses @array to generate parameters.
> + */
> +#define KUNIT_ARRAY_PARAM_DESC(name, array, desc_member) \
> + static const void *name##_gen_params(const void *prev, char *desc) \
> + { \
> + typeof((array)[0]) *__next = prev ? ((typeof(__next)) prev) + 1 : (array); \

checkpatch is complaining here:
ERROR: need consistent spacing around '*' (ctx:WxV)
#71: FILE: include/kunit/test.h:1528:

+ typeof((array)[0]) *__next = prev ? ((typeof(__next))
prev) + 1 : (array); \

> + if (__next - (array) < ARRAY_SIZE((array))) { \
> + strscpy(desc, __next->desc_member, KUNIT_PARAM_DESC_SIZE); \
> + return __next; \
> + } \
> + return NULL; \
> + }
> +
> // TODO([email protected]): consider eventually migrating users to explicitly
> // include resource.h themselves if they need it.
> #include <kunit/resource.h>
> --
> 2.43.0
>
> --
> You received this message because you are subscribed to the Google Groups "KUnit Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
> To view this discussion on the web visit https://groups.google.com/d/msgid/kunit-dev/20231220151952.415232-2-benjamin%40sipsolutions.net.


Attachments:
smime.p7s (3.91 kB)
S/MIME Cryptographic Signature

2023-12-22 10:03:37

by David Gow

[permalink] [raw]
Subject: Re: [PATCH 2/6] kunit: add a convenience allocation wrapper for SKBs

On Wed, 20 Dec 2023 at 23:20, <[email protected]> wrote:
>
> From: Benjamin Berg <[email protected]>
>
> Add a simple convenience helper to allocate and zero fill an SKB for the
> use by a kunit test. Also provide a way to free it again in case that
> may be desirable.
>
> This simply mirrors the kunit_kmalloc API.
>
> Signed-off-by: Benjamin Berg <[email protected]>
> ---

I'm happy with this as-is, but do think there's a discussion to be had
about where subsystem-specific KUnit helpers should live. I think,
because this is just a header (and it mirrors the normal
linux/skbuff.h), that having it in include/kunit works well.

If it needed a source file, I'm not 100% sure whether it should be in
net/core/ or lib/kunit.

Regardless, this looks good to me, modulo the small nitpick below.

Reviewed-by: David Gow <[email protected]>

> include/kunit/skbuff.h | 56 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 56 insertions(+)
> create mode 100644 include/kunit/skbuff.h
>
> diff --git a/include/kunit/skbuff.h b/include/kunit/skbuff.h
> new file mode 100644
> index 000000000000..2144d01e556f
> --- /dev/null
> +++ b/include/kunit/skbuff.h
> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Base unit test (KUnit) API.

This probably needs a better description which mentions skbuff, and
that it's for resource management.


> + *
> + * Copyright (C) 2023 Intel Corporation
> + */
> +
> +#ifndef _KUNIT_SKBUFF_H
> +#define _KUNIT_SKBUFF_H
> +
> +#include <kunit/resource.h>
> +#include <linux/skbuff.h>
> +
> +static void kunit_action_kfree_skb(void *p)
> +{
> + kfree_skb((struct sk_buff *)p);
> +}
> +
> +/**
> + * kunit_zalloc_skb() - Allocate and initialize a resource managed skb.
> + * @test: The test case to which the skb belongs
> + * @len: size to allocate
> + *
> + * Allocate a new struct sk_buff with GFP_KERNEL, zero fill the give length
> + * and add it as a resource to the kunit test for automatic cleanup.
> + *
> + * Returns: newly allocated SKB, or %NULL on error
> + */
> +static inline struct sk_buff *kunit_zalloc_skb(struct kunit *test, int len,
> + gfp_t gfp)
> +{
> + struct sk_buff *res = alloc_skb(len, GFP_KERNEL);
> +
> + if (!res || skb_pad(res, len))
> + return NULL;
> +
> + if (kunit_add_action_or_reset(test, kunit_action_kfree_skb, res))
> + return NULL;
> +
> + return res;
> +}
> +
> +/**
> + * kunit_kfree_skb() - Like kfree_skb except for allocations managed by KUnit.
> + * @test: The test case to which the resource belongs.
> + * @skb: The SKB to free.
> + */
> +static inline void kunit_kfree_skb(struct kunit *test, struct sk_buff *skb)
> +{
> + if (!skb)
> + return;
> +
> + kunit_release_action(test, kunit_action_kfree_skb, (void *)skb);
> +}
> +
> +#endif /* _KUNIT_SKBUFF_H */
> --
> 2.43.0
>
> --
> You received this message because you are subscribed to the Google Groups "KUnit Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
> To view this discussion on the web visit https://groups.google.com/d/msgid/kunit-dev/20231220151952.415232-3-benjamin%40sipsolutions.net.


Attachments:
smime.p7s (3.91 kB)
S/MIME Cryptographic Signature

2023-12-22 10:04:20

by David Gow

[permalink] [raw]
Subject: Re: [PATCH 0/6] Add some more cfg80211 and mac80211 kunit tests

On Fri, 22 Dec 2023 at 05:47, Shuah Khan <[email protected]> wrote:
>
> On 12/21/23 13:40, Johannes Berg wrote:
> > On Thu, 2023-12-21 at 13:06 -0700, Shuah Khan wrote:
> >> On 12/21/23 12:39, Johannes Berg wrote:
> >>>>
> >>>> This patchset adds a couple of helpers for kunit as well as tests for
> >>>> cfg80211 and mac80211 that use them.
> >>>
> >>> I can take this through the wireless tree, but then I'd like to have
> >>> ACKs from kunit folks for the kunit patches:
> >>>
> >>
> >> We have run into conflicts in the past with the kunit tree. I take the
> >> kunit patches through linux-kselftest tree. I do want to make sure there
> >> are no conflicts. I don't mind taking these through my tree.
> >
> > OK, fair enough.
> >
> > If you can still put it into 6.8, then I think you can also take the
> > wireless tests, assuming they pass (I haven't run them in the posted
> > version). I don't think we'll have conflicts there, we don't have much
> > work in wireless that's likely to land for 6.8.
> >
>
> Sounds good.
>
> David, will you be able to look at these patches and let me know if
> I can apply for Linux 6.8-rc1.

The two initial KUnit patches look fine, modulo a couple of minor docs
issues and checkpatch warnings. They apply cleanly, and I doubt
there's much chance of there being a merge conflict for 6.8 -- there
are no other changes to the parameterised test macros, and the skb
stuff is in its own file.

The remaining patches don't apply on top of the kunit branch as-is. I
haven't had a chance to review them properly yet; the initial glance I
had didn't show any serious issues (though I think checkpatch
suggested some things to 'check').

So (once those small issues are finished), I'm okay with the first two
patches going in via either tree. The remaining ones are probably best
done via the wireless tree, as they seem to depend on some existing
patches there, so maybe it makes sense to push everything via
wireless.

Cheers,
-- David


Attachments:
smime.p7s (3.91 kB)
S/MIME Cryptographic Signature

2023-12-22 10:09:26

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/6] Add some more cfg80211 and mac80211 kunit tests

Hi,

Thanks for taking a look!

On Fri, 2023-12-22 at 18:02 +0800, David Gow wrote:
> The two initial KUnit patches look fine, modulo a couple of minor docs
> issues and checkpatch warnings. 

I can run checkpatch (even if I can't always take it seriously), but do
you want to comment more specifically wrt. the docs?

> They apply cleanly, and I doubt
> there's much chance of there being a merge conflict for 6.8 -- there
> are no other changes to the parameterised test macros, and the skb
> stuff is in its own file.

Right.

> The remaining patches don't apply on top of the kunit branch as-is.

Oh, OK. That makes some sense though, we've had a number of changes in
the stack this cycle before. I somehow thought the tests were likely
standalone, but apparently not.

> I
> haven't had a chance to review them properly yet; the initial glance I
> had didn't show any serious issues (though I think checkpatch
> suggested some things to 'check').

I can check.

> So (once those small issues are finished), I'm okay with the first two
> patches going in via either tree. The remaining ones are probably best
> done via the wireless tree, as they seem to depend on some existing
> patches there, so maybe it makes sense to push everything via
> wireless.

If not through wireless I doubt we'll get it synchronized for 6.8,
though of course it's also not needed for 6.8 to have the extra unit
tests :)

I'll let Shuah decide.

Thanks!

johannes

2023-12-22 14:13:08

by David Gow

[permalink] [raw]
Subject: Re: [PATCH 0/6] Add some more cfg80211 and mac80211 kunit tests

On Fri, 22 Dec 2023 at 18:09, Johannes Berg <[email protected]> wrote:
>
> Hi,
>
> Thanks for taking a look!
>
> On Fri, 2023-12-22 at 18:02 +0800, David Gow wrote:
> > The two initial KUnit patches look fine, modulo a couple of minor docs
> > issues and checkpatch warnings.
>
> I can run checkpatch (even if I can't always take it seriously), but do
> you want to comment more specifically wrt. the docs?
>

Sorry, the 'docs' issue was just the initial comment on the
include/linux/skbuff.h file in patch 2, which could have been more
specific to skbuff and resource management.
The actual kerneldoc comments seem fine to me.



> > They apply cleanly, and I doubt
> > there's much chance of there being a merge conflict for 6.8 -- there
> > are no other changes to the parameterised test macros, and the skb
> > stuff is in its own file.
>
> Right.
>
> > The remaining patches don't apply on top of the kunit branch as-is.
>
> Oh, OK. That makes some sense though, we've had a number of changes in
> the stack this cycle before. I somehow thought the tests were likely
> standalone, but apparently not.
>

I managed to get this to apply locally. The only real changes are to
net/mac80211/ieee80211_i.h so it may be possible to port this across
to the kselftest/kunit branch if you want, but it doesn't apply
cleanly as-is.

Also, there are a couple of cfg80211 failures:
---
KTAP version 1
1..1
KTAP version 1
# Subtest: cfg80211-inform-bss
# module: cfg80211_tests
1..2
platform regulatory.0: Direct firmware load for regulatory.db failed
with error -2
cfg80211: failed to load regulatory.db
ok 1 test_inform_bss_ssid_only
KTAP version 1
# Subtest: test_inform_bss_ml_sta
# test_inform_bss_ml_sta: EXPECTATION FAILED at net/wireless/tests/scan.c:592
Expected ies->len == 6 + 2 + sizeof(rnr) + 2 + 155 +
mle_basic_common_info.var_len + 5, but
ies->len == 185 (0xb9)
6 + 2 + sizeof(rnr) + 2 + 155 + mle_basic_common_info.var_len +
5 == 203 (0xcb)
not ok 1 no_mld_id
# test_inform_bss_ml_sta: EXPECTATION FAILED at net/wireless/tests/scan.c:588
Expected ies->len == 6 + 2 + sizeof(rnr) + 2 + 160 + 2 + 165 +
mle_basic_common_info.var_len + 5, but
ies->len == 357 (0x165)
6 + 2 + sizeof(rnr) + 2 + 160 + 2 + 165 +
mle_basic_common_info.var_len + 5 == 376 (0x178)
not ok 2 mld_id_eq_1
# test_inform_bss_ml_sta: pass:0 fail:2 skip:0 total:2
not ok 2 test_inform_bss_ml_sta
# cfg80211-inform-bss: pass:1 fail:1 skip:0 total:2
# Totals: pass:1 fail:2 skip:0 total:3
not ok 1 cfg80211-inform-bss
---

If the failures are because of the missing 'regulatory.db' file, would
it make more sense to have that SKIP the tests instead? (And, if you
actually want to check that it loads correctly, have that be its own,
separate test?)

> > I
> > haven't had a chance to review them properly yet; the initial glance I
> > had didn't show any serious issues (though I think checkpatch
> > suggested some things to 'check').
>
> I can check.

Yeah, it mostly looks like really minor style 'suggestions' around
indenting and putting blank lines in, along with a couple of "you're
reusing a value in a macro, double check this" ones.. I'll paste them
below (but warning, they're a bit verbose).

CHECK: Please use a blank line after function/struct/union/enum declarations
#1142: FILE: net/wireless/tests/scan.c:225:
+};
+KUNIT_ARRAY_PARAM_DESC(gen_new_ie, gen_new_ie_cases, desc)

CHECK: Please use a blank line after function/struct/union/enum declarations
#1330: FILE: net/wireless/tests/scan.c:413:
+};
+KUNIT_ARRAY_PARAM_DESC(inform_bss_ml_sta, inform_bss_ml_sta_cases, desc)

CHECK: Alignment should match open parenthesis
#1489: FILE: net/wireless/tests/scan.c:572:
+ KUNIT_EXPECT_EQ(test, link_bss->beacon_interval,
+ le16_to_cpu(sta_prof.beacon_int));

CHECK: Alignment should match open parenthesis
#1491: FILE: net/wireless/tests/scan.c:574:
+ KUNIT_EXPECT_EQ(test, link_bss->capability,
+ le16_to_cpu(sta_prof.capabilities));

CHECK: Macro argument reuse '_freq' - possible side-effects?
#1620: FILE: net/wireless/tests/util.h:10:
+#define CHAN2G(_freq) { \
+ .band = NL80211_BAND_2GHZ, \
+ .center_freq = (_freq), \
+ .hw_value = (_freq), \
+}

CHECK: Macro argument reuse 'test' - possible side-effects?
#1653: FILE: net/wireless/tests/util.h:43:
+#define T_WIPHY(test, ctx) ({ \
+ struct wiphy *__wiphy = \
+ kunit_alloc_resource(test, t_wiphy_init, \
+ t_wiphy_exit, \
+ GFP_KERNEL, &(ctx)); \
+ \
+ KUNIT_ASSERT_NOT_NULL(test, __wiphy); \
+ __wiphy; \
+ })




>
> > So (once those small issues are finished), I'm okay with the first two
> > patches going in via either tree. The remaining ones are probably best
> > done via the wireless tree, as they seem to depend on some existing
> > patches there, so maybe it makes sense to push everything via
> > wireless.
>
> If not through wireless I doubt we'll get it synchronized for 6.8,
> though of course it's also not needed for 6.8 to have the extra unit
> tests :)
>
> I'll let Shuah decide.
>

I think you should be able to rebase on top of the kunit tree if Shuah
prefers that -- it's a reasonably straightforward conflict. But I
think we'd want to make sure that the various issues above are fixed
(and I'd not want the tests to fail out-of-the-box on the kunit.py UML
setup, though having them depend on !UML or 'SKIP' should be fine).

Cheers,
-- David


Attachments:
smime.p7s (3.91 kB)
S/MIME Cryptographic Signature

2023-12-22 15:15:14

by Benjamin Berg

[permalink] [raw]
Subject: Re: [PATCH 1/6] kunit: add parameter generation macro using description from array

On Fri, 2023-12-22 at 18:02 +0800, David Gow wrote:
> On Wed, 20 Dec 2023 at 23:20, <[email protected]> wrote:
> >
> > From: Benjamin Berg <[email protected]>
> >
> > The existing KUNIT_ARRAY_PARAM macro requires a separate function
> > to
> > get the description. However, in a lot of cases the description can
> > just be copied directly from the array. Add a second macro that
> > avoids having to write a static function just for a single strscpy.
> >
> > Signed-off-by: Benjamin Berg <[email protected]>
> > ---
>
> I'm generally pretty happy with this, though note the checkpatch
> warning below.
>
> There was some discussion at plumbers about expanding the
> parameterised test APIs, so we may need to adjust the implementation
> of this down the line, but I don't think that'll happen for a while,
> so don't worry.
>
> With the warnings fixed, this is:

I think the checkpatch warning is a false positive. It seems to confuse
the * as a multiplication due to typeof() looking like a function call
rather than a variable declaration.

Benjamin

> Reviewed-by: David Gow <[email protected]>
>
> I'm okay with this going in via the wireless tree if that's easier;
> certainly there are some conflicts with the later patches in this
> series and the kunit one.
>
> Cheers,
> -- David
>
> >  Documentation/dev-tools/kunit/usage.rst | 12 ++++--------
> >  include/kunit/test.h                    | 19 +++++++++++++++++++
> >  2 files changed, 23 insertions(+), 8 deletions(-)
> >
> > diff --git a/Documentation/dev-tools/kunit/usage.rst
> > b/Documentation/dev-tools/kunit/usage.rst
> > index c27e1646ecd9..b959e5befcbe 100644
> > --- a/Documentation/dev-tools/kunit/usage.rst
> > +++ b/Documentation/dev-tools/kunit/usage.rst
> > @@ -566,13 +566,9 @@ By reusing the same ``cases`` array from
> > above, we can write the test as a
> >                 },
> >         };
> >
> > -       // Need a helper function to generate a name for each test
> > case.
> > -       static void case_to_desc(const struct sha1_test_case *t,
> > char *desc)
> > -       {
> > -               strcpy(desc, t->str);
> > -       }
> > -       // Creates `sha1_gen_params()` to iterate over `cases`.
> > -       KUNIT_ARRAY_PARAM(sha1, cases, case_to_desc);
> > +       // Creates `sha1_gen_params()` to iterate over `cases`
> > while using
> > +       // the struct member `str` for the case description.
> > +       KUNIT_ARRAY_PARAM_DESC(sha1, cases, str);
> >
> >         // Looks no different from a normal test.
> >         static void sha1_test(struct kunit *test)
> > @@ -588,7 +584,7 @@ By reusing the same ``cases`` array from above,
> > we can write the test as a
> >         }
> >
> >         // Instead of KUNIT_CASE, we use KUNIT_CASE_PARAM and pass
> > in the
> > -       // function declared by KUNIT_ARRAY_PARAM.
> > +       // function declared by KUNIT_ARRAY_PARAM or
> > KUNIT_ARRAY_PARAM_DESC.
> >         static struct kunit_case sha1_test_cases[] = {
> >                 KUNIT_CASE_PARAM(sha1_test, sha1_gen_params),
> >                 {}
> > diff --git a/include/kunit/test.h b/include/kunit/test.h
> > index 20ed9f9275c9..2dfa851e1f88 100644
> > --- a/include/kunit/test.h
> > +++ b/include/kunit/test.h
> > @@ -1514,6 +1514,25 @@ do
> > {                                                                  
> >           \
> >                 return
> > NULL;                                                              
> >       \
> >         }
> >
> > +/**
> > + * KUNIT_ARRAY_PARAM_DESC() - Define test parameter generator from
> > an array.
> > + * @name:  prefix for the test parameter generator function.
> > + * @array: array of test parameters.
> > + * @desc_member: structure member from array element to use as
> > description
> > + *
> > + * Define function @name_gen_params which uses @array to generate
> > parameters.
> > + */
> > +#define KUNIT_ARRAY_PARAM_DESC(name, array,
> > desc_member)                                       \
> > +       static const void *name##_gen_params(const void *prev, char
> > *desc)                      \
> > +      
> > {                                                                  
> >                      \
> > +               typeof((array)[0]) *__next = prev ?
> > ((typeof(__next)) prev) + 1 : (array);      \
>
> checkpatch is complaining here:
> ERROR: need consistent spacing around '*' (ctx:WxV)
> #71: FILE: include/kunit/test.h:1528:
>
> +               typeof((array)[0]) *__next = prev ? ((typeof(__next))
> prev) + 1 : (array);      \
>
> > +               if (__next - (array) < ARRAY_SIZE((array)))
> > {                                   \
> > +                       strscpy(desc, __next->desc_member,
> > KUNIT_PARAM_DESC_SIZE);              \
> > +                       return
> > __next;                                                          \
> > +              
> > }                                                                  
> >              \
> > +               return
> > NULL;                                                              
> >       \
> > +       }
> > +
> >  // TODO([email protected]): consider eventually migrating users
> > to explicitly
> >  // include resource.h themselves if they need it.
> >  #include <kunit/resource.h>
> > --
> > 2.43.0
> >
> > --
> > You received this message because you are subscribed to the Google
> > Groups "KUnit Development" group.
> > To unsubscribe from this group and stop receiving emails from it,
> > send an email to [email protected].
> > To view this discussion on the web visit
> > https://groups.google.com/d/msgid/kunit-dev/20231220151952.415232-2-benjamin%40sipsolutions.net
> > .

2023-12-22 15:45:02

by Shuah Khan

[permalink] [raw]
Subject: Re: [PATCH 0/6] Add some more cfg80211 and mac80211 kunit tests

On 12/22/23 03:09, Johannes Berg wrote:
> Hi,
>
> Thanks for taking a look!
>
> On Fri, 2023-12-22 at 18:02 +0800, David Gow wrote:
>> The two initial KUnit patches look fine, modulo a couple of minor docs
>> issues and checkpatch warnings.
>
> I can run checkpatch (even if I can't always take it seriously), but do
> you want to comment more specifically wrt. the docs?
>
>> They apply cleanly, and I doubt
>> there's much chance of there being a merge conflict for 6.8 -- there
>> are no other changes to the parameterised test macros, and the skb
>> stuff is in its own file.
>
> Right.
>
>> The remaining patches don't apply on top of the kunit branch as-is.
>
> Oh, OK. That makes some sense though, we've had a number of changes in
> the stack this cycle before. I somehow thought the tests were likely
> standalone, but apparently not.
>
>> I
>> haven't had a chance to review them properly yet; the initial glance I
>> had didn't show any serious issues (though I think checkpatch
>> suggested some things to 'check').
>
> I can check.
>
>> So (once those small issues are finished), I'm okay with the first two
>> patches going in via either tree. The remaining ones are probably best
>> done via the wireless tree, as they seem to depend on some existing
>> patches there, so maybe it makes sense to push everything via
>> wireless.
>
> If not through wireless I doubt we'll get it synchronized for 6.8,
> though of course it's also not needed for 6.8 to have the extra unit
> tests :)
>
> I'll let Shuah decide.
>


Thank you David for the reviews.


johannes, Please take these through wireless - makes it easier for all
of us.

Acked-by: Shuah Khan <[email protected]>

thanks,
-- Shuah


2023-12-23 05:09:22

by David Gow

[permalink] [raw]
Subject: Re: [PATCH 1/6] kunit: add parameter generation macro using description from array

On Fri, 22 Dec 2023 at 23:09, Benjamin Berg <[email protected]> wrote:
>
> On Fri, 2023-12-22 at 18:02 +0800, David Gow wrote:
> > On Wed, 20 Dec 2023 at 23:20, <[email protected]> wrote:
> > >
> > > From: Benjamin Berg <[email protected]>
> > >
> > > The existing KUNIT_ARRAY_PARAM macro requires a separate function
> > > to
> > > get the description. However, in a lot of cases the description can
> > > just be copied directly from the array. Add a second macro that
> > > avoids having to write a static function just for a single strscpy.
> > >
> > > Signed-off-by: Benjamin Berg <[email protected]>
> > > ---
> >
> > I'm generally pretty happy with this, though note the checkpatch
> > warning below.
> >
> > There was some discussion at plumbers about expanding the
> > parameterised test APIs, so we may need to adjust the implementation
> > of this down the line, but I don't think that'll happen for a while,
> > so don't worry.
> >
> > With the warnings fixed, this is:
>
> I think the checkpatch warning is a false positive. It seems to confuse
> the * as a multiplication due to typeof() looking like a function call
> rather than a variable declaration.
>
> Benjamin
>

Ah, yeah: this appears to be due to checkpatch not handling nested ()
within a typeof().

Reviewed-by: David Gow <[email protected]>

Cheers,
-- David


Attachments:
smime.p7s (3.91 kB)
S/MIME Cryptographic Signature