1 /* $NetBSD: npf_nbuf_test.c,v 1.1 2012/04/14 21:57:29 rmind Exp $ */ 2 3 /* 4 * NPF nbuf interface test. 5 * 6 * Public Domain. 7 */ 8 9 #include <sys/types.h> 10 #include <sys/kmem.h> 11 12 #include "npf_impl.h" 13 #include "npf_test.h" 14 15 #define MBUF_CHAIN_LEN 128 16 17 CTASSERT((MBUF_CHAIN_LEN % sizeof(uint32_t)) == 0); 18 19 static char * 20 parse_nbuf_chain(void *nbuf, void *n_ptr) 21 { 22 char *s = kmem_zalloc(MBUF_CHAIN_LEN + 1, KM_SLEEP); 23 int n, error; 24 25 for (n = 0; ; ) { 26 char d[4 + 1]; 27 28 error = nbuf_fetch_datum(nbuf, n_ptr, sizeof(uint32_t), d); 29 if (error) { 30 return NULL; 31 } 32 d[sizeof(d) - 1] = '\0'; 33 strcat(s, d); 34 35 if (n + sizeof(uint32_t) == MBUF_CHAIN_LEN) { 36 assert(nbuf_advance(&nbuf, n_ptr, 37 sizeof(uint32_t) - 1)); 38 break; 39 } 40 n_ptr = nbuf_advance(&nbuf, n_ptr, sizeof(uint32_t)); 41 if (n_ptr == NULL) { 42 return NULL; 43 } 44 n += sizeof(uint32_t); 45 } 46 return s; 47 } 48 49 static char * 50 mbuf_getstring(struct mbuf *m) 51 { 52 char *s = kmem_zalloc(MBUF_CHAIN_LEN + 1, KM_SLEEP); 53 u_int tlen = 0; 54 55 while (m) { 56 int len = m->m_len; 57 char *d = m->m_data; 58 while (len--) { 59 s[tlen++] = *d++; 60 } 61 m = m->m_next; 62 } 63 return s; 64 } 65 66 static struct mbuf * 67 mbuf_alloc_with_off(size_t off, int len) 68 { 69 struct mbuf *m; 70 71 m = kmem_zalloc(sizeof(struct mbuf) + off + len, KM_SLEEP); 72 m->m_data = (char *)m + sizeof(struct mbuf) + off; 73 m->m_len = len; 74 return m; 75 } 76 77 /* 78 * Create an mbuf chain, each of 1 byte size. 79 */ 80 static struct mbuf * 81 mbuf_bytesize(size_t clen) 82 { 83 struct mbuf *m0 = NULL, *m = NULL; 84 u_int i, n; 85 86 /* Chain of clen (e.g. 128) mbufs, each storing 1 byte of data. */ 87 for (i = 0, n = 0; i < clen; i++) { 88 /* Range of offset: 0 .. 15. */ 89 m0 = mbuf_alloc_with_off(n & 0xf, 1); 90 91 /* Fill data with letters from 'a' to 'z'. */ 92 memset(m0->m_data, 'a' + n, 1); 93 n = ('a' + n) != 'z' ? n + 1 : 0; 94 95 /* Next mbuf.. */ 96 m0->m_next = m; 97 m = m0; 98 } 99 return m0; 100 } 101 102 /* 103 * Generate random amount of mbufs, with random offsets and lengths. 104 */ 105 static struct mbuf * 106 mbuf_random_len(size_t chain_len) 107 { 108 struct mbuf *m0 = NULL, *m = NULL; 109 u_int tlen = 0, n = 0; 110 111 while (tlen < chain_len) { 112 u_int off, len; 113 char *d; 114 115 /* Random offset and length range: 1 .. 16. */ 116 off = (random() % 16) + 1; 117 len = (random() % 16) + 1; 118 119 /* Do not exceed 128 bytes of total length. */ 120 if (tlen + len > chain_len) { 121 len = chain_len - tlen; 122 } 123 tlen += len; 124 125 /* Consistently fill data with letters from 'a' to 'z'. */ 126 m0 = mbuf_alloc_with_off(off, len); 127 d = m0->m_data; 128 while (len--) { 129 *d++ = ('a' + n); 130 n = ('a' + n) != 'z' ? n + 1 : 0; 131 } 132 133 /* Next mbuf.. */ 134 m0->m_next = m; 135 m = m0; 136 } 137 assert(tlen == chain_len); 138 return m0; 139 } 140 141 static bool 142 validate_mbuf_data(struct mbuf *m, bool verbose, char *bufa, char *bufb) 143 { 144 bool ret = (strcmp(bufa, bufb) == 0); 145 146 if (verbose) { 147 printf("Buffer A: %s\nBuffer B: %s\n", bufa, bufb); 148 } 149 /* XXX free m */ 150 kmem_free(bufa, MBUF_CHAIN_LEN + 1); 151 kmem_free(bufb, MBUF_CHAIN_LEN + 1); 152 return ret; 153 } 154 155 bool 156 npf_nbuf_test(bool verbose) 157 { 158 struct mbuf *m1, *m2; 159 char *bufa, *bufb; 160 161 m1 = mbuf_random_len(MBUF_CHAIN_LEN); 162 bufa = mbuf_getstring(m1); 163 bufb = parse_nbuf_chain(m1, m1->m_data); 164 if (!validate_mbuf_data(m1, verbose, bufa, bufb)) { 165 return false; 166 } 167 168 m2 = mbuf_bytesize(MBUF_CHAIN_LEN); 169 bufa = mbuf_getstring(m2); 170 bufb = parse_nbuf_chain(m2, m2->m_data); 171 if (!validate_mbuf_data(m2, verbose, bufa, bufb)) { 172 return false; 173 } 174 175 return true; 176 } 177