xref: /linux/net/mac80211/tests/s1g_tim.c (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1*1860b1a8SLachlan Hodges // SPDX-License-Identifier: GPL-2.0-only
2*1860b1a8SLachlan Hodges /*
3*1860b1a8SLachlan Hodges  * KUnit tests for S1G TIM PVB decoding. This test suite covers
4*1860b1a8SLachlan Hodges  * IEEE80211-2024 Annex L figures 8, 9, 10, 12, 13, 14. ADE mode
5*1860b1a8SLachlan Hodges  * is not covered as it is an optional encoding format and is not
6*1860b1a8SLachlan Hodges  * currently supported by mac80211.
7*1860b1a8SLachlan Hodges  *
8*1860b1a8SLachlan Hodges  * Copyright (C) 2025 Morse Micro
9*1860b1a8SLachlan Hodges  */
10*1860b1a8SLachlan Hodges #include <linux/ieee80211.h>
11*1860b1a8SLachlan Hodges #include <kunit/test.h>
12*1860b1a8SLachlan Hodges #include <kunit/test-bug.h>
13*1860b1a8SLachlan Hodges 
14*1860b1a8SLachlan Hodges #define MAX_AID 128
15*1860b1a8SLachlan Hodges 
16*1860b1a8SLachlan Hodges #define BC(enc_mode, inverse, blk_off)                          \
17*1860b1a8SLachlan Hodges 	((((blk_off) & 0x1f) << 3) | ((inverse) ? BIT(2) : 0) | \
18*1860b1a8SLachlan Hodges 	 ((enc_mode) & 0x3))
19*1860b1a8SLachlan Hodges 
20*1860b1a8SLachlan Hodges static void byte_to_bitstr(u8 v, char *out)
21*1860b1a8SLachlan Hodges {
22*1860b1a8SLachlan Hodges 	for (int b = 7; b >= 0; b--)
23*1860b1a8SLachlan Hodges 		*out++ = (v & BIT(b)) ? '1' : '0';
24*1860b1a8SLachlan Hodges 	*out = '\0';
25*1860b1a8SLachlan Hodges }
26*1860b1a8SLachlan Hodges 
27*1860b1a8SLachlan Hodges static void dump_tim_bits(struct kunit *test,
28*1860b1a8SLachlan Hodges 			  const struct ieee80211_tim_ie *tim, u8 tim_len)
29*1860b1a8SLachlan Hodges {
30*1860b1a8SLachlan Hodges 	const u8 *ptr = tim->virtual_map;
31*1860b1a8SLachlan Hodges 	const u8 *end = (const u8 *)tim + tim_len;
32*1860b1a8SLachlan Hodges 	unsigned int oct = 1;
33*1860b1a8SLachlan Hodges 	unsigned int blk = 0;
34*1860b1a8SLachlan Hodges 	char bits[9];
35*1860b1a8SLachlan Hodges 
36*1860b1a8SLachlan Hodges 	while (ptr < end) {
37*1860b1a8SLachlan Hodges 		u8 ctrl = *ptr++;
38*1860b1a8SLachlan Hodges 		u8 mode = ctrl & 0x03;
39*1860b1a8SLachlan Hodges 		bool inverse = ctrl & BIT(2);
40*1860b1a8SLachlan Hodges 		u8 blk_off = ctrl >> 3;
41*1860b1a8SLachlan Hodges 
42*1860b1a8SLachlan Hodges 		kunit_info(
43*1860b1a8SLachlan Hodges 			test, "Block %u (ENC=%s, blk_off=%u, inverse=%u)", blk,
44*1860b1a8SLachlan Hodges 			(mode == IEEE80211_S1G_TIM_ENC_MODE_BLOCK)  ? "BLOCK" :
45*1860b1a8SLachlan Hodges 			(mode == IEEE80211_S1G_TIM_ENC_MODE_SINGLE) ? "SINGLE" :
46*1860b1a8SLachlan Hodges 								      "OLB",
47*1860b1a8SLachlan Hodges 			blk_off, inverse);
48*1860b1a8SLachlan Hodges 
49*1860b1a8SLachlan Hodges 		byte_to_bitstr(ctrl, bits);
50*1860b1a8SLachlan Hodges 		kunit_info(test, "  octet %2u (ctrl)    : %s (0x%02x)", oct,
51*1860b1a8SLachlan Hodges 			   bits, ctrl);
52*1860b1a8SLachlan Hodges 		++oct;
53*1860b1a8SLachlan Hodges 
54*1860b1a8SLachlan Hodges 		switch (mode) {
55*1860b1a8SLachlan Hodges 		case IEEE80211_S1G_TIM_ENC_MODE_BLOCK: {
56*1860b1a8SLachlan Hodges 			u8 blkmap = *ptr++;
57*1860b1a8SLachlan Hodges 
58*1860b1a8SLachlan Hodges 			byte_to_bitstr(blkmap, bits);
59*1860b1a8SLachlan Hodges 			kunit_info(test, "  octet %2u (blk-map) : %s (0x%02x)",
60*1860b1a8SLachlan Hodges 				   oct, bits, blkmap);
61*1860b1a8SLachlan Hodges 			++oct;
62*1860b1a8SLachlan Hodges 
63*1860b1a8SLachlan Hodges 			for (u8 sb = 0; sb < 8; sb++) {
64*1860b1a8SLachlan Hodges 				if (!(blkmap & BIT(sb)))
65*1860b1a8SLachlan Hodges 					continue;
66*1860b1a8SLachlan Hodges 				u8 sub = *ptr++;
67*1860b1a8SLachlan Hodges 
68*1860b1a8SLachlan Hodges 				byte_to_bitstr(sub, bits);
69*1860b1a8SLachlan Hodges 				kunit_info(
70*1860b1a8SLachlan Hodges 					test,
71*1860b1a8SLachlan Hodges 					"  octet %2u (SB %2u)   : %s (0x%02x)",
72*1860b1a8SLachlan Hodges 					oct, sb, bits, sub);
73*1860b1a8SLachlan Hodges 				++oct;
74*1860b1a8SLachlan Hodges 			}
75*1860b1a8SLachlan Hodges 			break;
76*1860b1a8SLachlan Hodges 		}
77*1860b1a8SLachlan Hodges 		case IEEE80211_S1G_TIM_ENC_MODE_SINGLE: {
78*1860b1a8SLachlan Hodges 			u8 single = *ptr++;
79*1860b1a8SLachlan Hodges 
80*1860b1a8SLachlan Hodges 			byte_to_bitstr(single, bits);
81*1860b1a8SLachlan Hodges 			kunit_info(test, "  octet %2u (single)  : %s (0x%02x)",
82*1860b1a8SLachlan Hodges 				   oct, bits, single);
83*1860b1a8SLachlan Hodges 			++oct;
84*1860b1a8SLachlan Hodges 			break;
85*1860b1a8SLachlan Hodges 		}
86*1860b1a8SLachlan Hodges 		case IEEE80211_S1G_TIM_ENC_MODE_OLB: {
87*1860b1a8SLachlan Hodges 			u8 len = *ptr++;
88*1860b1a8SLachlan Hodges 
89*1860b1a8SLachlan Hodges 			byte_to_bitstr(len, bits);
90*1860b1a8SLachlan Hodges 			kunit_info(test, "  octet %2u (len=%2u)  : %s (0x%02x)",
91*1860b1a8SLachlan Hodges 				   oct, len, bits, len);
92*1860b1a8SLachlan Hodges 			++oct;
93*1860b1a8SLachlan Hodges 
94*1860b1a8SLachlan Hodges 			for (u8 i = 0; i < len && ptr < end; i++) {
95*1860b1a8SLachlan Hodges 				u8 sub = *ptr++;
96*1860b1a8SLachlan Hodges 
97*1860b1a8SLachlan Hodges 				byte_to_bitstr(sub, bits);
98*1860b1a8SLachlan Hodges 				kunit_info(
99*1860b1a8SLachlan Hodges 					test,
100*1860b1a8SLachlan Hodges 					"  octet %2u (SB %2u)   : %s (0x%02x)",
101*1860b1a8SLachlan Hodges 					oct, i, bits, sub);
102*1860b1a8SLachlan Hodges 				++oct;
103*1860b1a8SLachlan Hodges 			}
104*1860b1a8SLachlan Hodges 			break;
105*1860b1a8SLachlan Hodges 		}
106*1860b1a8SLachlan Hodges 		default:
107*1860b1a8SLachlan Hodges 			kunit_info(test, "  ** unknown encoding 0x%x **", mode);
108*1860b1a8SLachlan Hodges 			return;
109*1860b1a8SLachlan Hodges 		}
110*1860b1a8SLachlan Hodges 		blk++;
111*1860b1a8SLachlan Hodges 	}
112*1860b1a8SLachlan Hodges }
113*1860b1a8SLachlan Hodges 
114*1860b1a8SLachlan Hodges static void tim_push(u8 **p, u8 v)
115*1860b1a8SLachlan Hodges {
116*1860b1a8SLachlan Hodges 	*(*p)++ = v;
117*1860b1a8SLachlan Hodges }
118*1860b1a8SLachlan Hodges 
119*1860b1a8SLachlan Hodges static void tim_begin(struct ieee80211_tim_ie *tim, u8 **p)
120*1860b1a8SLachlan Hodges {
121*1860b1a8SLachlan Hodges 	tim->dtim_count = 0;
122*1860b1a8SLachlan Hodges 	tim->dtim_period = 1;
123*1860b1a8SLachlan Hodges 	tim->bitmap_ctrl = 0;
124*1860b1a8SLachlan Hodges 	*p = tim->virtual_map;
125*1860b1a8SLachlan Hodges }
126*1860b1a8SLachlan Hodges 
127*1860b1a8SLachlan Hodges static u8 tim_end(struct ieee80211_tim_ie *tim, u8 *tail)
128*1860b1a8SLachlan Hodges {
129*1860b1a8SLachlan Hodges 	return tail - (u8 *)tim;
130*1860b1a8SLachlan Hodges }
131*1860b1a8SLachlan Hodges 
132*1860b1a8SLachlan Hodges static void pvb_add_block_bitmap(u8 **p, u8 blk_off, bool inverse, u8 blk_bmap,
133*1860b1a8SLachlan Hodges 				 const u8 *subblocks)
134*1860b1a8SLachlan Hodges {
135*1860b1a8SLachlan Hodges 	u8 enc = IEEE80211_S1G_TIM_ENC_MODE_BLOCK;
136*1860b1a8SLachlan Hodges 	u8 n = hweight8(blk_bmap);
137*1860b1a8SLachlan Hodges 
138*1860b1a8SLachlan Hodges 	tim_push(p, BC(enc, inverse, blk_off));
139*1860b1a8SLachlan Hodges 	tim_push(p, blk_bmap);
140*1860b1a8SLachlan Hodges 
141*1860b1a8SLachlan Hodges 	for (u8 i = 0; i < n; i++)
142*1860b1a8SLachlan Hodges 		tim_push(p, subblocks[i]);
143*1860b1a8SLachlan Hodges }
144*1860b1a8SLachlan Hodges 
145*1860b1a8SLachlan Hodges static void pvb_add_single_aid(u8 **p, u8 blk_off, bool inverse, u8 single6)
146*1860b1a8SLachlan Hodges {
147*1860b1a8SLachlan Hodges 	u8 enc = IEEE80211_S1G_TIM_ENC_MODE_SINGLE;
148*1860b1a8SLachlan Hodges 
149*1860b1a8SLachlan Hodges 	tim_push(p, BC(enc, inverse, blk_off));
150*1860b1a8SLachlan Hodges 	tim_push(p, single6 & GENMASK(5, 0));
151*1860b1a8SLachlan Hodges }
152*1860b1a8SLachlan Hodges 
153*1860b1a8SLachlan Hodges static void pvb_add_olb(u8 **p, u8 blk_off, bool inverse, const u8 *subblocks,
154*1860b1a8SLachlan Hodges 			u8 len)
155*1860b1a8SLachlan Hodges {
156*1860b1a8SLachlan Hodges 	u8 enc = IEEE80211_S1G_TIM_ENC_MODE_OLB;
157*1860b1a8SLachlan Hodges 
158*1860b1a8SLachlan Hodges 	tim_push(p, BC(enc, inverse, blk_off));
159*1860b1a8SLachlan Hodges 	tim_push(p, len);
160*1860b1a8SLachlan Hodges 	for (u8 i = 0; i < len; i++)
161*1860b1a8SLachlan Hodges 		tim_push(p, subblocks[i]);
162*1860b1a8SLachlan Hodges }
163*1860b1a8SLachlan Hodges 
164*1860b1a8SLachlan Hodges static void check_all_aids(struct kunit *test,
165*1860b1a8SLachlan Hodges 			   const struct ieee80211_tim_ie *tim, u8 tim_len,
166*1860b1a8SLachlan Hodges 			   const unsigned long *expected)
167*1860b1a8SLachlan Hodges {
168*1860b1a8SLachlan Hodges 	for (u16 aid = 1; aid <= MAX_AID; aid++) {
169*1860b1a8SLachlan Hodges 		bool want = test_bit(aid, expected);
170*1860b1a8SLachlan Hodges 		bool got = ieee80211_s1g_check_tim(tim, tim_len, aid);
171*1860b1a8SLachlan Hodges 
172*1860b1a8SLachlan Hodges 		KUNIT_ASSERT_EQ_MSG(test, got, want,
173*1860b1a8SLachlan Hodges 				    "AID %u mismatch (got=%d want=%d)", aid,
174*1860b1a8SLachlan Hodges 				    got, want);
175*1860b1a8SLachlan Hodges 	}
176*1860b1a8SLachlan Hodges }
177*1860b1a8SLachlan Hodges 
178*1860b1a8SLachlan Hodges static void fill_bitmap(unsigned long *bm, const u16 *list, size_t n)
179*1860b1a8SLachlan Hodges {
180*1860b1a8SLachlan Hodges 	size_t i;
181*1860b1a8SLachlan Hodges 
182*1860b1a8SLachlan Hodges 	bitmap_zero(bm, MAX_AID + 1);
183*1860b1a8SLachlan Hodges 	for (i = 0; i < n; i++)
184*1860b1a8SLachlan Hodges 		__set_bit(list[i], bm);
185*1860b1a8SLachlan Hodges }
186*1860b1a8SLachlan Hodges 
187*1860b1a8SLachlan Hodges static void fill_bitmap_inverse(unsigned long *bm, u16 max_aid,
188*1860b1a8SLachlan Hodges 				const u16 *except, size_t n_except)
189*1860b1a8SLachlan Hodges {
190*1860b1a8SLachlan Hodges 	bitmap_zero(bm, MAX_AID + 1);
191*1860b1a8SLachlan Hodges 	for (u16 aid = 1; aid <= max_aid; aid++)
192*1860b1a8SLachlan Hodges 		__set_bit(aid, bm);
193*1860b1a8SLachlan Hodges 
194*1860b1a8SLachlan Hodges 	for (size_t i = 0; i < n_except; i++)
195*1860b1a8SLachlan Hodges 		if (except[i] <= max_aid)
196*1860b1a8SLachlan Hodges 			__clear_bit(except[i], bm);
197*1860b1a8SLachlan Hodges }
198*1860b1a8SLachlan Hodges 
199*1860b1a8SLachlan Hodges static void s1g_tim_block_test(struct kunit *test)
200*1860b1a8SLachlan Hodges {
201*1860b1a8SLachlan Hodges 	u8 buf[256] = {};
202*1860b1a8SLachlan Hodges 	struct ieee80211_tim_ie *tim = (void *)buf;
203*1860b1a8SLachlan Hodges 	u8 *p, tim_len;
204*1860b1a8SLachlan Hodges 	static const u8 subblocks[] = {
205*1860b1a8SLachlan Hodges 		0x42, /* SB m=0: AIDs 1,6 */
206*1860b1a8SLachlan Hodges 		0xA0, /* SB m=2: AIDs 21,23 */
207*1860b1a8SLachlan Hodges 	};
208*1860b1a8SLachlan Hodges 	u8 blk_bmap = 0x05; /* bits 0 and 2 set */
209*1860b1a8SLachlan Hodges 	bool inverse = false;
210*1860b1a8SLachlan Hodges 	static const u16 set_list[] = { 1, 6, 21, 23 };
211*1860b1a8SLachlan Hodges 	DECLARE_BITMAP(exp, MAX_AID + 1);
212*1860b1a8SLachlan Hodges 
213*1860b1a8SLachlan Hodges 	tim_begin(tim, &p);
214*1860b1a8SLachlan Hodges 	pvb_add_block_bitmap(&p, 0, inverse, blk_bmap, subblocks);
215*1860b1a8SLachlan Hodges 	tim_len = tim_end(tim, p);
216*1860b1a8SLachlan Hodges 
217*1860b1a8SLachlan Hodges 	fill_bitmap(exp, set_list, ARRAY_SIZE(set_list));
218*1860b1a8SLachlan Hodges 
219*1860b1a8SLachlan Hodges 	dump_tim_bits(test, tim, tim_len);
220*1860b1a8SLachlan Hodges 	check_all_aids(test, tim, tim_len, exp);
221*1860b1a8SLachlan Hodges }
222*1860b1a8SLachlan Hodges 
223*1860b1a8SLachlan Hodges static void s1g_tim_single_test(struct kunit *test)
224*1860b1a8SLachlan Hodges {
225*1860b1a8SLachlan Hodges 	u8 buf[256] = {};
226*1860b1a8SLachlan Hodges 	struct ieee80211_tim_ie *tim = (void *)buf;
227*1860b1a8SLachlan Hodges 	u8 *p, tim_len;
228*1860b1a8SLachlan Hodges 	bool inverse = false;
229*1860b1a8SLachlan Hodges 	u8 blk_off = 0;
230*1860b1a8SLachlan Hodges 	u8 single6 = 0x1f; /* 31 */
231*1860b1a8SLachlan Hodges 	static const u16 set_list[] = { 31 };
232*1860b1a8SLachlan Hodges 	DECLARE_BITMAP(exp, MAX_AID + 1);
233*1860b1a8SLachlan Hodges 
234*1860b1a8SLachlan Hodges 	tim_begin(tim, &p);
235*1860b1a8SLachlan Hodges 	pvb_add_single_aid(&p, blk_off, inverse, single6);
236*1860b1a8SLachlan Hodges 	tim_len = tim_end(tim, p);
237*1860b1a8SLachlan Hodges 
238*1860b1a8SLachlan Hodges 	fill_bitmap(exp, set_list, ARRAY_SIZE(set_list));
239*1860b1a8SLachlan Hodges 
240*1860b1a8SLachlan Hodges 	dump_tim_bits(test, tim, tim_len);
241*1860b1a8SLachlan Hodges 	check_all_aids(test, tim, tim_len, exp);
242*1860b1a8SLachlan Hodges }
243*1860b1a8SLachlan Hodges 
244*1860b1a8SLachlan Hodges static void s1g_tim_olb_test(struct kunit *test)
245*1860b1a8SLachlan Hodges {
246*1860b1a8SLachlan Hodges 	u8 buf[256] = {};
247*1860b1a8SLachlan Hodges 	struct ieee80211_tim_ie *tim = (void *)buf;
248*1860b1a8SLachlan Hodges 	u8 *p, tim_len;
249*1860b1a8SLachlan Hodges 	bool inverse = false;
250*1860b1a8SLachlan Hodges 	u8 blk_off = 0;
251*1860b1a8SLachlan Hodges 	static const u16 set_list[] = { 1,  6,	13, 15, 17, 22, 29, 31, 33,
252*1860b1a8SLachlan Hodges 					38, 45, 47, 49, 54, 61, 63, 65, 70 };
253*1860b1a8SLachlan Hodges 	static const u8 subblocks[] = { 0x42, 0xA0, 0x42, 0xA0, 0x42,
254*1860b1a8SLachlan Hodges 					0xA0, 0x42, 0xA0, 0x42 };
255*1860b1a8SLachlan Hodges 	u8 len = ARRAY_SIZE(subblocks);
256*1860b1a8SLachlan Hodges 	DECLARE_BITMAP(exp, MAX_AID + 1);
257*1860b1a8SLachlan Hodges 
258*1860b1a8SLachlan Hodges 	tim_begin(tim, &p);
259*1860b1a8SLachlan Hodges 	pvb_add_olb(&p, blk_off, inverse, subblocks, len);
260*1860b1a8SLachlan Hodges 	tim_len = tim_end(tim, p);
261*1860b1a8SLachlan Hodges 
262*1860b1a8SLachlan Hodges 	fill_bitmap(exp, set_list, ARRAY_SIZE(set_list));
263*1860b1a8SLachlan Hodges 
264*1860b1a8SLachlan Hodges 	dump_tim_bits(test, tim, tim_len);
265*1860b1a8SLachlan Hodges 	check_all_aids(test, tim, tim_len, exp);
266*1860b1a8SLachlan Hodges }
267*1860b1a8SLachlan Hodges 
268*1860b1a8SLachlan Hodges static void s1g_tim_inverse_block_test(struct kunit *test)
269*1860b1a8SLachlan Hodges {
270*1860b1a8SLachlan Hodges 	u8 buf[256] = {};
271*1860b1a8SLachlan Hodges 	struct ieee80211_tim_ie *tim = (void *)buf;
272*1860b1a8SLachlan Hodges 	u8 *p, tim_len;
273*1860b1a8SLachlan Hodges 	/* Same sub-block content as Figure L-8, but inverse = true */
274*1860b1a8SLachlan Hodges 	static const u8 subblocks[] = {
275*1860b1a8SLachlan Hodges 		0x42, /* SB m=0: AIDs 1,6 */
276*1860b1a8SLachlan Hodges 		0xA0, /* SB m=2: AIDs 21,23 */
277*1860b1a8SLachlan Hodges 	};
278*1860b1a8SLachlan Hodges 	u8 blk_bmap = 0x05;
279*1860b1a8SLachlan Hodges 	bool inverse = true;
280*1860b1a8SLachlan Hodges 	/*  All AIDs except 1,6,21,23 are set */
281*1860b1a8SLachlan Hodges 	static const u16 except[] = { 1, 6, 21, 23 };
282*1860b1a8SLachlan Hodges 	DECLARE_BITMAP(exp, MAX_AID + 1);
283*1860b1a8SLachlan Hodges 
284*1860b1a8SLachlan Hodges 	tim_begin(tim, &p);
285*1860b1a8SLachlan Hodges 	pvb_add_block_bitmap(&p, 0, inverse, blk_bmap, subblocks);
286*1860b1a8SLachlan Hodges 	tim_len = tim_end(tim, p);
287*1860b1a8SLachlan Hodges 
288*1860b1a8SLachlan Hodges 	fill_bitmap_inverse(exp, 63, except, ARRAY_SIZE(except));
289*1860b1a8SLachlan Hodges 
290*1860b1a8SLachlan Hodges 	dump_tim_bits(test, tim, tim_len);
291*1860b1a8SLachlan Hodges 	check_all_aids(test, tim, tim_len, exp);
292*1860b1a8SLachlan Hodges }
293*1860b1a8SLachlan Hodges 
294*1860b1a8SLachlan Hodges static void s1g_tim_inverse_single_test(struct kunit *test)
295*1860b1a8SLachlan Hodges {
296*1860b1a8SLachlan Hodges 	u8 buf[256] = {};
297*1860b1a8SLachlan Hodges 	struct ieee80211_tim_ie *tim = (void *)buf;
298*1860b1a8SLachlan Hodges 	u8 *p, tim_len;
299*1860b1a8SLachlan Hodges 	bool inverse = true;
300*1860b1a8SLachlan Hodges 	u8 blk_off = 0;
301*1860b1a8SLachlan Hodges 	u8 single6 = 0x1f; /* 31 */
302*1860b1a8SLachlan Hodges 	/*  All AIDs except 31 are set */
303*1860b1a8SLachlan Hodges 	static const u16 except[] = { 31 };
304*1860b1a8SLachlan Hodges 	DECLARE_BITMAP(exp, MAX_AID + 1);
305*1860b1a8SLachlan Hodges 
306*1860b1a8SLachlan Hodges 	tim_begin(tim, &p);
307*1860b1a8SLachlan Hodges 	pvb_add_single_aid(&p, blk_off, inverse, single6);
308*1860b1a8SLachlan Hodges 	tim_len = tim_end(tim, p);
309*1860b1a8SLachlan Hodges 
310*1860b1a8SLachlan Hodges 	fill_bitmap_inverse(exp, 63, except, ARRAY_SIZE(except));
311*1860b1a8SLachlan Hodges 
312*1860b1a8SLachlan Hodges 	dump_tim_bits(test, tim, tim_len);
313*1860b1a8SLachlan Hodges 	check_all_aids(test, tim, tim_len, exp);
314*1860b1a8SLachlan Hodges }
315*1860b1a8SLachlan Hodges 
316*1860b1a8SLachlan Hodges static void s1g_tim_inverse_olb_test(struct kunit *test)
317*1860b1a8SLachlan Hodges {
318*1860b1a8SLachlan Hodges 	u8 buf[256] = {};
319*1860b1a8SLachlan Hodges 	struct ieee80211_tim_ie *tim = (void *)buf;
320*1860b1a8SLachlan Hodges 	u8 *p, tim_len;
321*1860b1a8SLachlan Hodges 	bool inverse = true;
322*1860b1a8SLachlan Hodges 	u8 blk_off = 0, len;
323*1860b1a8SLachlan Hodges 	/*  All AIDs except the list below are set */
324*1860b1a8SLachlan Hodges 	static const u16 except[] = { 1,  6,  13, 15, 17, 22, 29, 31, 33,
325*1860b1a8SLachlan Hodges 				      38, 45, 47, 49, 54, 61, 63, 65, 70 };
326*1860b1a8SLachlan Hodges 	static const u8 subblocks[] = { 0x42, 0xA0, 0x42, 0xA0, 0x42,
327*1860b1a8SLachlan Hodges 					0xA0, 0x42, 0xA0, 0x42 };
328*1860b1a8SLachlan Hodges 	len = ARRAY_SIZE(subblocks);
329*1860b1a8SLachlan Hodges 	DECLARE_BITMAP(exp, MAX_AID + 1);
330*1860b1a8SLachlan Hodges 
331*1860b1a8SLachlan Hodges 	tim_begin(tim, &p);
332*1860b1a8SLachlan Hodges 	pvb_add_olb(&p, blk_off, inverse, subblocks, len);
333*1860b1a8SLachlan Hodges 	tim_len = tim_end(tim, p);
334*1860b1a8SLachlan Hodges 
335*1860b1a8SLachlan Hodges 	fill_bitmap_inverse(exp, 127, except, ARRAY_SIZE(except));
336*1860b1a8SLachlan Hodges 
337*1860b1a8SLachlan Hodges 	dump_tim_bits(test, tim, tim_len);
338*1860b1a8SLachlan Hodges 	check_all_aids(test, tim, tim_len, exp);
339*1860b1a8SLachlan Hodges }
340*1860b1a8SLachlan Hodges 
341*1860b1a8SLachlan Hodges static struct kunit_case s1g_tim_test_cases[] = {
342*1860b1a8SLachlan Hodges 	KUNIT_CASE(s1g_tim_block_test),
343*1860b1a8SLachlan Hodges 	KUNIT_CASE(s1g_tim_single_test),
344*1860b1a8SLachlan Hodges 	KUNIT_CASE(s1g_tim_olb_test),
345*1860b1a8SLachlan Hodges 	KUNIT_CASE(s1g_tim_inverse_block_test),
346*1860b1a8SLachlan Hodges 	KUNIT_CASE(s1g_tim_inverse_single_test),
347*1860b1a8SLachlan Hodges 	KUNIT_CASE(s1g_tim_inverse_olb_test),
348*1860b1a8SLachlan Hodges 	{}
349*1860b1a8SLachlan Hodges };
350*1860b1a8SLachlan Hodges 
351*1860b1a8SLachlan Hodges static struct kunit_suite s1g_tim = {
352*1860b1a8SLachlan Hodges 	.name = "mac80211-s1g-tim",
353*1860b1a8SLachlan Hodges 	.test_cases = s1g_tim_test_cases,
354*1860b1a8SLachlan Hodges };
355*1860b1a8SLachlan Hodges 
356*1860b1a8SLachlan Hodges kunit_test_suite(s1g_tim);
357