when i send arp repeatedly in userland by BPF, i find: when the data flow is large, the performance will be very slow. for example: if i dont' send arp, the data flow can reach 3.5G, if i send arp, the data flow can only reach 1.5G. Finally, i find the reason: the BPF will leak some device in ifp->bpf_if->bif_dlist, so the system will capture passing packets in ETHER_BPF_MTAP! Fix: in devfs_close(), i found the fd can't correctly closed.: if (vp->v_iflag & VI_DOOMED) { /* Forced close. */ } else if (dsw->d_flags & D_TRACKCLOSE) { /* Keep device updated on status. */ } else if (count_dev(dev) > 1) {<----------------it go into this case! VI_UNLOCK(vp); dev_relthread(dev); return (0); } i don't know why it go into this case when close BPF device, so it don't call bpfclose() to remove the BPF device from ifp->bpf_if->bif_dlist. thanks. Test case attached with submission follows: #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <net/if.h> #include <net/bpf.h> #include <fcntl.h> #include <sys/ioctl.h> int open_bpf(char *ifname) { struct ifreq ifr; int fd, n = 0; char device[sizeof "/dev/bpf000"]; /* * Go through all the minors and find one that isn't in use. */ do { (void)sprintf(device, "/dev/bpf%d", n++); fd = open(device, O_RDWR); } while (fd < 0 && errno == EBUSY && n < 100); if (fd < 0) { return -1; } (void)strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, (caddr_t) &ifr) < 0) { return -1; } return fd; } main() { int fd; char buf[3333]; int len=3332; while(1){ fd = open_bpf("em0"); if (fd < 0) { return -1; } len = write(fd, buf, len); close(fd); sleep(10); } } How-To-Repeat: 1. run daemon userland code: AN# cat a.c #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <net/if.h> #include <net/bpf.h> #include <fcntl.h> #include <sys/ioctl.h> int open_bpf(char *ifname) { struct ifreq ifr; int fd, n = 0; char device[sizeof "/dev/bpf000"]; /* * Go through all the minors and find one that isn't in use. */ do { (void)sprintf(device, "/dev/bpf%d", n++); fd = open(device, O_RDWR); } while (fd < 0 && errno == EBUSY && n < 100); if (fd < 0) { return -1; } (void)strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, (caddr_t) &ifr) < 0) { return -1; } return fd; } main() { int fd; char buf[3333]; int len=3332; while(1){ fd = open_bpf("em0"); if (fd < 0) { return -1; } len = write(fd, buf, len); close(fd); sleep(10); } } 2.kgdb /kernel /dev/mem (kgdb) p bpf_bpfd_cnt $1 = 8 (it will increase, so it's a leak!)
Responsible Changed From-To: freebsd-bugs->freebsd-net Over to maintainer(s).
i think in sending packet case, the BFD device should not be inserted into ifp->bpf_if->bif_dlist list. anybody know this? thanks a lot! 2011-07-25 lanxw
For bugs matching the following criteria: Status: In Progress Changed: (is less than) 2014-06-01 Reset to default assignee and clear in-progress tags. Mail being skipped
I think this was fixed in svn r229898 (9a7e6bac47adc1bbff8a3cb38ff74bde8a2cc399) in 2012.