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 __dead static void 28 worker(void *arg) 29 { 30 npf_t *npf = npf_getkernctx(); 31 ifnet_t *ifp = npf_test_getif(IFNAME_INT); 32 unsigned int i = (uintptr_t)arg; 33 struct mbuf *m; 34 uint64_t n = 0; 35 36 m = mbuf_get_pkt(AF_INET, IPPROTO_UDP, 37 PUB_IP1, stateful ? LOCAL_IP2 : LOCAL_IP3, 38 80, 15000 + i); 39 40 while (!run) 41 /* spin-wait */; 42 while (!done) { 43 int error; 44 45 error = npfk_packet_handler(npf, &m, ifp, PFIL_OUT); 46 KASSERT(error == 0); (void)error; 47 n++; 48 } 49 npackets[i] = n; 50 m_freem(m); 51 kthread_exit(0); 52 } 53 54 void 55 npf_test_conc(bool st, unsigned nthreads) 56 { 57 uint64_t total = 0; 58 int error; 59 lwp_t **l; 60 61 printf("THREADS\tPKTS\n"); 62 stateful = st; 63 done = false; 64 run = false; 65 66 npackets = kmem_zalloc(sizeof(uint64_t) * nthreads, KM_SLEEP); 67 l = kmem_zalloc(sizeof(lwp_t *) * nthreads, KM_SLEEP); 68 69 for (unsigned i = 0; i < nthreads; i++) { 70 error = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN | 71 KTHREAD_MPSAFE, NULL, worker, (void *)(uintptr_t)i, 72 &l[i], "npfperf"); 73 KASSERT(error == 0); (void)error; 74 } 75 76 /* Let them spin! */ 77 run = true; 78 kpause("perf", false, mstohz(NSECS * 1000), NULL); 79 done = true; 80 81 /* Wait until all threads exit and sum the counts. */ 82 for (unsigned i = 0; i < nthreads; i++) { 83 kthread_join(l[i]); 84 total += npackets[i]; 85 } 86 kmem_free(npackets, sizeof(uint64_t) * nthreads); 87 kmem_free(l, sizeof(lwp_t *) * nthreads); 88 89 printf("%u\t%" PRIu64 "\n", nthreads, total / NSECS); 90 } 91