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