1 /* 2 * NPF benchmarking. 3 * 4 * Public Domain. 5 */ 6 7 #ifdef _KERNEL 8 #include <sys/types.h> 9 #include <sys/param.h> 10 11 #include <sys/kernel.h> 12 #include <sys/kmem.h> 13 #include <sys/kthread.h> 14 #endif 15 16 #include "npf_impl.h" 17 #include "npf_test.h" 18 19 #define NSECS 10 /* seconds */ 20 21 static volatile int run; 22 static volatile int done; 23 24 static uint64_t * npackets; 25 static bool stateful; 26 27 static struct mbuf * 28 fill_packet(unsigned i) 29 { 30 struct mbuf *m; 31 struct ip *ip; 32 struct udphdr *uh; 33 char buf[32]; 34 35 m = mbuf_construct(IPPROTO_UDP); 36 uh = mbuf_return_hdrs(m, false, &ip); 37 38 snprintf(buf, sizeof(buf), "192.0.2.%u", i + i); 39 ip->ip_src.s_addr = inet_addr(PUB_IP1); 40 ip->ip_dst.s_addr = inet_addr(stateful ? LOCAL_IP2 : LOCAL_IP3); 41 uh->uh_sport = htons(80); 42 uh->uh_dport = htons(15000 + i); 43 return m; 44 } 45 46 __dead static void 47 worker(void *arg) 48 { 49 npf_t *npf = npf_getkernctx(); 50 ifnet_t *ifp = npf_test_getif(IFNAME_INT); 51 unsigned int i = (uintptr_t)arg; 52 struct mbuf *m = fill_packet(i); 53 uint64_t n = 0; 54 55 while (!run) 56 /* spin-wait */; 57 while (!done) { 58 int error; 59 60 error = npf_packet_handler(npf, &m, ifp, PFIL_OUT); 61 KASSERT(error == 0); (void)error; 62 n++; 63 } 64 npackets[i] = n; 65 kthread_exit(0); 66 } 67 68 void 69 npf_test_conc(bool st, unsigned nthreads) 70 { 71 uint64_t total = 0; 72 int error; 73 lwp_t **l; 74 75 printf("THREADS\tPKTS\n"); 76 stateful = st; 77 done = false; 78 run = false; 79 80 npackets = kmem_zalloc(sizeof(uint64_t) * nthreads, KM_SLEEP); 81 l = kmem_zalloc(sizeof(lwp_t *) * nthreads, KM_SLEEP); 82 83 for (unsigned i = 0; i < nthreads; i++) { 84 error = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN | 85 KTHREAD_MPSAFE, NULL, worker, (void *)(uintptr_t)i, 86 &l[i], "npfperf"); 87 KASSERT(error == 0); (void)error; 88 } 89 90 /* Let them spin! */ 91 run = true; 92 kpause("perf", false, mstohz(NSECS * 1000), NULL); 93 done = true; 94 95 /* Wait until all threads exit and sum the counts. */ 96 for (unsigned i = 0; i < nthreads; i++) { 97 kthread_join(l[i]); 98 total += npackets[i]; 99 } 100 kmem_free(npackets, sizeof(uint64_t) * nthreads); 101 kmem_free(l, sizeof(lwp_t *) * nthreads); 102 103 printf("%u\t%" PRIu64 "\n", nthreads, total / NSECS); 104 } 105