xref: /netbsd-src/usr.sbin/npf/npftest/libnpftest/npf_nbuf_test.c (revision f916b9b1ff9c7fa95cc504cdcf5a9d088475af06)
19ffbe6bdSrmind /*
23d9a792dSrmind  * NPF nbuf interface tests.
39ffbe6bdSrmind  *
49ffbe6bdSrmind  * Public Domain.
59ffbe6bdSrmind  */
69ffbe6bdSrmind 
7f75d79ebSchristos #ifdef _KERNEL
89ffbe6bdSrmind #include <sys/types.h>
99ffbe6bdSrmind #include <sys/kmem.h>
10f75d79ebSchristos #endif
119ffbe6bdSrmind 
129ffbe6bdSrmind #include "npf_impl.h"
139ffbe6bdSrmind #include "npf_test.h"
149ffbe6bdSrmind 
159ffbe6bdSrmind #define	MBUF_CHAIN_LEN		128
169ffbe6bdSrmind 
179ffbe6bdSrmind CTASSERT((MBUF_CHAIN_LEN % sizeof(uint32_t)) == 0);
189ffbe6bdSrmind 
193107fd1eSrmind static void
mbuf_consistency_check(nbuf_t * nbuf)203107fd1eSrmind mbuf_consistency_check(nbuf_t *nbuf)
213107fd1eSrmind {
223107fd1eSrmind 	struct mbuf *m = nbuf_head_mbuf(nbuf);
233107fd1eSrmind 
243107fd1eSrmind 	while (m) {
253107fd1eSrmind 		assert(m->m_type != MT_FREE);
263107fd1eSrmind 		m = m->m_next;
273107fd1eSrmind 	}
283107fd1eSrmind }
293107fd1eSrmind 
309ffbe6bdSrmind static char *
parse_nbuf_chain(struct mbuf * m)31352f1606Srmind parse_nbuf_chain(struct mbuf *m)
329ffbe6bdSrmind {
33a79812eaSrmind 	ifnet_t *dummy_ifp = npf_test_addif(IFNAME_TEST, false, false);
349ffbe6bdSrmind 	char *s = kmem_zalloc(MBUF_CHAIN_LEN + 1, KM_SLEEP);
35352f1606Srmind 	nbuf_t nbuf;
363107fd1eSrmind 	void *nptr;
37352f1606Srmind 	int n;
389ffbe6bdSrmind 
39f75d79ebSchristos 	nbuf_init(npf_getkernctx(), &nbuf, m, dummy_ifp);
403107fd1eSrmind 
413107fd1eSrmind 	nptr = nbuf_advance(&nbuf, (random() % 16) + 1, (random() % 16) + 1);
423107fd1eSrmind 	mbuf_consistency_check(&nbuf);
433107fd1eSrmind 	assert(nptr != NULL);
443107fd1eSrmind 	nbuf_reset(&nbuf);
453107fd1eSrmind 
469ffbe6bdSrmind 	for (n = 0; ; ) {
479ffbe6bdSrmind 		char d[4 + 1];
489ffbe6bdSrmind 
49352f1606Srmind 		nptr = nbuf_ensure_contig(&nbuf, sizeof(uint32_t));
50352f1606Srmind 		if (nptr == NULL) {
51352f1606Srmind 			break;
529ffbe6bdSrmind 		}
533107fd1eSrmind 		mbuf_consistency_check(&nbuf);
54352f1606Srmind 		memcpy(&d, nptr, sizeof(uint32_t));
55352f1606Srmind 
569ffbe6bdSrmind 		d[sizeof(d) - 1] = '\0';
579ffbe6bdSrmind 		strcat(s, d);
589ffbe6bdSrmind 
599ffbe6bdSrmind 		if (n + sizeof(uint32_t) == MBUF_CHAIN_LEN) {
60352f1606Srmind 			assert(nbuf_advance(&nbuf, sizeof(uint32_t) - 1, 0));
61352f1606Srmind 			assert(!nbuf_advance(&nbuf, 1, 0));
629ffbe6bdSrmind 			break;
639ffbe6bdSrmind 		}
64352f1606Srmind 		if (!nbuf_advance(&nbuf, sizeof(uint32_t), 0)) {
65352f1606Srmind 			break;
669ffbe6bdSrmind 		}
679ffbe6bdSrmind 		n += sizeof(uint32_t);
689ffbe6bdSrmind 	}
693107fd1eSrmind 	mbuf_consistency_check(&nbuf);
70dadc88e3Srmind 	m_freem(nbuf_head_mbuf(&nbuf));
719ffbe6bdSrmind 	return s;
729ffbe6bdSrmind }
739ffbe6bdSrmind 
749ffbe6bdSrmind static char *
mbuf_getstring(struct mbuf * m)759ffbe6bdSrmind mbuf_getstring(struct mbuf *m)
769ffbe6bdSrmind {
779ffbe6bdSrmind 	char *s = kmem_zalloc(MBUF_CHAIN_LEN + 1, KM_SLEEP);
78dadc88e3Srmind 	unsigned tlen = 0;
799ffbe6bdSrmind 
809ffbe6bdSrmind 	while (m) {
819ffbe6bdSrmind 		int len = m->m_len;
829ffbe6bdSrmind 		char *d = m->m_data;
839ffbe6bdSrmind 		while (len--) {
849ffbe6bdSrmind 			s[tlen++] = *d++;
859ffbe6bdSrmind 		}
869ffbe6bdSrmind 		m = m->m_next;
879ffbe6bdSrmind 	}
889ffbe6bdSrmind 	return s;
899ffbe6bdSrmind }
909ffbe6bdSrmind 
919ffbe6bdSrmind static struct mbuf *
mbuf_alloc_with_off(size_t off,int len)929ffbe6bdSrmind mbuf_alloc_with_off(size_t off, int len)
939ffbe6bdSrmind {
949ffbe6bdSrmind 	struct mbuf *m;
959ffbe6bdSrmind 
96352f1606Srmind 	KASSERT(off + len < MLEN);
97352f1606Srmind 	m = m_get(M_WAITOK, MT_DATA);
98352f1606Srmind 	m->m_data = (char *)m->m_data + off;
999ffbe6bdSrmind 	m->m_len = len;
1009ffbe6bdSrmind 	return m;
1019ffbe6bdSrmind }
1029ffbe6bdSrmind 
1039ffbe6bdSrmind /*
1049ffbe6bdSrmind  * Create an mbuf chain, each of 1 byte size.
1059ffbe6bdSrmind  */
1069ffbe6bdSrmind static struct mbuf *
mbuf_bytesize(size_t clen)1079ffbe6bdSrmind mbuf_bytesize(size_t clen)
1089ffbe6bdSrmind {
1099ffbe6bdSrmind 	struct mbuf *m0 = NULL, *m = NULL;
110dadc88e3Srmind 	unsigned i, n;
1119ffbe6bdSrmind 
1129ffbe6bdSrmind 	/* Chain of clen (e.g. 128) mbufs, each storing 1 byte of data. */
1139ffbe6bdSrmind 	for (i = 0, n = 0; i < clen; i++) {
1149ffbe6bdSrmind 		/* Range of offset: 0 .. 15. */
1159ffbe6bdSrmind 		m0 = mbuf_alloc_with_off(n & 0xf, 1);
1169ffbe6bdSrmind 
1179ffbe6bdSrmind 		/* Fill data with letters from 'a' to 'z'. */
1189ffbe6bdSrmind 		memset(m0->m_data, 'a' + n, 1);
119352f1606Srmind 		n = ('a' + n) < 'z' ? n + 1 : 0;
1209ffbe6bdSrmind 
1219ffbe6bdSrmind 		/* Next mbuf.. */
1229ffbe6bdSrmind 		m0->m_next = m;
1239ffbe6bdSrmind 		m = m0;
1249ffbe6bdSrmind 	}
125352f1606Srmind 
126352f1606Srmind 	m0 = m_gethdr(M_WAITOK, MT_HEADER);
127352f1606Srmind 	m0->m_pkthdr.len = clen;
128352f1606Srmind 	m0->m_len = 0;
129352f1606Srmind 	m0->m_next = m;
1309ffbe6bdSrmind 	return m0;
1319ffbe6bdSrmind }
1329ffbe6bdSrmind 
1339ffbe6bdSrmind /*
134dadc88e3Srmind  * Generate random number of mbufs, with random offsets and lengths.
1359ffbe6bdSrmind  */
1369ffbe6bdSrmind static struct mbuf *
mbuf_random_len(size_t chain_len)1379ffbe6bdSrmind mbuf_random_len(size_t chain_len)
1389ffbe6bdSrmind {
1399ffbe6bdSrmind 	struct mbuf *m0 = NULL, *m = NULL;
140dadc88e3Srmind 	unsigned tlen = 0, n = 0;
1419ffbe6bdSrmind 
1429ffbe6bdSrmind 	while (tlen < chain_len) {
143dadc88e3Srmind 		unsigned off, len;
1449ffbe6bdSrmind 		char *d;
1459ffbe6bdSrmind 
1469ffbe6bdSrmind 		/* Random offset and length range: 1 .. 16. */
1479ffbe6bdSrmind 		off = (random() % 16) + 1;
1489ffbe6bdSrmind 		len = (random() % 16) + 1;
1499ffbe6bdSrmind 
1509ffbe6bdSrmind 		/* Do not exceed 128 bytes of total length. */
1519ffbe6bdSrmind 		if (tlen + len > chain_len) {
1529ffbe6bdSrmind 			len = chain_len - tlen;
1539ffbe6bdSrmind 		}
1549ffbe6bdSrmind 		tlen += len;
1559ffbe6bdSrmind 
1569ffbe6bdSrmind 		/* Consistently fill data with letters from 'a' to 'z'. */
1579ffbe6bdSrmind 		m0 = mbuf_alloc_with_off(off, len);
1589ffbe6bdSrmind 		d = m0->m_data;
1599ffbe6bdSrmind 		while (len--) {
1609ffbe6bdSrmind 			*d++ = ('a' + n);
161352f1606Srmind 			n = ('a' + n) < 'z' ? n + 1 : 0;
1629ffbe6bdSrmind 		}
1639ffbe6bdSrmind 
1649ffbe6bdSrmind 		/* Next mbuf.. */
1659ffbe6bdSrmind 		m0->m_next = m;
1669ffbe6bdSrmind 		m = m0;
1679ffbe6bdSrmind 	}
168352f1606Srmind 	KASSERT(tlen == chain_len);
169352f1606Srmind 
170352f1606Srmind 	m0 = m_gethdr(M_WAITOK, MT_HEADER);
171352f1606Srmind 	m0->m_pkthdr.len = tlen;
172352f1606Srmind 	m0->m_next = m;
173352f1606Srmind 	m0->m_len = 0;
1749ffbe6bdSrmind 	return m0;
1759ffbe6bdSrmind }
1769ffbe6bdSrmind 
1779ffbe6bdSrmind static bool
validate_mbuf_data(char * bufa,char * bufb)178dadc88e3Srmind validate_mbuf_data(char *bufa, char *bufb)
1799ffbe6bdSrmind {
180dadc88e3Srmind 	bool ok = strcmp(bufa, bufb) == 0;
1819ffbe6bdSrmind 
182dadc88e3Srmind 	if (!ok) {
1839ffbe6bdSrmind 		printf("Buffer A: %s\nBuffer B: %s\n", bufa, bufb);
1849ffbe6bdSrmind 	}
1859ffbe6bdSrmind 	kmem_free(bufa, MBUF_CHAIN_LEN + 1);
1869ffbe6bdSrmind 	kmem_free(bufb, MBUF_CHAIN_LEN + 1);
187dadc88e3Srmind 	return ok;
1889ffbe6bdSrmind }
1899ffbe6bdSrmind 
1909ffbe6bdSrmind bool
npf_nbuf_test(bool verbose)1919ffbe6bdSrmind npf_nbuf_test(bool verbose)
1929ffbe6bdSrmind {
193*f916b9b1Srmind 	struct mbuf *m;
1949ffbe6bdSrmind 	char *bufa, *bufb;
195dadc88e3Srmind 	unsigned n = 10000;
196dadc88e3Srmind 	bool ok;
1979ffbe6bdSrmind 
198dadc88e3Srmind 	while (n--) {
199*f916b9b1Srmind 		m = mbuf_random_len(MBUF_CHAIN_LEN);
200*f916b9b1Srmind 		bufa = mbuf_getstring(m);
201*f916b9b1Srmind 		bufb = parse_nbuf_chain(m);
202dadc88e3Srmind 		ok = validate_mbuf_data(bufa, bufb);
203dadc88e3Srmind 		CHECK_TRUE(ok);
204dadc88e3Srmind 	}
2059ffbe6bdSrmind 
206*f916b9b1Srmind 	m = mbuf_bytesize(MBUF_CHAIN_LEN);
207*f916b9b1Srmind 	bufa = mbuf_getstring(m);
208*f916b9b1Srmind 	bufb = parse_nbuf_chain(m);
209dadc88e3Srmind 	ok = validate_mbuf_data(bufa, bufb);
210dadc88e3Srmind 	CHECK_TRUE(ok);
2119ffbe6bdSrmind 
212dadc88e3Srmind 	(void)verbose;
213dadc88e3Srmind 	return true;
2149ffbe6bdSrmind }
215