linux-kselftest.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/5] MCTP kunit tests
@ 2021-10-01  8:18 Jeremy Kerr
  2021-10-01  8:18 ` [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test Jeremy Kerr
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Jeremy Kerr @ 2021-10-01  8:18 UTC (permalink / raw)
  To: netdev
  Cc: Matt Johnston, David S. Miller, Jakub Kicinski, Brendan Higgins,
	linux-kselftest

This change adds some initial kunit tests for the MCTP core. We'll
expand the coverage in a future series, and augment with a few
selftests, but this establishes a baseline set of tests for now.

Thanks to the kunit folks for the framework!

Cheers,


Jeremy

---

Jeremy Kerr (5):
  mctp: Add initial test structure and fragmentation test
  mctp: Add test utils
  mctp: Add packet rx tests
  mctp: Add route input to socket tests
  mctp: Add input reassembly tests

 net/mctp/Kconfig           |   5 +
 net/mctp/Makefile          |   3 +
 net/mctp/route.c           |   5 +
 net/mctp/test/route-test.c | 532 +++++++++++++++++++++++++++++++++++++
 net/mctp/test/utils.c      |  67 +++++
 net/mctp/test/utils.h      |  20 ++
 6 files changed, 632 insertions(+)
 create mode 100644 net/mctp/test/route-test.c
 create mode 100644 net/mctp/test/utils.c
 create mode 100644 net/mctp/test/utils.h

-- 
2.33.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test
  2021-10-01  8:18 [PATCH net-next 0/5] MCTP kunit tests Jeremy Kerr
@ 2021-10-01  8:18 ` Jeremy Kerr
  2021-10-01 19:16   ` kernel test robot
                     ` (2 more replies)
  2021-10-01  8:18 ` [PATCH net-next 2/5] mctp: Add test utils Jeremy Kerr
                   ` (4 subsequent siblings)
  5 siblings, 3 replies; 11+ messages in thread
From: Jeremy Kerr @ 2021-10-01  8:18 UTC (permalink / raw)
  To: netdev
  Cc: Matt Johnston, David S. Miller, Jakub Kicinski, Brendan Higgins,
	linux-kselftest

This change adds the first kunit test for the mctp subsystem, and an
initial test for the fragmentation path.

We're adding tests under a new net/mctp/test/ directory.

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 net/mctp/Kconfig           |   5 +
 net/mctp/route.c           |   5 +
 net/mctp/test/route-test.c | 206 +++++++++++++++++++++++++++++++++++++
 3 files changed, 216 insertions(+)
 create mode 100644 net/mctp/test/route-test.c

diff --git a/net/mctp/Kconfig b/net/mctp/Kconfig
index 2cdf3d0a28c9..15267a5043d9 100644
--- a/net/mctp/Kconfig
+++ b/net/mctp/Kconfig
@@ -11,3 +11,8 @@ menuconfig MCTP
 	  This option enables core MCTP support. For communicating with other
 	  devices, you'll want to enable a driver for a specific hardware
 	  channel.
+
+config MCTP_TEST
+        tristate "MCTP core tests" if !KUNIT_ALL_TESTS
+        depends on MCTP && KUNIT
+        default KUNIT_ALL_TESTS
diff --git a/net/mctp/route.c b/net/mctp/route.c
index 9bea232cf250..b7e4e6281806 100644
--- a/net/mctp/route.c
+++ b/net/mctp/route.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/idr.h>
+#include <linux/kconfig.h>
 #include <linux/mctp.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
@@ -1275,3 +1276,7 @@ void __exit mctp_routes_exit(void)
 	rtnl_unregister(PF_MCTP, RTM_GETROUTE);
 	dev_remove_pack(&mctp_packet_type);
 }
