xref: /linux/net/core/net_test.c (revision 6dd514f4)
15b2be2abSAlexander Lobakin // SPDX-License-Identifier: GPL-2.0-or-later
25b2be2abSAlexander Lobakin 
35b2be2abSAlexander Lobakin #include <kunit/test.h>
45b2be2abSAlexander Lobakin 
55b2be2abSAlexander Lobakin /* GSO */
65b2be2abSAlexander Lobakin 
75b2be2abSAlexander Lobakin #include <linux/skbuff.h>
85b2be2abSAlexander Lobakin 
95b2be2abSAlexander Lobakin static const char hdr[] = "abcdefgh";
105b2be2abSAlexander Lobakin #define GSO_TEST_SIZE 1000
115b2be2abSAlexander Lobakin 
__init_skb(struct sk_buff * skb)125b2be2abSAlexander Lobakin static void __init_skb(struct sk_buff *skb)
135b2be2abSAlexander Lobakin {
145b2be2abSAlexander Lobakin 	skb_reset_mac_header(skb);
155b2be2abSAlexander Lobakin 	memcpy(skb_mac_header(skb), hdr, sizeof(hdr));
165b2be2abSAlexander Lobakin 
175b2be2abSAlexander Lobakin 	/* skb_segment expects skb->data at start of payload */
185b2be2abSAlexander Lobakin 	skb_pull(skb, sizeof(hdr));
195b2be2abSAlexander Lobakin 	skb_reset_network_header(skb);
205b2be2abSAlexander Lobakin 	skb_reset_transport_header(skb);
215b2be2abSAlexander Lobakin 
225b2be2abSAlexander Lobakin 	/* proto is arbitrary, as long as not ETH_P_TEB or vlan */
235b2be2abSAlexander Lobakin 	skb->protocol = htons(ETH_P_ATALK);
245b2be2abSAlexander Lobakin 	skb_shinfo(skb)->gso_size = GSO_TEST_SIZE;
255b2be2abSAlexander Lobakin }
265b2be2abSAlexander Lobakin 
275b2be2abSAlexander Lobakin enum gso_test_nr {
285b2be2abSAlexander Lobakin 	GSO_TEST_LINEAR,
295b2be2abSAlexander Lobakin 	GSO_TEST_NO_GSO,
305b2be2abSAlexander Lobakin 	GSO_TEST_FRAGS,
315b2be2abSAlexander Lobakin 	GSO_TEST_FRAGS_PURE,
325b2be2abSAlexander Lobakin 	GSO_TEST_GSO_PARTIAL,
335b2be2abSAlexander Lobakin 	GSO_TEST_FRAG_LIST,
345b2be2abSAlexander Lobakin 	GSO_TEST_FRAG_LIST_PURE,
355b2be2abSAlexander Lobakin 	GSO_TEST_FRAG_LIST_NON_UNIFORM,
365b2be2abSAlexander Lobakin 	GSO_TEST_GSO_BY_FRAGS,
375b2be2abSAlexander Lobakin };
385b2be2abSAlexander Lobakin 
395b2be2abSAlexander Lobakin struct gso_test_case {
405b2be2abSAlexander Lobakin 	enum gso_test_nr id;
415b2be2abSAlexander Lobakin 	const char *name;
425b2be2abSAlexander Lobakin 
435b2be2abSAlexander Lobakin 	/* input */
445b2be2abSAlexander Lobakin 	unsigned int linear_len;
455b2be2abSAlexander Lobakin 	unsigned int nr_frags;
465b2be2abSAlexander Lobakin 	const unsigned int *frags;
475b2be2abSAlexander Lobakin 	unsigned int nr_frag_skbs;
485b2be2abSAlexander Lobakin 	const unsigned int *frag_skbs;
495b2be2abSAlexander Lobakin 
505b2be2abSAlexander Lobakin 	/* output as expected */
515b2be2abSAlexander Lobakin 	unsigned int nr_segs;
525b2be2abSAlexander Lobakin 	const unsigned int *segs;
535b2be2abSAlexander Lobakin };
545b2be2abSAlexander Lobakin 
555b2be2abSAlexander Lobakin static struct gso_test_case cases[] = {
565b2be2abSAlexander Lobakin 	{
575b2be2abSAlexander Lobakin 		.id = GSO_TEST_NO_GSO,
585b2be2abSAlexander Lobakin 		.name = "no_gso",
595b2be2abSAlexander Lobakin 		.linear_len = GSO_TEST_SIZE,
605b2be2abSAlexander Lobakin 		.nr_segs = 1,
615b2be2abSAlexander Lobakin 		.segs = (const unsigned int[]) { GSO_TEST_SIZE },
625b2be2abSAlexander Lobakin 	},
635b2be2abSAlexander Lobakin 	{
645b2be2abSAlexander Lobakin 		.id = GSO_TEST_LINEAR,
655b2be2abSAlexander Lobakin 		.name = "linear",
665b2be2abSAlexander Lobakin 		.linear_len = GSO_TEST_SIZE + GSO_TEST_SIZE + 1,
675b2be2abSAlexander Lobakin 		.nr_segs = 3,
685b2be2abSAlexander Lobakin 		.segs = (const unsigned int[]) { GSO_TEST_SIZE, GSO_TEST_SIZE, 1 },
695b2be2abSAlexander Lobakin 	},
705b2be2abSAlexander Lobakin 	{
715b2be2abSAlexander Lobakin 		.id = GSO_TEST_FRAGS,
725b2be2abSAlexander Lobakin 		.name = "frags",
735b2be2abSAlexander Lobakin 		.linear_len = GSO_TEST_SIZE,
745b2be2abSAlexander Lobakin 		.nr_frags = 2,
755b2be2abSAlexander Lobakin 		.frags = (const unsigned int[]) { GSO_TEST_SIZE, 1 },
765b2be2abSAlexander Lobakin 		.nr_segs = 3,
775b2be2abSAlexander Lobakin 		.segs = (const unsigned int[]) { GSO_TEST_SIZE, GSO_TEST_SIZE, 1 },
785b2be2abSAlexander Lobakin 	},
795b2be2abSAlexander Lobakin 	{
805b2be2abSAlexander Lobakin 		.id = GSO_TEST_FRAGS_PURE,
815b2be2abSAlexander Lobakin 		.name = "frags_pure",
825b2be2abSAlexander Lobakin 		.nr_frags = 3,
835b2be2abSAlexander Lobakin 		.frags = (const unsigned int[]) { GSO_TEST_SIZE, GSO_TEST_SIZE, 2 },
845b2be2abSAlexander Lobakin 		.nr_segs = 3,
855b2be2abSAlexander Lobakin 		.segs = (const unsigned int[]) { GSO_TEST_SIZE, GSO_TEST_SIZE, 2 },
865b2be2abSAlexander Lobakin 	},
875b2be2abSAlexander Lobakin 	{
885b2be2abSAlexander Lobakin 		.id = GSO_TEST_GSO_PARTIAL,
895b2be2abSAlexander Lobakin 		.name = "gso_partial",
905b2be2abSAlexander Lobakin 		.linear_len = GSO_TEST_SIZE,
915b2be2abSAlexander Lobakin 		.nr_frags = 2,
925b2be2abSAlexander Lobakin 		.frags = (const unsigned int[]) { GSO_TEST_SIZE, 3 },
935b2be2abSAlexander Lobakin 		.nr_segs = 2,
945b2be2abSAlexander Lobakin 		.segs = (const unsigned int[]) { 2 * GSO_TEST_SIZE, 3 },
955b2be2abSAlexander Lobakin 	},
965b2be2abSAlexander Lobakin 	{
975b2be2abSAlexander Lobakin 		/* commit 89319d3801d1: frag_list on mss boundaries */
985b2be2abSAlexander Lobakin 		.id = GSO_TEST_FRAG_LIST,
995b2be2abSAlexander Lobakin 		.name = "frag_list",
1005b2be2abSAlexander Lobakin 		.linear_len = GSO_TEST_SIZE,
1015b2be2abSAlexander Lobakin 		.nr_frag_skbs = 2,
1025b2be2abSAlexander Lobakin 		.frag_skbs = (const unsigned int[]) { GSO_TEST_SIZE, GSO_TEST_SIZE },
1035b2be2abSAlexander Lobakin 		.nr_segs = 3,
1045b2be2abSAlexander Lobakin 		.segs = (const unsigned int[]) { GSO_TEST_SIZE, GSO_TEST_SIZE, GSO_TEST_SIZE },
1055b2be2abSAlexander Lobakin 	},
1065b2be2abSAlexander Lobakin 	{
1075b2be2abSAlexander Lobakin 		.id = GSO_TEST_FRAG_LIST_PURE,
1085b2be2abSAlexander Lobakin 		.name = "frag_list_pure",
1095b2be2abSAlexander Lobakin 		.nr_frag_skbs = 2,
1105b2be2abSAlexander Lobakin 		.frag_skbs = (const unsigned int[]) { GSO_TEST_SIZE, GSO_TEST_SIZE },
1115b2be2abSAlexander Lobakin 		.nr_segs = 2,
1125b2be2abSAlexander Lobakin 		.segs = (const unsigned int[]) { GSO_TEST_SIZE, GSO_TEST_SIZE },
1135b2be2abSAlexander Lobakin 	},
1145b2be2abSAlexander Lobakin 	{
1155b2be2abSAlexander Lobakin 		/* commit 43170c4e0ba7: GRO of frag_list trains */
1165b2be2abSAlexander Lobakin 		.id = GSO_TEST_FRAG_LIST_NON_UNIFORM,
1175b2be2abSAlexander Lobakin 		.name = "frag_list_non_uniform",
1185b2be2abSAlexander Lobakin 		.linear_len = GSO_TEST_SIZE,
1195b2be2abSAlexander Lobakin 		.nr_frag_skbs = 4,
1205b2be2abSAlexander Lobakin 		.frag_skbs = (const unsigned int[]) { GSO_TEST_SIZE, 1, GSO_TEST_SIZE, 2 },
1215b2be2abSAlexander Lobakin 		.nr_segs = 4,
1225b2be2abSAlexander Lobakin 		.segs = (const unsigned int[]) { GSO_TEST_SIZE, GSO_TEST_SIZE, GSO_TEST_SIZE, 3 },
1235b2be2abSAlexander Lobakin 	},
1245b2be2abSAlexander Lobakin 	{
1255b2be2abSAlexander Lobakin 		/* commit 3953c46c3ac7 ("sk_buff: allow segmenting based on frag sizes") and
1265b2be2abSAlexander Lobakin 		 * commit 90017accff61 ("sctp: Add GSO support")
1275b2be2abSAlexander Lobakin 		 *
1285b2be2abSAlexander Lobakin 		 * "there will be a cover skb with protocol headers and
1295b2be2abSAlexander Lobakin 		 *  children ones containing the actual segments"
1305b2be2abSAlexander Lobakin 		 */
1315b2be2abSAlexander Lobakin 		.id = GSO_TEST_GSO_BY_FRAGS,
1325b2be2abSAlexander Lobakin 		.name = "gso_by_frags",
1335b2be2abSAlexander Lobakin 		.nr_frag_skbs = 4,
1345b2be2abSAlexander Lobakin 		.frag_skbs = (const unsigned int[]) { 100, 200, 300, 400 },
1355b2be2abSAlexander Lobakin 		.nr_segs = 4,
1365b2be2abSAlexander Lobakin 		.segs = (const unsigned int[]) { 100, 200, 300, 400 },
1375b2be2abSAlexander Lobakin 	},
1385b2be2abSAlexander Lobakin };
1395b2be2abSAlexander Lobakin 
gso_test_case_to_desc(struct gso_test_case * t,char * desc)1405b2be2abSAlexander Lobakin static void gso_test_case_to_desc(struct gso_test_case *t, char *desc)
1415b2be2abSAlexander Lobakin {
1425b2be2abSAlexander Lobakin 	sprintf(desc, "%s", t->name);
1435b2be2abSAlexander Lobakin }
1445b2be2abSAlexander Lobakin 
1455b2be2abSAlexander Lobakin KUNIT_ARRAY_PARAM(gso_test, cases, gso_test_case_to_desc);
1465b2be2abSAlexander Lobakin 
gso_test_func(struct kunit * test)1475b2be2abSAlexander Lobakin static void gso_test_func(struct kunit *test)
1485b2be2abSAlexander Lobakin {
1495b2be2abSAlexander Lobakin 	const int shinfo_size = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
1505b2be2abSAlexander Lobakin 	struct sk_buff *skb, *segs, *cur, *next, *last;
1515b2be2abSAlexander Lobakin 	const struct gso_test_case *tcase;
1525b2be2abSAlexander Lobakin 	netdev_features_t features;
1535b2be2abSAlexander Lobakin 	struct page *page;
1545b2be2abSAlexander Lobakin 	int i;
1555b2be2abSAlexander Lobakin 
1565b2be2abSAlexander Lobakin 	tcase = test->param_value;
1575b2be2abSAlexander Lobakin 
1585b2be2abSAlexander Lobakin 	page = alloc_page(GFP_KERNEL);
1595b2be2abSAlexander Lobakin 	KUNIT_ASSERT_NOT_NULL(test, page);
1605b2be2abSAlexander Lobakin 	skb = build_skb(page_address(page), sizeof(hdr) + tcase->linear_len + shinfo_size);
1615b2be2abSAlexander Lobakin 	KUNIT_ASSERT_NOT_NULL(test, skb);
1625b2be2abSAlexander Lobakin 	__skb_put(skb, sizeof(hdr) + tcase->linear_len);
1635b2be2abSAlexander Lobakin 
1645b2be2abSAlexander Lobakin 	__init_skb(skb);
1655b2be2abSAlexander Lobakin 
1665b2be2abSAlexander Lobakin 	if (tcase->nr_frags) {
1675b2be2abSAlexander Lobakin 		unsigned int pg_off = 0;
1685b2be2abSAlexander Lobakin 
1695b2be2abSAlexander Lobakin 		page = alloc_page(GFP_KERNEL);
1705b2be2abSAlexander Lobakin 		KUNIT_ASSERT_NOT_NULL(test, page);
1715b2be2abSAlexander Lobakin 		page_ref_add(page, tcase->nr_frags - 1);
1725b2be2abSAlexander Lobakin 
1735b2be2abSAlexander Lobakin 		for (i = 0; i < tcase->nr_frags; i++) {
1745b2be2abSAlexander Lobakin 			skb_fill_page_desc(skb, i, page, pg_off, tcase->frags[i]);
1755b2be2abSAlexander Lobakin 			pg_off += tcase->frags[i];
1765b2be2abSAlexander Lobakin 		}
1775b2be2abSAlexander Lobakin 
1785b2be2abSAlexander Lobakin 		KUNIT_ASSERT_LE(test, pg_off, PAGE_SIZE);
1795b2be2abSAlexander Lobakin 
1805b2be2abSAlexander Lobakin 		skb->data_len = pg_off;
1815b2be2abSAlexander Lobakin 		skb->len += skb->data_len;
1825b2be2abSAlexander Lobakin 		skb->truesize += skb->data_len;
1835b2be2abSAlexander Lobakin 	}
1845b2be2abSAlexander Lobakin 
1855b2be2abSAlexander Lobakin 	if (tcase->frag_skbs) {
1865b2be2abSAlexander Lobakin 		unsigned int total_size = 0, total_true_size = 0;
1875b2be2abSAlexander Lobakin 		struct sk_buff *frag_skb, *prev = NULL;
1885b2be2abSAlexander Lobakin 
1895b2be2abSAlexander Lobakin 		for (i = 0; i < tcase->nr_frag_skbs; i++) {
1905b2be2abSAlexander Lobakin 			unsigned int frag_size;
1915b2be2abSAlexander Lobakin 
1925b2be2abSAlexander Lobakin 			page = alloc_page(GFP_KERNEL);
1935b2be2abSAlexander Lobakin 			KUNIT_ASSERT_NOT_NULL(test, page);
1945b2be2abSAlexander Lobakin 
1955b2be2abSAlexander Lobakin 			frag_size = tcase->frag_skbs[i];
1965b2be2abSAlexander Lobakin 			frag_skb = build_skb(page_address(page),
1975b2be2abSAlexander Lobakin 					     frag_size + shinfo_size);
1985b2be2abSAlexander Lobakin 			KUNIT_ASSERT_NOT_NULL(test, frag_skb);
1995b2be2abSAlexander Lobakin 			__skb_put(frag_skb, frag_size);
2005b2be2abSAlexander Lobakin 
2015b2be2abSAlexander Lobakin 			if (prev)
2025b2be2abSAlexander Lobakin 				prev->next = frag_skb;
2035b2be2abSAlexander Lobakin 			else
2045b2be2abSAlexander Lobakin 				skb_shinfo(skb)->frag_list = frag_skb;
2055b2be2abSAlexander Lobakin 			prev = frag_skb;
2065b2be2abSAlexander Lobakin 
2075b2be2abSAlexander Lobakin 			total_size += frag_size;
2085b2be2abSAlexander Lobakin 			total_true_size += frag_skb->truesize;
2095b2be2abSAlexander Lobakin 		}
2105b2be2abSAlexander Lobakin 
2115b2be2abSAlexander Lobakin 		skb->len += total_size;
2125b2be2abSAlexander Lobakin 		skb->data_len += total_size;
2135b2be2abSAlexander Lobakin 		skb->truesize += total_true_size;
2145b2be2abSAlexander Lobakin 
2155b2be2abSAlexander Lobakin 		if (tcase->id == GSO_TEST_GSO_BY_FRAGS)
2165b2be2abSAlexander Lobakin 			skb_shinfo(skb)->gso_size = GSO_BY_FRAGS;
2175b2be2abSAlexander Lobakin 	}
2185b2be2abSAlexander Lobakin 
2195b2be2abSAlexander Lobakin 	features = NETIF_F_SG | NETIF_F_HW_CSUM;
2205b2be2abSAlexander Lobakin 	if (tcase->id == GSO_TEST_GSO_PARTIAL)
2215b2be2abSAlexander Lobakin 		features |= NETIF_F_GSO_PARTIAL;
2225b2be2abSAlexander Lobakin 
2235b2be2abSAlexander Lobakin 	/* TODO: this should also work with SG,
2245b2be2abSAlexander Lobakin 	 * rather than hit BUG_ON(i >= nfrags)
2255b2be2abSAlexander Lobakin 	 */
2265b2be2abSAlexander Lobakin 	if (tcase->id == GSO_TEST_FRAG_LIST_NON_UNIFORM)
2275b2be2abSAlexander Lobakin 		features &= ~NETIF_F_SG;
2285b2be2abSAlexander Lobakin 
2295b2be2abSAlexander Lobakin 	segs = skb_segment(skb, features);
2305b2be2abSAlexander Lobakin 	if (IS_ERR(segs)) {
2315b2be2abSAlexander Lobakin 		KUNIT_FAIL(test, "segs error %pe", segs);
2325b2be2abSAlexander Lobakin 		goto free_gso_skb;
2335b2be2abSAlexander Lobakin 	} else if (!segs) {
2345b2be2abSAlexander Lobakin 		KUNIT_FAIL(test, "no segments");
2355b2be2abSAlexander Lobakin 		goto free_gso_skb;
2365b2be2abSAlexander Lobakin 	}
2375b2be2abSAlexander Lobakin 
2385b2be2abSAlexander Lobakin 	last = segs->prev;
2395b2be2abSAlexander Lobakin 	for (cur = segs, i = 0; cur; cur = next, i++) {
2405b2be2abSAlexander Lobakin 		next = cur->next;
2415b2be2abSAlexander Lobakin 
2425b2be2abSAlexander Lobakin 		KUNIT_ASSERT_EQ(test, cur->len, sizeof(hdr) + tcase->segs[i]);
2435b2be2abSAlexander Lobakin 
2445b2be2abSAlexander Lobakin 		/* segs have skb->data pointing to the mac header */
2455b2be2abSAlexander Lobakin 		KUNIT_ASSERT_PTR_EQ(test, skb_mac_header(cur), cur->data);
2465b2be2abSAlexander Lobakin 		KUNIT_ASSERT_PTR_EQ(test, skb_network_header(cur), cur->data + sizeof(hdr));
2475b2be2abSAlexander Lobakin 
2485b2be2abSAlexander Lobakin 		/* header was copied to all segs */
2495b2be2abSAlexander Lobakin 		KUNIT_ASSERT_EQ(test, memcmp(skb_mac_header(cur), hdr, sizeof(hdr)), 0);
2505b2be2abSAlexander Lobakin 
2515b2be2abSAlexander Lobakin 		/* last seg can be found through segs->prev pointer */
2525b2be2abSAlexander Lobakin 		if (!next)
2535b2be2abSAlexander Lobakin 			KUNIT_ASSERT_PTR_EQ(test, cur, last);
2545b2be2abSAlexander Lobakin 
2555b2be2abSAlexander Lobakin 		consume_skb(cur);
2565b2be2abSAlexander Lobakin 	}
2575b2be2abSAlexander Lobakin 
2585b2be2abSAlexander Lobakin 	KUNIT_ASSERT_EQ(test, i, tcase->nr_segs);
2595b2be2abSAlexander Lobakin 
2605b2be2abSAlexander Lobakin free_gso_skb:
2615b2be2abSAlexander Lobakin 	consume_skb(skb);
2625b2be2abSAlexander Lobakin }
2635b2be2abSAlexander Lobakin 
2645b2be2abSAlexander Lobakin /* IP tunnel flags */
2655b2be2abSAlexander Lobakin 
2665b2be2abSAlexander Lobakin #include <net/ip_tunnels.h>
2675b2be2abSAlexander Lobakin 
2685b2be2abSAlexander Lobakin struct ip_tunnel_flags_test {
2695b2be2abSAlexander Lobakin 	const char	*name;
2705b2be2abSAlexander Lobakin 
2715b2be2abSAlexander Lobakin 	const u16	*src_bits;
2725b2be2abSAlexander Lobakin 	const u16	*exp_bits;
2735b2be2abSAlexander Lobakin 	u8		src_num;
2745b2be2abSAlexander Lobakin 	u8		exp_num;
2755b2be2abSAlexander Lobakin 
2765b2be2abSAlexander Lobakin 	__be16		exp_val;
2775b2be2abSAlexander Lobakin 	bool		exp_comp;
2785b2be2abSAlexander Lobakin };
2795b2be2abSAlexander Lobakin 
2805b2be2abSAlexander Lobakin #define IP_TUNNEL_FLAGS_TEST(n, src, comp, eval, exp) {	\
2815b2be2abSAlexander Lobakin 	.name		= (n),				\
2825b2be2abSAlexander Lobakin 	.src_bits	= (src),			\
2835b2be2abSAlexander Lobakin 	.src_num	= ARRAY_SIZE(src),		\
2845b2be2abSAlexander Lobakin 	.exp_comp	= (comp),			\
2855b2be2abSAlexander Lobakin 	.exp_val	= (eval),			\
2865b2be2abSAlexander Lobakin 	.exp_bits	= (exp),			\
2875b2be2abSAlexander Lobakin 	.exp_num	= ARRAY_SIZE(exp),		\
2885b2be2abSAlexander Lobakin }
2895b2be2abSAlexander Lobakin 
2905b2be2abSAlexander Lobakin /* These are __be16-compatible and can be compared as is */
2915b2be2abSAlexander Lobakin static const u16 ip_tunnel_flags_1[] = {
2925b2be2abSAlexander Lobakin 	IP_TUNNEL_KEY_BIT,
2935b2be2abSAlexander Lobakin 	IP_TUNNEL_STRICT_BIT,
2945b2be2abSAlexander Lobakin 	IP_TUNNEL_ERSPAN_OPT_BIT,
2955b2be2abSAlexander Lobakin };
2965b2be2abSAlexander Lobakin 
2975b2be2abSAlexander Lobakin /* Due to the previous flags design limitation, setting either
2985b2be2abSAlexander Lobakin  * ``IP_TUNNEL_CSUM_BIT`` (on Big Endian) or ``IP_TUNNEL_DONT_FRAGMENT_BIT``
2995b2be2abSAlexander Lobakin  * (on Little) also sets VTI/ISATAP bit. In the bitmap implementation, they
3005b2be2abSAlexander Lobakin  * correspond to ``BIT(16)``, which is bigger than ``U16_MAX``, but still is
3015b2be2abSAlexander Lobakin  * backward-compatible.
3025b2be2abSAlexander Lobakin  */
3035b2be2abSAlexander Lobakin #ifdef __LITTLE_ENDIAN
3045b2be2abSAlexander Lobakin #define IP_TUNNEL_CONFLICT_BIT	IP_TUNNEL_DONT_FRAGMENT_BIT
3055b2be2abSAlexander Lobakin #else
3065b2be2abSAlexander Lobakin #define IP_TUNNEL_CONFLICT_BIT	IP_TUNNEL_CSUM_BIT
3075b2be2abSAlexander Lobakin #endif
3085b2be2abSAlexander Lobakin 
3095b2be2abSAlexander Lobakin static const u16 ip_tunnel_flags_2_src[] = {
3105b2be2abSAlexander Lobakin 	IP_TUNNEL_CONFLICT_BIT,
3115b2be2abSAlexander Lobakin };
3125b2be2abSAlexander Lobakin 
3135b2be2abSAlexander Lobakin static const u16 ip_tunnel_flags_2_exp[] = {
3145b2be2abSAlexander Lobakin 	IP_TUNNEL_CONFLICT_BIT,
3155b2be2abSAlexander Lobakin 	IP_TUNNEL_SIT_ISATAP_BIT,
3165b2be2abSAlexander Lobakin };
3175b2be2abSAlexander Lobakin 
3185b2be2abSAlexander Lobakin /* Bits 17 and higher are not compatible with __be16 flags */
3195b2be2abSAlexander Lobakin static const u16 ip_tunnel_flags_3_src[] = {
3205b2be2abSAlexander Lobakin 	IP_TUNNEL_VXLAN_OPT_BIT,
3215b2be2abSAlexander Lobakin 	17,
3225b2be2abSAlexander Lobakin 	18,
3235b2be2abSAlexander Lobakin 	20,
3245b2be2abSAlexander Lobakin };
3255b2be2abSAlexander Lobakin 
3265b2be2abSAlexander Lobakin static const u16 ip_tunnel_flags_3_exp[] = {
3275b2be2abSAlexander Lobakin 	IP_TUNNEL_VXLAN_OPT_BIT,
3285b2be2abSAlexander Lobakin };
3295b2be2abSAlexander Lobakin 
3305b2be2abSAlexander Lobakin static const struct ip_tunnel_flags_test ip_tunnel_flags_test[] = {
3315b2be2abSAlexander Lobakin 	IP_TUNNEL_FLAGS_TEST("compat", ip_tunnel_flags_1, true,
3325b2be2abSAlexander Lobakin 			     cpu_to_be16(BIT(IP_TUNNEL_KEY_BIT) |
3335b2be2abSAlexander Lobakin 					 BIT(IP_TUNNEL_STRICT_BIT) |
3345b2be2abSAlexander Lobakin 					 BIT(IP_TUNNEL_ERSPAN_OPT_BIT)),
3355b2be2abSAlexander Lobakin 			     ip_tunnel_flags_1),
3365b2be2abSAlexander Lobakin 	IP_TUNNEL_FLAGS_TEST("conflict", ip_tunnel_flags_2_src, true,
3375b2be2abSAlexander Lobakin 			     VTI_ISVTI, ip_tunnel_flags_2_exp),
338*6dd514f4SMichal Swiatkowski 	IP_TUNNEL_FLAGS_TEST("new", ip_tunnel_flags_3_src, false,
339*6dd514f4SMichal Swiatkowski 			     cpu_to_be16(BIT(IP_TUNNEL_VXLAN_OPT_BIT)),
3405b2be2abSAlexander Lobakin 			     ip_tunnel_flags_3_exp),
3415b2be2abSAlexander Lobakin };
3425b2be2abSAlexander Lobakin 
3435b2be2abSAlexander Lobakin static void
ip_tunnel_flags_test_case_to_desc(const struct ip_tunnel_flags_test * t,char * desc)3445b2be2abSAlexander Lobakin ip_tunnel_flags_test_case_to_desc(const struct ip_tunnel_flags_test *t,
3455b2be2abSAlexander Lobakin 				  char *desc)
3465b2be2abSAlexander Lobakin {
3475b2be2abSAlexander Lobakin 	strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
3485b2be2abSAlexander Lobakin }
3495b2be2abSAlexander Lobakin KUNIT_ARRAY_PARAM(ip_tunnel_flags_test, ip_tunnel_flags_test,
3505b2be2abSAlexander Lobakin 		  ip_tunnel_flags_test_case_to_desc);
3515b2be2abSAlexander Lobakin 
ip_tunnel_flags_test_run(struct kunit * test)3525b2be2abSAlexander Lobakin static void ip_tunnel_flags_test_run(struct kunit *test)
3535b2be2abSAlexander Lobakin {
3545b2be2abSAlexander Lobakin 	const struct ip_tunnel_flags_test *t = test->param_value;
3555b2be2abSAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(src) = { };
3565b2be2abSAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(exp) = { };
3575b2be2abSAlexander Lobakin 	IP_TUNNEL_DECLARE_FLAGS(out);
3585b2be2abSAlexander Lobakin 
3595b2be2abSAlexander Lobakin 	for (u32 j = 0; j < t->src_num; j++)
3605b2be2abSAlexander Lobakin 		__set_bit(t->src_bits[j], src);
3615b2be2abSAlexander Lobakin 	for (u32 j = 0; j < t->exp_num; j++)
3625b2be2abSAlexander Lobakin 		__set_bit(t->exp_bits[j], exp);
3635b2be2abSAlexander Lobakin 
3645b2be2abSAlexander Lobakin 	KUNIT_ASSERT_EQ(test, t->exp_comp,
3655b2be2abSAlexander Lobakin 			ip_tunnel_flags_is_be16_compat(src));
3665b2be2abSAlexander Lobakin 	KUNIT_ASSERT_EQ(test, (__force u16)t->exp_val,
3675b2be2abSAlexander Lobakin 			(__force u16)ip_tunnel_flags_to_be16(src));
3685b2be2abSAlexander Lobakin 
3695b2be2abSAlexander Lobakin 	ip_tunnel_flags_from_be16(out, t->exp_val);
3705b2be2abSAlexander Lobakin 	KUNIT_ASSERT_TRUE(test, __ipt_flag_op(bitmap_equal, exp, out));
3715b2be2abSAlexander Lobakin }
3725b2be2abSAlexander Lobakin 
3735b2be2abSAlexander Lobakin static struct kunit_case net_test_cases[] = {
3745b2be2abSAlexander Lobakin 	KUNIT_CASE_PARAM(gso_test_func, gso_test_gen_params),
3755b2be2abSAlexander Lobakin 	KUNIT_CASE_PARAM(ip_tunnel_flags_test_run,
3765b2be2abSAlexander Lobakin 			 ip_tunnel_flags_test_gen_params),
3775b2be2abSAlexander Lobakin 	{ },
3785b2be2abSAlexander Lobakin };
3795b2be2abSAlexander Lobakin 
3805b2be2abSAlexander Lobakin static struct kunit_suite net_test_suite = {
3815b2be2abSAlexander Lobakin 	.name		= "net_core",
3825b2be2abSAlexander Lobakin 	.test_cases	= net_test_cases,
3835b2be2abSAlexander Lobakin };
3845b2be2abSAlexander Lobakin kunit_test_suite(net_test_suite);
3855b2be2abSAlexander Lobakin 
3865b2be2abSAlexander Lobakin MODULE_DESCRIPTION("KUnit tests for networking core");
3875b2be2abSAlexander Lobakin MODULE_LICENSE("GPL");
388