Index: sys/dev/altera/atse/if_atse.c =================================================================== --- sys/dev/altera/atse/if_atse.c +++ sys/dev/altera/atse/if_atse.c @@ -1381,8 +1381,7 @@ } ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSEPOCH; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = atse_ioctl; ifp->if_transmit = atse_transmit; ifp->if_qflush = atse_qflush; Index: sys/dev/beri/virtio/network/if_vtbe.c =================================================================== --- sys/dev/beri/virtio/network/if_vtbe.c +++ sys/dev/beri/virtio/network/if_vtbe.c @@ -613,7 +613,7 @@ ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | - IFF_MULTICAST | IFF_PROMISC | IFF_NEEDSEPOCH); + IFF_MULTICAST | IFF_PROMISC); ifp->if_capabilities = IFCAP_VLAN_MTU; ifp->if_capenable = ifp->if_capabilities; ifp->if_start = vtbe_txstart; Index: sys/dev/dpaa/if_dtsec.c =================================================================== --- sys/dev/dpaa/if_dtsec.c +++ sys/dev/dpaa/if_dtsec.c @@ -688,7 +688,7 @@ ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; /* TODO: Configure */ - ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_NEEDSEPOCH; + ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; ifp->if_init = dtsec_if_init; ifp->if_start = dtsec_if_start; ifp->if_ioctl = dtsec_if_ioctl; Index: sys/dev/hyperv/netvsc/if_hn.c =================================================================== --- sys/dev/hyperv/netvsc/if_hn.c +++ sys/dev/hyperv/netvsc/if_hn.c @@ -2362,8 +2362,7 @@ */ ifp->if_baudrate = IF_Gbps(10); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSEPOCH; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = hn_ioctl; ifp->if_init = hn_init; #ifdef HN_IFSTART_SUPPORT Index: sys/dev/if_ndis/if_ndis.c =================================================================== --- sys/dev/if_ndis/if_ndis.c +++ sys/dev/if_ndis/if_ndis.c @@ -967,8 +967,7 @@ if_initname(ifp, device_get_name(sc->ndis_dev), device_get_unit(sc->ndis_dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSEPOCH; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = ndis_ifioctl; ifp->if_start = ndis_ifstart; ifp->if_init = ndis_init; Index: sys/dev/ntb/if_ntb/if_ntb.c =================================================================== --- sys/dev/ntb/if_ntb/if_ntb.c +++ sys/dev/ntb/if_ntb/if_ntb.c @@ -172,8 +172,7 @@ if_setinitfn(ifp, ntb_net_init); if_setsoftc(ifp, sc); - if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSEPOCH); + if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); if_setioctlfn(ifp, ntb_ioctl); if_settransmitfn(ifp, ntb_transmit); if_setqflushfn(ifp, ntb_qflush); Index: sys/dev/sbni/if_sbni.c =================================================================== --- sys/dev/sbni/if_sbni.c +++ sys/dev/sbni/if_sbni.c @@ -243,8 +243,7 @@ ifp->if_baudrate = (csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSEPOCH; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; mtx_init(&sc->lock, ifp->if_xname, MTX_NETWORK_LOCK, MTX_DEF); callout_init_mtx(&sc->wch, &sc->lock, 0); Index: sys/mips/nlm/dev/net/xlpge.c =================================================================== --- sys/mips/nlm/dev/net/xlpge.c +++ sys/mips/nlm/dev/net/xlpge.c @@ -1052,8 +1052,7 @@ } ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | - IFF_NEEDSEPOCH; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; sc->if_flags = ifp->if_flags; /*ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_HWTAGGING;*/ ifp->if_capabilities = 0; Index: sys/net/if.h =================================================================== --- sys/net/if.h +++ sys/net/if.h @@ -144,7 +144,7 @@ #define IFF_DEBUG 0x4 /* (n) turn on debugging */ #define IFF_LOOPBACK 0x8 /* (i) is a loopback net */ #define IFF_POINTOPOINT 0x10 /* (i) is a point-to-point link */ -#define IFF_NEEDSEPOCH 0x20 /* (i) calls if_input w/o epoch */ +#define IFF_EPOCH_SAFE 0x20 /* (i) calls if_input w/ net epoch */ #define IFF_DRV_RUNNING 0x40 /* (d) resources allocated */ #define IFF_NOARP 0x80 /* (n) no address resolution protocol */ #define IFF_PROMISC 0x100 /* (n) receive all packets */ Index: sys/net/if_ethersubr.c =================================================================== --- sys/net/if_ethersubr.c +++ sys/net/if_ethersubr.c @@ -795,8 +795,36 @@ vnet_ether_destroy, NULL); #endif +static void +ether_input_epoch_safe(struct ifnet *ifp, struct mbuf *m) +{ + struct mbuf *mn; + NET_EPOCH_ASSERT(); + /* + * The drivers are allowed to pass in a chain of packets linked with + * m_nextpkt. We split them up into separate packets here and pass + * them up. This allows the drivers to amortize the receive lock. + */ + CURVNET_SET_QUIET(ifp->if_vnet); + while (m) { + mn = m->m_nextpkt; + m->m_nextpkt = NULL; + + /* + * We will rely on rcvif being set properly in the deferred + * context, so assert it is correct here. + */ + MPASS((m->m_pkthdr.csum_flags & CSUM_SND_TAG) == 0); + KASSERT(m->m_pkthdr.rcvif == ifp, ("%s: ifnet mismatch m %p " + "rcvif %p ifp %p", __func__, m, m->m_pkthdr.rcvif, ifp)); + netisr_dispatch(NETISR_ETHER, m); + m = mn; + } + CURVNET_RESTORE(); +} + static void ether_input(struct ifnet *ifp, struct mbuf *m) { @@ -809,8 +837,7 @@ * them up. This allows the drivers to amortize the receive lock. */ CURVNET_SET_QUIET(ifp->if_vnet); - if (__predict_false(ifp->if_flags & IFF_NEEDSEPOCH)) - NET_EPOCH_ENTER(et); + NET_EPOCH_ENTER(et); while (m) { mn = m->m_nextpkt; m->m_nextpkt = NULL; @@ -825,8 +852,7 @@ netisr_dispatch(NETISR_ETHER, m); m = mn; } - if (__predict_false(ifp->if_flags & IFF_NEEDSEPOCH)) - NET_EPOCH_EXIT(et); + NET_EPOCH_EXIT(et); CURVNET_RESTORE(); } @@ -969,7 +995,10 @@ if_attach(ifp); ifp->if_mtu = ETHERMTU; ifp->if_output = ether_output; - ifp->if_input = ether_input; + if (ifp->if_flags & IFF_EPOCH_SAFE) + ifp->if_input = ether_input_epoch_safe; + else + ifp->if_input = ether_input; ifp->if_resolvemulti = ether_resolvemulti; ifp->if_requestencap = ether_requestencap; #ifdef VIMAGE