+
+#if IS_ENABLED(CONFIG_MCTP_TEST)
+#include "test/route-test.c"
+#endif
diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
new file mode 100644
index 000000000000..cf3b51183613
--- /dev/null
+++ b/net/mctp/test/route-test.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <kunit/test.h>
+
+struct mctp_test_route {
+	struct mctp_route	rt;
+	struct sk_buff_head	pkts;
+};
+
+static int mctp_test_route_output(struct mctp_route *rt, struct sk_buff *skb)
+{
+	struct mctp_test_route *test_rt = container_of(rt, struct mctp_test_route, rt);
+
+	skb_queue_tail(&test_rt->pkts, skb);
+
+	return 0;
+}
+
+/* local version of mctp_route_alloc() */
+static struct mctp_test_route *mctp_route_test_alloc(void)
+{
+	struct mctp_test_route *rt;
+
+	rt = kzalloc(sizeof(*rt), GFP_KERNEL);
+	if (!rt)
+		return NULL;
+
+	INIT_LIST_HEAD(&rt->rt.list);
+	refcount_set(&rt->rt.refs, 1);
+	rt->rt.output = mctp_test_route_output;
+
+	skb_queue_head_init(&rt->pkts);
+
+	return rt;
+}
+
+static struct mctp_test_route *mctp_test_create_route(struct net *net,
+						      mctp_eid_t eid,
+						      unsigned int mtu)
+{
+	struct mctp_test_route *rt;
+
+	rt = mctp_route_test_alloc();
+	if (!rt)
+		return NULL;
+
+	rt->rt.min = eid;
+	rt->rt.max = eid;
+	rt->rt.mtu = mtu;
+	rt->rt.type = RTN_UNSPEC;
+	rt->rt.dev = NULL; /* somewhat illegal, but fine for current tests */
+
+	list_add_rcu(&rt->rt.list, &net->mctp.routes);
+
+	return rt;
+}
+
+static void mctp_test_route_destroy(struct mctp_test_route *rt)
+{
+	rtnl_lock();
+	list_del_rcu(&rt->rt.list);
+	rtnl_unlock();
+
+	skb_queue_purge(&rt->pkts);
+
+	kfree_rcu(&rt->rt, rcu);
+}
+
+static struct sk_buff *mctp_test_create_skb(struct mctp_hdr *hdr,
+					    unsigned int data_len)
+{
+	size_t hdr_len = sizeof(*hdr);
+	struct sk_buff *skb;
+	unsigned int i;
+	u8 *buf;
+
+	skb = alloc_skb(hdr_len + data_len, GFP_KERNEL);
+	if (!skb)
+		return NULL;
+
+	memcpy(skb_put(skb, hdr_len), hdr, hdr_len);
+
+	buf = skb_put(skb, data_len);
+	for (i = 0; i < data_len; i++)
+		buf[i] = i & 0xff;
+
+	return skb;
+}
+
+struct mctp_frag_test {
+	unsigned int mtu;
+	unsigned int msgsize;
+	unsigned int n_frags;
+};
+
+static void mctp_test_fragment(struct kunit *test)
+{
+	const struct mctp_frag_test *params;
+	int rc, i, n, mtu, msgsize;
+	struct mctp_test_route *rt;
+	struct sk_buff *skb;
+	struct mctp_hdr hdr;
+	u8 seq;
+
+	params = test->param_value;
+	mtu = params->mtu;
+	msgsize = params->msgsize;
+
+	hdr.ver = 1;
+	hdr.src = 8;
+	hdr.dest = 10;
+	hdr.flags_seq_tag = MCTP_HDR_FLAG_TO;
+
+	skb = mctp_test_create_skb(&hdr, msgsize);
+	KUNIT_ASSERT_TRUE(test, skb);
+
+	rt = mctp_test_create_route(&init_net, 10, mtu);
+	KUNIT_ASSERT_TRUE(test, rt);
+
+	rc = mctp_do_fragment_route(&rt->rt, skb, mtu, MCTP_TAG_OWNER);
+	KUNIT_EXPECT_FALSE(test, rc);
+
+	n = rt->pkts.qlen;
+
+	KUNIT_EXPECT_EQ(test, n, params->n_frags);
+
+	for (i = 0;; i++) {
+		struct mctp_hdr *hdr2;
+		struct sk_buff *skb2;
+		u8 tag_mask, seq2;
+		bool first, last;
+
+		first = i == 0;
+		last = i == (n - 1);
+
+		skb2 = skb_dequeue(&rt->pkts);
+
+		if (!skb2)
+			break;
+
+		hdr2 = mctp_hdr(skb2);
+
+		tag_mask = MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO;
+
+		KUNIT_EXPECT_EQ(test, hdr2->ver, hdr.ver);
+		KUNIT_EXPECT_EQ(test, hdr2->src, hdr.src);
+		KUNIT_EXPECT_EQ(test, hdr2->dest, hdr.dest);
+		KUNIT_EXPECT_EQ(test, hdr2->flags_seq_tag & tag_mask,
+				hdr.flags_seq_tag & tag_mask);
+
+		KUNIT_EXPECT_EQ(test,
+				!!(hdr2->flags_seq_tag & MCTP_HDR_FLAG_SOM), first);
+		KUNIT_EXPECT_EQ(test,
+				!!(hdr2->flags_seq_tag & MCTP_HDR_FLAG_EOM), last);
+
+		seq2 = (hdr2->flags_seq_tag >> MCTP_HDR_SEQ_SHIFT) &
+			MCTP_HDR_SEQ_MASK;
+
+		if (first) {
+			seq = seq2;
+		} else {
+			seq++;
+			KUNIT_EXPECT_EQ(test, seq2, seq & MCTP_HDR_SEQ_MASK);
+		}
+
+		if (!last)
+			KUNIT_EXPECT_EQ(test, skb2->len, mtu);
+		else
+			KUNIT_EXPECT_LE(test, skb2->len, mtu);
+
+		kfree_skb(skb2);
+	}
+
+	mctp_test_route_destroy(rt);
+}
+
+static const struct mctp_frag_test mctp_frag_tests[] = {
+	{.mtu = 68, .msgsize = 63, .n_frags = 1},
+	{.mtu = 68, .msgsize = 64, .n_frags = 1},
+	{.mtu = 68, .msgsize = 65, .n_frags = 2},
+	{.mtu = 68, .msgsize = 66, .n_frags = 2},
+	{.mtu = 68, .msgsize = 127, .n_frags = 2},
+	{.mtu = 68, .msgsize = 128, .n_frags = 2},
+	{.mtu = 68, .msgsize = 129, .n_frags = 3},
+	{.mtu = 68, .msgsize = 130, .n_frags = 3},
+};
+
+static void mctp_frag_test_to_desc(const struct mctp_frag_test *t, char *desc)
+{
+	sprintf(desc, "mtu %d len %d -> %d frags",
+		t->msgsize, t->mtu, t->n_frags);
+}
+
+KUNIT_ARRAY_PARAM(mctp_frag, mctp_frag_tests, mctp_frag_test_to_desc);
+
+static struct kunit_case mctp_test_cases[] = {
+	KUNIT_CASE_PARAM(mctp_test_fragment, mctp_frag_gen_params),
+	{}
+};
+
+static struct kunit_suite mctp_test_suite = {
+	.name = "mctp",
+	.test_cases = mctp_test_cases,
+};
+
+kunit_test_suite(mctp_test_suite);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next 2/5] mctp: Add test utils
  2021-10-01  8:18 [PATCH net-next 0/5] MCTP kunit tests Jeremy Kerr
  2021-10-01  8:18 ` [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test Jeremy Kerr
@ 2021-10-01  8:18 ` Jeremy Kerr
  2021-10-01  8:18 ` [PATCH net-next 3/5] mctp: Add packet rx tests Jeremy Kerr
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Jeremy Kerr @ 2021-10-01  8:18 UTC (permalink / raw)
  To: netdev
  Cc: Matt Johnston, David S. Miller, Jakub Kicinski, Brendan Higgins,
	linux-kselftest

Add a new object for shared test utilities

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 net/mctp/Makefile     |  3 ++
 net/mctp/test/utils.c | 67 +++++++++++++++++++++++++++++++++++++++++++
 net/mctp/test/utils.h | 20 +++++++++++++
 3 files changed, 90 insertions(+)
 create mode 100644 net/mctp/test/utils.c
 create mode 100644 net/mctp/test/utils.h

diff --git a/net/mctp/Makefile b/net/mctp/Makefile
index 0171333384d7..6cd55233e685 100644
--- a/net/mctp/Makefile
+++ b/net/mctp/Makefile
@@ -1,3 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_MCTP) += mctp.o
 mctp-objs := af_mctp.o device.o route.o neigh.o
+
+# tests
+obj-$(CONFIG_MCTP_TEST) += test/utils.o
diff --git a/net/mctp/test/utils.c b/net/mctp/test/utils.c
new file mode 100644
index 000000000000..e2ab1f3da357
--- /dev/null
+++ b/net/mctp/test/utils.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/netdevice.h>
+#include <linux/mctp.h>
+#include <linux/if_arp.h>
+
+#include <net/mctpdevice.h>
+#include <net/pkt_sched.h>
+
+#include "utils.h"
+
+static netdev_tx_t mctp_test_dev_tx(struct sk_buff *skb,
+				    struct net_device *ndev)
+{
+	kfree(skb);
+	return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops mctp_test_netdev_ops = {
+	.ndo_start_xmit = mctp_test_dev_tx,
+};
+
+static void mctp_test_dev_setup(struct net_device *ndev)
+{
+	ndev->type = ARPHRD_MCTP;
+	ndev->mtu = MCTP_DEV_TEST_MTU;
+	ndev->hard_header_len = 0;
+	ndev->addr_len = 0;
+	ndev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
+	ndev->flags = IFF_NOARP;
+	ndev->netdev_ops = &mctp_test_netdev_ops;
+	ndev->needs_free_netdev = true;
+}
+
+struct mctp_test_dev *mctp_test_create_dev(void)
+{
+	struct mctp_test_dev *dev;
+	struct net_device *ndev;
+	int rc;
+
+	ndev = alloc_netdev(sizeof(*dev), "mctptest%d", NET_NAME_ENUM,
+			    mctp_test_dev_setup);
+	if (!ndev)
+		return NULL;
+
+	dev = netdev_priv(ndev);
+	dev->ndev = ndev;
+
+	rcu_read_lock();
+	dev->mdev = __mctp_dev_get(ndev);
+	mctp_dev_hold(dev->mdev);
+	rcu_read_unlock();
+
+	rc = register_netdev(ndev);
+	if (rc) {
+		free_netdev(ndev);
+		return NULL;
+	}
+
+	return dev;
+}
+
+void mctp_test_destroy_dev(struct mctp_test_dev *dev)
+{
+	mctp_dev_put(dev->mdev);
+	unregister_netdev(dev->ndev);
+}
diff --git a/net/mctp/test/utils.h b/net/mctp/test/utils.h
new file mode 100644
index 000000000000..df6aa1c03440
--- /dev/null
+++ b/net/mctp/test/utils.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __NET_MCTP_TEST_UTILS_H
+#define __NET_MCTP_TEST_UTILS_H
+
+#include <kunit/test.h>
+
+#define MCTP_DEV_TEST_MTU	68
+
+struct mctp_test_dev {
+	struct net_device *ndev;
+	struct mctp_dev *mdev;
+};
+
+struct mctp_test_dev;
+
+struct mctp_test_dev *mctp_test_create_dev(void);
+void mctp_test_destroy_dev(struct mctp_test_dev *dev);
+
+#endif /* __NET_MCTP_TEST_UTILS_H */
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next 3/5] mctp: Add packet rx tests
  2021-10-01  8:18 [PATCH net-next 0/5] MCTP kunit tests Jeremy Kerr
  2021-10-01  8:18 ` [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test Jeremy Kerr
  2021-10-01  8:18 ` [PATCH net-next 2/5] mctp: Add test utils Jeremy Kerr
@ 2021-10-01  8:18 ` Jeremy Kerr
  2021-10-02  0:39   ` kernel test robot
  2021-10-01  8:18 ` [PATCH net-next 4/5] mctp: Add route input to socket tests Jeremy Kerr
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Jeremy Kerr @ 2021-10-01  8:18 UTC (permalink / raw)
  To: netdev
  Cc: Matt Johnston, David S. Miller, Jakub Kicinski, Brendan Higgins,
	linux-kselftest

Add a few tests for the initial packet ingress through
mctp_pkttype_receive function; mainly packet header sanity checks. Full
input routing checks will be added as a separate change.

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 net/mctp/test/route-test.c | 67 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 3 deletions(-)

diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
index cf3b51183613..ee0422bf24ce 100644
--- a/net/mctp/test/route-test.c
+++ b/net/mctp/test/route-test.c
@@ -2,6 +2,8 @@
 
 #include <kunit/test.h>
 
+#include "utils.h"
+
 struct mctp_test_route {
 	struct mctp_route	rt;
 	struct sk_buff_head	pkts;
@@ -35,6 +37,7 @@ static struct mctp_test_route *mctp_route_test_alloc(void)
 }
 
 static struct mctp_test_route *mctp_test_create_route(struct net *net,
+						      struct mctp_dev *dev,
 						      mctp_eid_t eid,
 						      unsigned int mtu)
 {
@@ -48,7 +51,9 @@ static struct mctp_test_route *mctp_test_create_route(struct net *net,
 	rt->rt.max = eid;
 	rt->rt.mtu = mtu;
 	rt->rt.type = RTN_UNSPEC;
-	rt->rt.dev = NULL; /* somewhat illegal, but fine for current tests */
+	if (dev)
+		mctp_dev_hold(dev);
+	rt->rt.dev = dev;
 
 	list_add_rcu(&rt->rt.list, &net->mctp.routes);
 
@@ -62,11 +67,13 @@ static void mctp_test_route_destroy(struct mctp_test_route *rt)
 	rtnl_unlock();
 
 	skb_queue_purge(&rt->pkts);
+	if (rt->rt.dev)
+		mctp_dev_put(rt->rt.dev);
 
 	kfree_rcu(&rt->rt, rcu);
 }
 
-static struct sk_buff *mctp_test_create_skb(struct mctp_hdr *hdr,
+static struct sk_buff *mctp_test_create_skb(const struct mctp_hdr *hdr,
 					    unsigned int data_len)
 {
 	size_t hdr_len = sizeof(*hdr);
@@ -114,7 +121,7 @@ static void mctp_test_fragment(struct kunit *test)
 	skb = mctp_test_create_skb(&hdr, msgsize);
 	KUNIT_ASSERT_TRUE(test, skb);
 
-	rt = mctp_test_create_route(&init_net, 10, mtu);
+	rt = mctp_test_create_route(&init_net, NULL, 10, mtu);
 	KUNIT_ASSERT_TRUE(test, rt);
 
 	rc = mctp_do_fragment_route(&rt->rt, skb, mtu, MCTP_TAG_OWNER);
@@ -193,8 +200,62 @@ static void mctp_frag_test_to_desc(const struct mctp_frag_test *t, char *desc)
 
 KUNIT_ARRAY_PARAM(mctp_frag, mctp_frag_tests, mctp_frag_test_to_desc);
 
+struct mctp_rx_input_test {
+	struct mctp_hdr hdr;
+	bool input;
+};
+
+static void mctp_test_rx_input(struct kunit *test)
+{
+	const struct mctp_rx_input_test *params;
+	struct mctp_test_route *rt;
+	struct mctp_test_dev *dev;
+	struct sk_buff *skb;
+
+	params = test->param_value;
+
+	dev = mctp_test_create_dev();
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+	rt = mctp_test_create_route(&init_net, dev->mdev, 8, 68);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rt);
+
+	skb = mctp_test_create_skb(&params->hdr, 1);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb);
+
+	__mctp_cb(skb);
+
+	mctp_pkttype_receive(skb, dev->ndev, &mctp_packet_type, NULL);
+
+	KUNIT_EXPECT_EQ(test, !!rt->pkts.qlen, params->input);
+
+	mctp_test_route_destroy(rt);
+	mctp_test_destroy_dev(dev);
+}
+
+#define RX_HDR(_ver, _src, _dest, _fst) \
+	{ .ver = _ver, .src = _src, .dest = _dest, .flags_seq_tag = _fst }
+
+/* we have a route for EID 8 only */
+static const struct mctp_rx_input_test mctp_rx_input_tests[] = {
+	{ .hdr = RX_HDR(1, 10, 8, 0), .input = true },
+	{ .hdr = RX_HDR(1, 10, 9, 0), .input = false }, /* no input route */
+	{ .hdr = RX_HDR(2, 10, 8, 0), .input = false }, /* invalid version */
+};
+
+static void mctp_rx_input_test_to_desc(const struct mctp_rx_input_test *t,
+				       char *desc)
+{
+	sprintf(desc, "{%x,%x,%x,%x}", t->hdr.ver, t->hdr.src, t->hdr.dest,
+		t->hdr.flags_seq_tag);
+}
+
+KUNIT_ARRAY_PARAM(mctp_rx_input, mctp_rx_input_tests,
+		  mctp_rx_input_test_to_desc);
+
 static struct kunit_case mctp_test_cases[] = {
 	KUNIT_CASE_PARAM(mctp_test_fragment, mctp_frag_gen_params),
+	KUNIT_CASE_PARAM(mctp_test_rx_input, mctp_rx_input_gen_params),
 	{}
 };
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next 4/5] mctp: Add route input to socket tests
  2021-10-01  8:18 [PATCH net-next 0/5] MCTP kunit tests Jeremy Kerr
                   ` (2 preceding siblings ...)
  2021-10-01  8:18 ` [PATCH net-next 3/5] mctp: Add packet rx tests Jeremy Kerr
@ 2021-10-01  8:18 ` Jeremy Kerr
  2021-10-01  8:18 ` [PATCH net-next 5/5] mctp: Add input reassembly tests Jeremy Kerr
  2021-10-01 13:20 ` [PATCH net-next 0/5] MCTP kunit tests patchwork-bot+netdevbpf
  5 siblings, 0 replies; 11+ messages in thread
From: Jeremy Kerr @ 2021-10-01  8:18 UTC (permalink / raw)
  To: netdev
  Cc: Matt Johnston, David S. Miller, Jakub Kicinski, Brendan Higgins,
	linux-kselftest

Add a few tests for single-packet route inputs, testing the
mctp_route_input function.

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 net/mctp/test/route-test.c | 131 +++++++++++++++++++++++++++++++++++++
 1 file changed, 131 insertions(+)

diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
index ee0422bf24ce..efb621317ec5 100644
--- a/net/mctp/test/route-test.c
+++ b/net/mctp/test/route-test.c
@@ -94,6 +94,26 @@ static struct sk_buff *mctp_test_create_skb(const struct mctp_hdr *hdr,
 	return skb;
 }
 
+static struct sk_buff *__mctp_test_create_skb_data(const struct mctp_hdr *hdr,
+						   const void *data,
+						   size_t data_len)
+{
+	size_t hdr_len = sizeof(*hdr);
+	struct sk_buff *skb;
+
+	skb = alloc_skb(hdr_len + data_len, GFP_KERNEL);
+	if (!skb)
+		return NULL;
+
+	memcpy(skb_put(skb, hdr_len), hdr, hdr_len);
+	memcpy(skb_put(skb, data_len), data, data_len);
+
+	return skb;
+}
+
+#define mctp_test_create_skb_data(h, d) \
+	__mctp_test_create_skb_data(h, d, sizeof(*d))
+
 struct mctp_frag_test {
 	unsigned int mtu;
 	unsigned int msgsize;
@@ -253,9 +273,120 @@ static void mctp_rx_input_test_to_desc(const struct mctp_rx_input_test *t,
 KUNIT_ARRAY_PARAM(mctp_rx_input, mctp_rx_input_tests,
 		  mctp_rx_input_test_to_desc);
 
+/* set up a local dev, route on EID 8, and a socket listening on type 0 */
+static void __mctp_route_test_init(struct kunit *test,
+				   struct mctp_test_dev **devp,
+				   struct mctp_test_route **rtp,
+				   struct socket **sockp)
+{
+	struct sockaddr_mctp addr;
+	struct mctp_test_route *rt;
+	struct mctp_test_dev *dev;
+	struct socket *sock;
+	int rc;
+
+	dev = mctp_test_create_dev();
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+	rt = mctp_test_create_route(&init_net, dev->mdev, 8, 68);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, rt);
+
+	rc = sock_create_kern(&init_net, AF_MCTP, SOCK_DGRAM, 0, &sock);
+	KUNIT_ASSERT_EQ(test, rc, 0);
+
+	addr.smctp_family = AF_MCTP;
+	addr.smctp_network = MCTP_NET_ANY;
+	addr.smctp_addr.s_addr = 8;
+	addr.smctp_type = 0;
+	rc = kernel_bind(sock, (struct sockaddr *)&addr, sizeof(addr));
+	KUNIT_ASSERT_EQ(test, rc, 0);
+
+	*rtp = rt;
+	*devp = dev;
+	*sockp = sock;
+}
+
+static void __mctp_route_test_fini(struct mctp_test_dev *dev,
+				   struct mctp_test_route *rt,
+				   struct socket *sock)
+{
+	sock_release(sock);
+	mctp_test_route_destroy(rt);
+	mctp_test_destroy_dev(dev);
+}
+
+struct mctp_route_input_sk_test {
+	struct mctp_hdr hdr;
+	u8 type;
+	bool deliver;
+};
+
+static void mctp_test_route_input_sk(struct kunit *test)
+{
+	const struct mctp_route_input_sk_test *params;
+	struct sk_buff *skb, *skb2;
+	struct mctp_test_route *rt;
+	struct mctp_test_dev *dev;
+	struct socket *sock;
+	int rc;
+
+	params = test->param_value;
+
+	__mctp_route_test_init(test, &dev, &rt, &sock);
+
+	skb = mctp_test_create_skb_data(&params->hdr, &params->type);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb);
+
+	skb->dev = dev->ndev;
+	__mctp_cb(skb);
+
+	rc = mctp_route_input(&rt->rt, skb);
+
+	if (params->deliver) {
+		KUNIT_EXPECT_EQ(test, rc, 0);
+
+		skb2 = skb_recv_datagram(sock->sk, 0, 1, &rc);
+		KUNIT_EXPECT_NOT_ERR_OR_NULL(test, skb2);
+		KUNIT_EXPECT_EQ(test, skb->len, 1);
+
+		skb_free_datagram(sock->sk, skb2);
+
+	} else {
+		KUNIT_EXPECT_NE(test, rc, 0);
+		skb2 = skb_recv_datagram(sock->sk, 0, 1, &rc);
+		KUNIT_EXPECT_PTR_EQ(test, skb2, NULL);
+	}
+
+	__mctp_route_test_fini(dev, rt, sock);
+}
+
+#define FL_S	(MCTP_HDR_FLAG_SOM)
+#define FL_E	(MCTP_HDR_FLAG_EOM)
+#define FL_T	(MCTP_HDR_FLAG_TO)
+
+static const struct mctp_route_input_sk_test mctp_route_input_sk_tests[] = {
+	{ .hdr = RX_HDR(1, 10, 8, FL_S | FL_E | FL_T), .type = 0, .deliver = true },
+	{ .hdr = RX_HDR(1, 10, 8, FL_S | FL_E | FL_T), .type = 1, .deliver = false },
+	{ .hdr = RX_HDR(1, 10, 8, FL_S | FL_E), .type = 0, .deliver = false },
+	{ .hdr = RX_HDR(1, 10, 8, FL_E | FL_T), .type = 0, .deliver = false },
+	{ .hdr = RX_HDR(1, 10, 8, FL_T), .type = 0, .deliver = false },
+	{ .hdr = RX_HDR(1, 10, 8, 0), .type = 0, .deliver = false },
+};
+
+static void mctp_route_input_sk_to_desc(const struct mctp_route_input_sk_test *t,
+					char *desc)
+{
+	sprintf(desc, "{%x,%x,%x,%x} type %d", t->hdr.ver, t->hdr.src,
+		t->hdr.dest, t->hdr.flags_seq_tag, t->type);
+}
+
+KUNIT_ARRAY_PARAM(mctp_route_input_sk, mctp_route_input_sk_tests,
+		  mctp_route_input_sk_to_desc);
+
 static struct kunit_case mctp_test_cases[] = {
 	KUNIT_CASE_PARAM(mctp_test_fragment, mctp_frag_gen_params),
 	KUNIT_CASE_PARAM(mctp_test_rx_input, mctp_rx_input_gen_params),
+	KUNIT_CASE_PARAM(mctp_test_route_input_sk, mctp_route_input_sk_gen_params),
 	{}
 };
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH net-next 5/5] mctp: Add input reassembly tests
  2021-10-01  8:18 [PATCH net-next 0/5] MCTP kunit tests Jeremy Kerr
                   ` (3 preceding siblings ...)
  2021-10-01  8:18 ` [PATCH net-next 4/5] mctp: Add route input to socket tests Jeremy Kerr
@ 2021-10-01  8:18 ` Jeremy Kerr
  2021-10-01 13:20 ` [PATCH net-next 0/5] MCTP kunit tests patchwork-bot+netdevbpf
  5 siblings, 0 replies; 11+ messages in thread
From: Jeremy Kerr @ 2021-10-01  8:18 UTC (permalink / raw)
  To: netdev
  Cc: Matt Johnston, David S. Miller, Jakub Kicinski, Brendan Higgins,
	linux-kselftest

Add multi-packet route input tests, for message reassembly. These will
feed packets to be received by a bound socket, or dropped.

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
---
 net/mctp/test/route-test.c | 134 +++++++++++++++++++++++++++++++++++++
 1 file changed, 134 insertions(+)

diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
index efb621317ec5..2785a8ea554c 100644
--- a/net/mctp/test/route-test.c
+++ b/net/mctp/test/route-test.c
@@ -383,10 +383,144 @@ static void mctp_route_input_sk_to_desc(const struct mctp_route_input_sk_test *t
 KUNIT_ARRAY_PARAM(mctp_route_input_sk, mctp_route_input_sk_tests,
 		  mctp_route_input_sk_to_desc);
 
+struct mctp_route_input_sk_reasm_test {
+	const char *name;
+	struct mctp_hdr hdrs[4];
+	int n_hdrs;
+	int rx_len;
+};
+
+static void mctp_test_route_input_sk_reasm(struct kunit *test)
+{
+	const struct mctp_route_input_sk_reasm_test *params;
+	struct sk_buff *skb, *skb2;
+	struct mctp_test_route *rt;
+	struct mctp_test_dev *dev;
+	struct socket *sock;
+	int i, rc;
+	u8 c;
+
+	params = test->param_value;
+
+	__mctp_route_test_init(test, &dev, &rt, &sock);
+
+	for (i = 0; i < params->n_hdrs; i++) {
+		c = i;
+		skb = mctp_test_create_skb_data(&params->hdrs[i], &c);
+		KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb);
+
+		skb->dev = dev->ndev;
+		__mctp_cb(skb);
+
+		rc = mctp_route_input(&rt->rt, skb);
+	}
+
+	skb2 = skb_recv_datagram(sock->sk, 0, 1, &rc);
+
+	if (params->rx_len) {
+		KUNIT_EXPECT_NOT_ERR_OR_NULL(test, skb2);
+		KUNIT_EXPECT_EQ(test, skb2->len, params->rx_len);
+		skb_free_datagram(sock->sk, skb2);
+
+	} else {
+		KUNIT_EXPECT_PTR_EQ(test, skb2, NULL);
+	}
+
+	__mctp_route_test_fini(dev, rt, sock);
+}
+
+#define RX_FRAG(f, s) RX_HDR(1, 10, 8, FL_T | (f) | ((s) << MCTP_HDR_SEQ_SHIFT))
+
+static const struct mctp_route_input_sk_reasm_test mctp_route_input_sk_reasm_tests[] = {
+	{
+		.name = "single packet",
+		.hdrs = {
+			RX_FRAG(FL_S | FL_E, 0),
+		},
+		.n_hdrs = 1,
+		.rx_len = 1,
+	},
+	{
+		.name = "single packet, offset seq",
+		.hdrs = {
+			RX_FRAG(FL_S | FL_E, 1),
+		},
+		.n_hdrs = 1,
+		.rx_len = 1,
+	},
+	{
+		.name = "start & end packets",
+		.hdrs = {
+			RX_FRAG(FL_S, 0),
+			RX_FRAG(FL_E, 1),
+		},
+		.n_hdrs = 2,
+		.rx_len = 2,
+	},
+	{
+		.name = "start & end packets, offset seq",
+		.hdrs = {
+			RX_FRAG(FL_S, 1),
+			RX_FRAG(FL_E, 2),
+		},
+		.n_hdrs = 2,
+		.rx_len = 2,
+	},
+	{
+		.name = "start & end packets, out of order",
+		.hdrs = {
+			RX_FRAG(FL_E, 1),
+			RX_FRAG(FL_S, 0),
+		},
+		.n_hdrs = 2,
+		.rx_len = 0,
+	},
+	{
+		.name = "start, middle & end packets",
+		.hdrs = {
+			RX_FRAG(FL_S, 0),
+			RX_FRAG(0,    1),
+			RX_FRAG(FL_E, 2),
+		},
+		.n_hdrs = 3,
+		.rx_len = 3,
+	},
+	{
+		.name = "missing seq",
+		.hdrs = {
+			RX_FRAG(FL_S, 0),
+			RX_FRAG(FL_E, 2),
+		},
+		.n_hdrs = 2,
+		.rx_len = 0,
+	},
+	{
+		.name = "seq wrap",
+		.hdrs = {
+			RX_FRAG(FL_S, 3),
+			RX_FRAG(FL_E, 0),
+		},
+		.n_hdrs = 2,
+		.rx_len = 2,
+	},
+};
+
+static void mctp_route_input_sk_reasm_to_desc(
+				const struct mctp_route_input_sk_reasm_test *t,
+				char *desc)
+{
+	sprintf(desc, "%s", t->name);
+}
+
+KUNIT_ARRAY_PARAM(mctp_route_input_sk_reasm, mctp_route_input_sk_reasm_tests,
+		  mctp_route_input_sk_reasm_to_desc);
+
 static struct kunit_case mctp_test_cases[] = {
 	KUNIT_CASE_PARAM(mctp_test_fragment, mctp_frag_gen_params),
 	KUNIT_CASE_PARAM(mctp_test_rx_input, mctp_rx_input_gen_params),
 	KUNIT_CASE_PARAM(mctp_test_route_input_sk, mctp_route_input_sk_gen_params),
+	KUNIT_CASE_PARAM(mctp_test_route_input_sk_reasm,
+			 mctp_route_input_sk_reasm_gen_params),
 	{}
 };
 
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next 0/5] MCTP kunit tests
  2021-10-01  8:18 [PATCH net-next 0/5] MCTP kunit tests Jeremy Kerr
                   ` (4 preceding siblings ...)
  2021-10-01  8:18 ` [PATCH net-next 5/5] mctp: Add input reassembly tests Jeremy Kerr
@ 2021-10-01 13:20 ` patchwork-bot+netdevbpf
  5 siblings, 0 replies; 11+ messages in thread
From: patchwork-bot+netdevbpf @ 2021-10-01 13:20 UTC (permalink / raw)
  To: Jeremy Kerr; +Cc: netdev, matt, davem, kuba, brendanhiggins, linux-kselftest

Hello:

This series was applied to netdev/net-next.git (refs/heads/master):

On Fri,  1 Oct 2021 16:18:39 +0800 you wrote:
> This change adds some initial kunit tests for the MCTP core. We'll
> expand the coverage in a future series, and augment with a few
> selftests, but this establishes a baseline set of tests for now.
> 
> Thanks to the kunit folks for the framework!
> 
> Cheers,
> 
> [...]

Here is the summary with links:
  - [net-next,1/5] mctp: Add initial test structure and fragmentation test
    https://git.kernel.org/netdev/net-next/c/8c02066b053d
  - [net-next,2/5] mctp: Add test utils
    https://git.kernel.org/netdev/net-next/c/077b6d52df6d
  - [net-next,3/5] mctp: Add packet rx tests
    https://git.kernel.org/netdev/net-next/c/925c01afb06a
  - [net-next,4/5] mctp: Add route input to socket tests
    https://git.kernel.org/netdev/net-next/c/d04dcc2d67ef
  - [net-next,5/5] mctp: Add input reassembly tests
    https://git.kernel.org/netdev/net-next/c/bbde430319ee

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test
  2021-10-01  8:18 ` [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test Jeremy Kerr
@ 2021-10-01 19:16   ` kernel test robot
  2021-10-01 23:09   ` kernel test robot
  2021-10-02  2:56   ` David Gow
  2 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2021-10-01 19:16 UTC (permalink / raw)
  To: Jeremy Kerr, netdev
  Cc: kbuild-all, Matt Johnston, Jakub Kicinski, Brendan Higgins,
	linux-kselftest

[-- Attachment #1: Type: text/plain, Size: 1734 bytes --]

Hi Jeremy,

I love your patch! Yet something to improve:

[auto build test ERROR on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Jeremy-Kerr/MCTP-kunit-tests/20211001-162019
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git b05173028cc52384be42dcf81abdb4133caccfa5
config: alpha-randconfig-r026-20211001 (attached as .config)
compiler: alpha-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/4cc0785d056598892d81256078a62a8c52458d6d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jeremy-Kerr/MCTP-kunit-tests/20211001-162019
        git checkout 4cc0785d056598892d81256078a62a8c52458d6d
        # save the attached .config to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=alpha SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   alpha-linux-ld: net/mctp/route.o: in function `kunit_test_suites_init':
>> (.init.text+0x198): multiple definition of `init_module'; net/mctp/af_mctp.o:(.init.text+0x0): first defined here
   alpha-linux-ld: net/mctp/route.o: in function `kunit_test_suites_exit':
>> (.exit.text+0xa4): multiple definition of `cleanup_module'; net/mctp/af_mctp.o:(.exit.text+0x0): first defined here

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32552 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test
  2021-10-01  8:18 ` [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test Jeremy Kerr
  2021-10-01 19:16   ` kernel test robot
@ 2021-10-01 23:09   ` kernel test robot
  2021-10-02  2:56   ` David Gow
  2 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2021-10-01 23:09 UTC (permalink / raw)
  To: Jeremy Kerr, netdev
  Cc: kbuild-all, Matt Johnston, Jakub Kicinski, Brendan Higgins,
	linux-kselftest

[-- Attachment #1: Type: text/plain, Size: 1745 bytes --]

Hi Jeremy,

I love your patch! Yet something to improve:

[auto build test ERROR on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Jeremy-Kerr/MCTP-kunit-tests/20211001-162019
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git b05173028cc52384be42dcf81abdb4133caccfa5
config: sh-allmodconfig (attached as .config)
compiler: sh4-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/4cc0785d056598892d81256078a62a8c52458d6d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jeremy-Kerr/MCTP-kunit-tests/20211001-162019
        git checkout 4cc0785d056598892d81256078a62a8c52458d6d
        # save the attached .config to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=sh SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   sh4-linux-ld: net/mctp/route.o: in function `kunit_test_suites_exit':
>> route.c:(.exit.text+0x54): multiple definition of `cleanup_module'; net/mctp/af_mctp.o:af_mctp.c:(.exit.text+0x0): first defined here
   sh4-linux-ld: net/mctp/route.o: in function `kunit_test_suites_init':
>> route.c:(.init.text+0xa0): multiple definition of `init_module'; net/mctp/af_mctp.o:af_mctp.c:(.init.text+0x0): first defined here

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 55499 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next 3/5] mctp: Add packet rx tests
  2021-10-01  8:18 ` [PATCH net-next 3/5] mctp: Add packet rx tests Jeremy Kerr
@ 2021-10-02  0:39   ` kernel test robot
  0 siblings, 0 replies; 11+ messages in thread
From: kernel test robot @ 2021-10-02  0:39 UTC (permalink / raw)
  To: Jeremy Kerr, netdev
  Cc: llvm, kbuild-all, Matt Johnston, Jakub Kicinski, Brendan Higgins,
	linux-kselftest

[-- Attachment #1: Type: text/plain, Size: 1837 bytes --]

Hi Jeremy,

I love your patch! Yet something to improve:

[auto build test ERROR on net-next/master]

url:    https://github.com/0day-ci/linux/commits/Jeremy-Kerr/MCTP-kunit-tests/20211001-162019
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git b05173028cc52384be42dcf81abdb4133caccfa5
config: arm-randconfig-r006-20211001 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 962e503cc8bc411f7523cc393acae8aae425b1c4)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install arm cross compiling tool for clang build
        # apt-get install binutils-arm-linux-gnueabi
        # https://github.com/0day-ci/linux/commit/85da939dab5470b1f2a921867d780af5a1fd8aab
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jeremy-Kerr/MCTP-kunit-tests/20211001-162019
        git checkout 85da939dab5470b1f2a921867d780af5a1fd8aab
        # save the attached .config to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> ld.lld: error: undefined symbol: mctp_test_create_dev
   >>> referenced by route.c
   >>> mctp/route.o:(mctp_test_rx_input) in archive net/built-in.a
--
>> ld.lld: error: undefined symbol: mctp_test_destroy_dev
   >>> referenced by route.c
   >>> mctp/route.o:(mctp_test_rx_input) in archive net/built-in.a

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32263 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test
  2021-10-01  8:18 ` [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test Jeremy Kerr
  2021-10-01 19:16   ` kernel test robot
  2021-10-01 23:09   ` kernel test robot
@ 2021-10-02  2:56   ` David Gow
  2 siblings, 0 replies; 11+ messages in thread
From: David Gow @ 2021-10-02  2:56 UTC (permalink / raw)
  To: Jeremy Kerr
  Cc: Networking, Matt Johnston, David S. Miller, Jakub Kicinski,
	Brendan Higgins, open list:KERNEL SELFTEST FRAMEWORK

On Fri, Oct 1, 2021 at 4:19 PM Jeremy Kerr <jk@codeconstruct.com.au> wrote:
>
> This change adds the first kunit test for the mctp subsystem, and an
> initial test for the fragmentation path.
>
> We're adding tests under a new net/mctp/test/ directory.
>
> Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
> ---

Thanks for writing these tests. There are (as you've probably noticed)
a couple of issues with them at the moment, but it shouldn't take too
much to fix.

A few comments below.

-- David

>  net/mctp/Kconfig           |   5 +
>  net/mctp/route.c           |   5 +
>  net/mctp/test/route-test.c | 206 +++++++++++++++++++++++++++++++++++++
>  3 files changed, 216 insertions(+)
>  create mode 100644 net/mctp/test/route-test.c
>
> diff --git a/net/mctp/Kconfig b/net/mctp/Kconfig
> index 2cdf3d0a28c9..15267a5043d9 100644
> --- a/net/mctp/Kconfig
> +++ b/net/mctp/Kconfig
> @@ -11,3 +11,8 @@ menuconfig MCTP
>           This option enables core MCTP support. For communicating with other
>           devices, you'll want to enable a driver for a specific hardware
>           channel.
> +
> +config MCTP_TEST
> +        tristate "MCTP core tests" if !KUNIT_ALL_TESTS
> +        depends on MCTP && KUNIT
> +        default KUNIT_ALL_TESTS
> diff --git a/net/mctp/route.c b/net/mctp/route.c
> index 9bea232cf250..b7e4e6281806 100644
> --- a/net/mctp/route.c
> +++ b/net/mctp/route.c
> @@ -11,6 +11,7 @@
>   */
>
>  #include <linux/idr.h>
> +#include <linux/kconfig.h>
>  #include <linux/mctp.h>
>  #include <linux/netdevice.h>
>  #include <linux/rtnetlink.h>
> @@ -1275,3 +1276,7 @@ void __exit mctp_routes_exit(void)
>         rtnl_unregister(PF_MCTP, RTM_GETROUTE);
>         dev_remove_pack(&mctp_packet_type);
>  }
> +
> +#if IS_ENABLED(CONFIG_MCTP_TEST)
> +#include "test/route-test.c"
> +#endif

FYI: This is not going to work if MCTP is built as a module.

Basically, KUnit's module support currently provides its own
module_init()/module_exit(), so really needs the test to be part of
its own separate module, rather than #included into the mctp module.

Hopefully we'll find a nicer way of handling this sort of thing in
KUnit, but in the meantime, the options are to compile the tests
separately (which would require exporting any functions being tested,
at least if CONFIG_MCTP_TEST is enabled), or to just drop module
support from the test (making MCTP_TEST bool, and having it depend on
MCTP=y).


> diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
> new file mode 100644
> index 000000000000..cf3b51183613
> --- /dev/null
> +++ b/net/mctp/test/route-test.c
> @@ -0,0 +1,206 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <kunit/test.h>
> +
> +struct mctp_test_route {
> +       struct mctp_route       rt;
> +       struct sk_buff_head     pkts;
> +};
> +
> +static int mctp_test_route_output(struct mctp_route *rt, struct sk_buff *skb)
> +{
> +       struct mctp_test_route *test_rt = container_of(rt, struct mctp_test_route, rt);
> +
> +       skb_queue_tail(&test_rt->pkts, skb);
> +
> +       return 0;
> +}
> +
> +/* local version of mctp_route_alloc() */
> +static struct mctp_test_route *mctp_route_test_alloc(void)
> +{
> +       struct mctp_test_route *rt;
> +
> +       rt = kzalloc(sizeof(*rt), GFP_KERNEL);
> +       if (!rt)
> +               return NULL;
> +
> +       INIT_LIST_HEAD(&rt->rt.list);
> +       refcount_set(&rt->rt.refs, 1);
> +       rt->rt.output = mctp_test_route_output;
> +
> +       skb_queue_head_init(&rt->pkts);
> +
> +       return rt;
> +}
> +
> +static struct mctp_test_route *mctp_test_create_route(struct net *net,
> +                                                     mctp_eid_t eid,
> +                                                     unsigned int mtu)
> +{
> +       struct mctp_test_route *rt;
> +
> +       rt = mctp_route_test_alloc();
> +       if (!rt)
> +               return NULL;
> +
> +       rt->rt.min = eid;
> +       rt->rt.max = eid;
> +       rt->rt.mtu = mtu;
> +       rt->rt.type = RTN_UNSPEC;
> +       rt->rt.dev = NULL; /* somewhat illegal, but fine for current tests */

This actually causes a crash for me:

BUG: kernel NULL pointer dereference, address: 00000004
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
<snip>
Call Trace:
mctp_route_release+0x28/0x70
mctp_do_fragment_route+0x25a/0x2a0
mctp_test_fragment+0x150/0x770
? kunit_fail_assert_format+0x70/0x70
? __schedule+0x1a7/0x480
kunit_try_run_case+0x4c/0x80
kunit_generic_run_threadfn_adapter+0x11/0x20
kthread+0xe7/0x110
? kunit_binary_str_assert_format+0x120/0x120
? set_kthread_struct+0x40/0x40
ret_from_fork+0x1c/0x28
CR2: 0000000000000004
---[ end trace fbe68c67c18e04a5 ]---

Only calling mctp_dev_put() if rt->dev is non-NULL in
mctp_route_release() fixes it, e.g.:

diff --git a/net/mctp/route.c b/net/mctp/route.c
index 04781459b2be..3692e7e8a555 100644
--- a/net/mctp/route.c
+++ b/net/mctp/route.c
@@ -469,7 +469,8 @@ static int mctp_route_output(struct mctp_route
*route, struct sk_buff *skb)
static void mctp_route_release(struct mctp_route *rt)
{
       if (refcount_dec_and_test(&rt->refs)) {
-               mctp_dev_put(rt->dev);
+               if (rt->dev)
+                       mctp_dev_put(rt->dev);
               kfree_rcu(rt, rcu);

       }
}


> +
> +       list_add_rcu(&rt->rt.list, &net->mctp.routes);
> +
> +       return rt;
> +}
> +
> +static void mctp_test_route_destroy(struct mctp_test_route *rt)
> +{
> +       rtnl_lock();
> +       list_del_rcu(&rt->rt.list);
> +       rtnl_unlock();
> +
> +       skb_queue_purge(&rt->pkts);
> +
> +       kfree_rcu(&rt->rt, rcu);
> +}
> +
> +static struct sk_buff *mctp_test_create_skb(struct mctp_hdr *hdr,
> +                                           unsigned int data_len)
> +{
> +       size_t hdr_len = sizeof(*hdr);
> +       struct sk_buff *skb;
> +       unsigned int i;
> +       u8 *buf;
> +
> +       skb = alloc_skb(hdr_len + data_len, GFP_KERNEL);
> +       if (!skb)
> +               return NULL;
> +
> +       memcpy(skb_put(skb, hdr_len), hdr, hdr_len);
> +
> +       buf = skb_put(skb, data_len);
> +       for (i = 0; i < data_len; i++)
> +               buf[i] = i & 0xff;
> +
> +       return skb;
> +}
> +
> +struct mctp_frag_test {
> +       unsigned int mtu;
> +       unsigned int msgsize;
> +       unsigned int n_frags;
> +};
> +
> +static void mctp_test_fragment(struct kunit *test)
> +{
> +       const struct mctp_frag_test *params;
> +       int rc, i, n, mtu, msgsize;
> +       struct mctp_test_route *rt;
> +       struct sk_buff *skb;
> +       struct mctp_hdr hdr;
> +       u8 seq;
> +
> +       params = test->param_value;
> +       mtu = params->mtu;
> +       msgsize = params->msgsize;
> +
> +       hdr.ver = 1;
> +       hdr.src = 8;
> +       hdr.dest = 10;
> +       hdr.flags_seq_tag = MCTP_HDR_FLAG_TO;
> +
> +       skb = mctp_test_create_skb(&hdr, msgsize);
> +       KUNIT_ASSERT_TRUE(test, skb);
> +
> +       rt = mctp_test_create_route(&init_net, 10, mtu);
> +       KUNIT_ASSERT_TRUE(test, rt);
> +
> +       rc = mctp_do_fragment_route(&rt->rt, skb, mtu, MCTP_TAG_OWNER);
> +       KUNIT_EXPECT_FALSE(test, rc);
> +
> +       n = rt->pkts.qlen;
> +
> +       KUNIT_EXPECT_EQ(test, n, params->n_frags);
> +
> +       for (i = 0;; i++) {
> +               struct mctp_hdr *hdr2;
> +               struct sk_buff *skb2;
> +               u8 tag_mask, seq2;
> +               bool first, last;
> +
> +               first = i == 0;
> +               last = i == (n - 1);
> +
> +               skb2 = skb_dequeue(&rt->pkts);
> +
> +               if (!skb2)
> +                       break;
> +
> +               hdr2 = mctp_hdr(skb2);
> +
> +               tag_mask = MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO;
> +
> +               KUNIT_EXPECT_EQ(test, hdr2->ver, hdr.ver);
> +               KUNIT_EXPECT_EQ(test, hdr2->src, hdr.src);
> +               KUNIT_EXPECT_EQ(test, hdr2->dest, hdr.dest);
> +               KUNIT_EXPECT_EQ(test, hdr2->flags_seq_tag & tag_mask,
> +                               hdr.flags_seq_tag & tag_mask);
> +
> +               KUNIT_EXPECT_EQ(test,
> +                               !!(hdr2->flags_seq_tag & MCTP_HDR_FLAG_SOM), first);
> +               KUNIT_EXPECT_EQ(test,
> +                               !!(hdr2->flags_seq_tag & MCTP_HDR_FLAG_EOM), last);
> +
> +               seq2 = (hdr2->flags_seq_tag >> MCTP_HDR_SEQ_SHIFT) &
> +                       MCTP_HDR_SEQ_MASK;
> +
> +               if (first) {
> +                       seq = seq2;
> +               } else {
> +                       seq++;
> +                       KUNIT_EXPECT_EQ(test, seq2, seq & MCTP_HDR_SEQ_MASK);
> +               }
> +
> +               if (!last)
> +                       KUNIT_EXPECT_EQ(test, skb2->len, mtu);
> +               else
> +                       KUNIT_EXPECT_LE(test, skb2->len, mtu);
> +
> +               kfree_skb(skb2);
> +       }
> +
> +       mctp_test_route_destroy(rt);
> +}
> +
> +static const struct mctp_frag_test mctp_frag_tests[] = {
> +       {.mtu = 68, .msgsize = 63, .n_frags = 1},
> +       {.mtu = 68, .msgsize = 64, .n_frags = 1},
> +       {.mtu = 68, .msgsize = 65, .n_frags = 2},
> +       {.mtu = 68, .msgsize = 66, .n_frags = 2},
> +       {.mtu = 68, .msgsize = 127, .n_frags = 2},
> +       {.mtu = 68, .msgsize = 128, .n_frags = 2},
> +       {.mtu = 68, .msgsize = 129, .n_frags = 3},
> +       {.mtu = 68, .msgsize = 130, .n_frags = 3},
> +};
> +
> +static void mctp_frag_test_to_desc(const struct mctp_frag_test *t, char *desc)
> +{
> +       sprintf(desc, "mtu %d len %d -> %d frags",
> +               t->msgsize, t->mtu, t->n_frags);
> +}
> +
> +KUNIT_ARRAY_PARAM(mctp_frag, mctp_frag_tests, mctp_frag_test_to_desc);
> +
> +static struct kunit_case mctp_test_cases[] = {
> +       KUNIT_CASE_PARAM(mctp_test_fragment, mctp_frag_gen_params),
> +       {}
> +};
> +
> +static struct kunit_suite mctp_test_suite = {
> +       .name = "mctp",
> +       .test_cases = mctp_test_cases,
> +};
> +
> +kunit_test_suite(mctp_test_suite);
> --
> 2.33.0
>

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-10-02  2:57 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-01  8:18 [PATCH net-next 0/5] MCTP kunit tests Jeremy Kerr
2021-10-01  8:18 ` [PATCH net-next 1/5] mctp: Add initial test structure and fragmentation test Jeremy Kerr
2021-10-01 19:16   ` kernel test robot
2021-10-01 23:09   ` kernel test robot
2021-10-02  2:56   ` David Gow
2021-10-01  8:18 ` [PATCH net-next 2/5] mctp: Add test utils Jeremy Kerr
2021-10-01  8:18 ` [PATCH net-next 3/5] mctp: Add packet rx tests Jeremy Kerr
2021-10-02  0:39   ` kernel test robot
2021-10-01  8:18 ` [PATCH net-next 4/5] mctp: Add route input to socket tests Jeremy Kerr
2021-10-01  8:18 ` [PATCH net-next 5/5] mctp: Add input reassembly tests Jeremy Kerr
2021-10-01 13:20 ` [PATCH net-next 0/5] MCTP kunit tests patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).