From 2802b30081525836ca4599c79f53541b2085a3ac Mon Sep 17 00:00:00 2001 From: Renato Botelho Date: Mon, 17 Aug 2015 13:53:11 -0300 Subject: Importing pfSense patch tun_optimization.diff --- sys/net/if_tun.c | 79 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 37 deletions(-) (limited to 'sys/net/if_tun.c') diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 262d6d2..9864278 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -52,6 +52,7 @@ #include #ifdef INET #include +#include #endif #include #include @@ -110,6 +111,7 @@ static const char tunname[] = "tun"; static MALLOC_DEFINE(M_TUN, tunname, "Tunnel Interface"); static int tundebug = 0; static int tundclone = 1; +static int tundispatch = 1; static struct clonedevs *tunclones; static TAILQ_HEAD(,tun_softc) tunhead = TAILQ_HEAD_INITIALIZER(tunhead); SYSCTL_INT(_debug, OID_AUTO, if_tun_debug, CTLFLAG_RW, &tundebug, 0, ""); @@ -119,6 +121,8 @@ static SYSCTL_NODE(_net_link, OID_AUTO, tun, CTLFLAG_RW, 0, "IP tunnel software network interface."); SYSCTL_INT(_net_link_tun, OID_AUTO, devfs_cloning, CTLFLAG_RW, &tundclone, 0, "Enable legacy devfs interface creation."); +SYSCTL_INT(_net_link_tun, OID_AUTO, tun_dispatching, CTLFLAG_RW, &tundispatch, 0, + "Queue rather than direct dispatch on write."); TUNABLE_INT("net.link.tun.devfs_cloning", &tundclone); @@ -328,31 +332,28 @@ static void tunstart(struct ifnet *ifp) { struct tun_softc *tp = ifp->if_softc; - struct mbuf *m; TUNDEBUG(ifp,"%s starting\n", ifp->if_xname); - if (ALTQ_IS_ENABLED(&ifp->if_snd)) { - IFQ_LOCK(&ifp->if_snd); - IFQ_POLL_NOLOCK(&ifp->if_snd, m); - if (m == NULL) { - IFQ_UNLOCK(&ifp->if_snd); - return; - } - IFQ_UNLOCK(&ifp->if_snd); - } + if (IFQ_IS_EMPTY(&ifp->if_snd)) + return; + + ifp->if_drv_flags |= IFF_DRV_OACTIVE; - mtx_lock(&tp->tun_mtx); if (tp->tun_flags & TUN_RWAIT) { tp->tun_flags &= ~TUN_RWAIT; wakeup(tp); } - selwakeuppri(&tp->tun_rsel, PZERO + 1); - KNOTE_LOCKED(&tp->tun_rsel.si_note, 0); - if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) { + if (!TAILQ_EMPTY(&tp->tun_rsel.si_tdlist)) + selwakeuppri(&tp->tun_rsel, PZERO + 1); + if (!KNLIST_EMPTY(&tp->tun_rsel.si_note)) { + mtx_lock(&tp->tun_mtx); + KNOTE_LOCKED(&tp->tun_rsel.si_note, 0); mtx_unlock(&tp->tun_mtx); + } + if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) pgsigio(&tp->tun_sigio, SIGIO, 0); - } else - mtx_unlock(&tp->tun_mtx); + + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } /* XXX: should return an error code so it can fail. */ @@ -590,9 +591,7 @@ tunoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, #endif /* Could be unlocked read? */ - mtx_lock(&tp->tun_mtx); cached_tun_flags = tp->tun_flags; - mtx_unlock(&tp->tun_mtx); if ((cached_tun_flags & TUN_READY) != TUN_READY) { TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags); m_freem (m0); @@ -799,9 +798,7 @@ tunread(struct cdev *dev, struct uio *uio, int flag) int error=0, len; TUNDEBUG (ifp, "read\n"); - mtx_lock(&tp->tun_mtx); if ((tp->tun_flags & TUN_READY) != TUN_READY) { - mtx_unlock(&tp->tun_mtx); TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags); return (EHOSTDOWN); } @@ -812,19 +809,19 @@ tunread(struct cdev *dev, struct uio *uio, int flag) IFQ_DEQUEUE(&ifp->if_snd, m); if (m == NULL) { if (flag & O_NONBLOCK) { - mtx_unlock(&tp->tun_mtx); return (EWOULDBLOCK); } + mtx_lock(&tp->tun_mtx); tp->tun_flags |= TUN_RWAIT; error = mtx_sleep(tp, &tp->tun_mtx, PCATCH | (PZERO + 1), "tunread", 0); + tp->tun_flags &= ~TUN_RWAIT; + mtx_unlock(&tp->tun_mtx); if (error != 0) { - mtx_unlock(&tp->tun_mtx); return (error); } } } while (m == NULL); - mtx_unlock(&tp->tun_mtx); while (m && uio->uio_resid > 0 && error == 0) { len = min(uio->uio_resid, m->m_len); @@ -849,6 +846,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag) struct tun_softc *tp = dev->si_drv1; struct ifnet *ifp = TUN2IFP(tp); struct mbuf *m; + struct ip *ip; uint32_t family; int isr; @@ -876,18 +874,26 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag) mac_ifnet_create_mbuf(ifp, m); #endif - /* Could be unlocked read? */ - mtx_lock(&tp->tun_mtx); + /* XXX: unlocked read? */ if (tp->tun_flags & TUN_IFHEAD) { - mtx_unlock(&tp->tun_mtx); if (m->m_len < sizeof(family) && (m = m_pullup(m, sizeof(family))) == NULL) return (ENOBUFS); family = ntohl(*mtod(m, u_int32_t *)); m_adj(m, sizeof(family)); } else { - mtx_unlock(&tp->tun_mtx); - family = AF_INET; + if (m->m_len < sizeof(struct ip) && + (m = m_pullup(m, sizeof(struct ip))) == NULL) + return (ENOBUFS); + ip = mtod(m, struct ip *); + if (ip->ip_v == IPVERSION) + family = AF_INET; + else if (ip->ip_v == AF_INET6) + family = AF_INET6; + else { + m_freem(m); + return (EINVAL); + } } BPF_MTAP2(ifp, &family, sizeof(family), m); @@ -923,7 +929,10 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag) ifp->if_ipackets++; CURVNET_SET(ifp->if_vnet); M_SETFIB(m, ifp->if_fib); - netisr_dispatch(isr, m); + if (tundispatch) + netisr_queue(isr, m); + else + netisr_dispatch(isr, m); CURVNET_RESTORE(); return (0); } @@ -939,21 +948,17 @@ tunpoll(struct cdev *dev, int events, struct thread *td) struct tun_softc *tp = dev->si_drv1; struct ifnet *ifp = TUN2IFP(tp); int revents = 0; - struct mbuf *m; TUNDEBUG(ifp, "tunpoll\n"); if (events & (POLLIN | POLLRDNORM)) { - IFQ_LOCK(&ifp->if_snd); - IFQ_POLL_NOLOCK(&ifp->if_snd, m); - if (m != NULL) { - TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len); - revents |= events & (POLLIN | POLLRDNORM); - } else { + if (IFQ_IS_EMPTY(&ifp->if_snd)) { TUNDEBUG(ifp, "tunpoll waiting\n"); selrecord(td, &tp->tun_rsel); + } else { + TUNDEBUG(ifp, "tunpoll q=%d\n", ifp->if_snd.ifq_len); + revents |= events & (POLLIN | POLLRDNORM); } - IFQ_UNLOCK(&ifp->if_snd); } if (events & (POLLOUT | POLLWRNORM)) revents |= events & (POLLOUT | POLLWRNORM); -- cgit v1.1