CVSROOT: /cvs Module name: src Changes by: d...@cvs.openbsd.org 2015/08/16 06:17:16
Modified files: sys/net : bpf.c bpfdesc.h Log message: make bpf_mtap mpsafe by using SRPs. this was originally implemented by jmatthew@ last year, and updated by us both during s2k15. there are four data structures that need to be looked after. the first is the bpf interface itself. it is allocated and freed at the same time as an actual interface, so if you're able to send or receive packets, you're able to run bpf on an interface too. dont need to do any work there. the second are bpf descriptors. these represent userland attaching to a bpf interface, so you can have many of them on a single bpf interface. they were arranged in a singly linked list before. now the head and next pointers are replaced with SRP pointers and followed by srp_enter. the list updates are serialised by the kernel lock. the third are the bpf filters. there is an inbound and outbound filter on each bpf descriptor, ann a process can replace them at any time. the pointers from the descriptor to those is also changed to be accessed via srp_enter. updates are serialised by the kernel lock. the fourth thing is the ring that bpf writes to for userland to read. there's one of these per descriptor. because these are only updated when a filter matches (which is hopefully a relatively rare event), we take the kernel lock to serialise the writes to the ring. all this together means you can run bpf against a packet without taking the kernel lock unless you actually caught a packet and need to send it to userland. even better, you can run bpf in parallel, so if we ever support multiple rings on a single interface, we can run bpf on each ring on different cpus safely. ive hit this pretty hard in production at work (yay dhcrelay) on myx (which does rx outside the biglock). ok jmatthew@ mpi@ millert@