diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2008-04-10 23:15:46 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2008-04-10 23:15:46 +0000 |
commit | ca31726a0b98ca5ca3caaf50a8f5ca284988eb81 (patch) | |
tree | 48f39439a52434c61ba8601f48b4342f835a7b75 /sys | |
parent | 809a2c5adf7ac3bbd6d750fd38725a635cd2a0c4 (diff) |
introduce mitigation for the calling of an interfaces start routine.
decent drivers prefer to have a lot of packets on the send queue so they
can queue a lot of them up on the tx ring and then post them all in one
big chunk. unfortunately our stack queues one packet onto the send queue
and then calls the start handler immediately.
this mitigates against that queue, send, queue, send behaviour by trying to
call the start routine only once per softnet. now its queue, queue, queue,
send.
this is the result of a lot of discussion with claudio@
tested by many.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if.c | 39 | ||||
-rw-r--r-- | sys/net/if.h | 7 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 5 | ||||
-rw-r--r-- | sys/net/netisr.h | 4 | ||||
-rw-r--r-- | sys/net/netisr_dispatch.h | 3 |
5 files changed, 51 insertions, 7 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 272c773336c..84a5f0409a9 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.168 2008/01/05 19:08:19 henning Exp $ */ +/* $OpenBSD: if.c,v 1.169 2008/04/10 23:15:45 dlg Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -174,6 +174,7 @@ int if_indexlim = 0; struct ifaddr **ifnet_addrs = NULL; struct ifnet **ifindex2ifnet = NULL; struct ifnet_head ifnet; +struct ifnet_head iftxlist = TAILQ_HEAD_INITIALIZER(iftxlist); struct ifnet *lo0ifp; /* @@ -459,6 +460,40 @@ if_attach(struct ifnet *ifp) if_attachsetup(ifp); } +void +if_start(struct ifnet *ifp) +{ + if (IF_QFULL(&ifp->if_snd) && !ISSET(ifp->if_flags, IFF_OACTIVE)) { + if (ISSET(ifp->if_xflags, IFXF_TXREADY)) { + TAILQ_REMOVE(&iftxlist, ifp, if_txlist); + CLR(ifp->if_xflags, IFXF_TXREADY); + } + ifp->if_start(ifp); + return; + } + + if (!ISSET(ifp->if_xflags, IFXF_TXREADY)) { + SET(ifp->if_xflags, IFXF_TXREADY); + TAILQ_INSERT_TAIL(&iftxlist, ifp, if_txlist); + schednetisr(NETISR_TX); + } +} + +void +nettxintr(void) +{ + struct ifnet *ifp; + int s; + + s = splnet(); + while ((ifp = TAILQ_FIRST(&iftxlist)) != NULL) { + TAILQ_REMOVE(&iftxlist, ifp, if_txlist); + CLR(ifp->if_xflags, IFXF_TXREADY); + ifp->if_start(ifp); + } + splx(s); +} + /* * Detach an interface from everything in the kernel. Also deallocate * private resources. @@ -559,6 +594,8 @@ do { \ /* Remove the interface from the list of all interfaces. */ TAILQ_REMOVE(&ifnet, ifp, if_list); + if (ISSET(ifp->if_xflags, IFXF_TXREADY)) + TAILQ_REMOVE(&iftxlist, ifp, if_txlist); /* * Deallocate private resources. diff --git a/sys/net/if.h b/sys/net/if.h index c2adb9e9a36..21dc8f31e4f 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.93 2007/11/18 12:51:48 mpf Exp $ */ +/* $OpenBSD: if.h,v 1.94 2008/04/10 23:15:45 dlg Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -178,6 +178,7 @@ TAILQ_HEAD(ifnet_head, ifnet); /* the actual queue head */ struct ifnet { /* and the entries */ void *if_softc; /* lower-level data for this if */ TAILQ_ENTRY(ifnet) if_list; /* all struct ifnets are chained */ + TAILQ_ENTRY(ifnet) if_txlist; /* list of ifnets ready to tx */ TAILQ_HEAD(, ifaddr) if_addrlist; /* linked list of addresses per if */ TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */ struct hook_desc_head *if_addrhooks; /* address change callbacks */ @@ -198,6 +199,7 @@ struct ifnet { /* and the entries */ u_short if_index; /* numeric abbreviation for this if */ short if_timer; /* time 'til if_watchdog called */ short if_flags; /* up/down, broadcast, etc. */ + int if_xflags; /* extra softnet flags */ struct if_data if_data; /* stats and other data about if */ u_int32_t if_hardmtu; /* maximum MTU device supports */ int if_capabilities; /* interface capabilities */ @@ -265,6 +267,8 @@ struct ifnet { /* and the entries */ (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\ IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI) +#define IFXF_TXREADY 0x1 /* interface is ready to tx */ + /* * Some convenience macros used for setting ifi_baudrate. */ @@ -775,6 +779,7 @@ int if_addgroup(struct ifnet *, const char *); int if_delgroup(struct ifnet *, const char *); void if_group_routechange(struct sockaddr *, struct sockaddr *); struct ifnet *ifunit(const char *); +void if_start(struct ifnet *); struct ifaddr *ifa_ifwithaddr(struct sockaddr *); struct ifaddr *ifa_ifwithaf(int); diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 08c3c67968e..6d3247f628b 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ethersubr.c,v 1.115 2008/04/10 22:33:14 brad Exp $ */ +/* $OpenBSD: if_ethersubr.c,v 1.116 2008/04/10 23:15:45 dlg Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* @@ -432,8 +432,7 @@ ether_output(ifp0, m0, dst, rt0) #endif /* NCARP > 0 */ if (mflags & M_MCAST) ifp->if_omcasts++; - if ((ifp->if_flags & IFF_OACTIVE) == 0) - (*ifp->if_start)(ifp); + if_start(ifp); splx(s); return (error); diff --git a/sys/net/netisr.h b/sys/net/netisr.h index 4c56b7e5c17..2887556c754 100644 --- a/sys/net/netisr.h +++ b/sys/net/netisr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: netisr.h,v 1.29 2008/01/19 18:26:18 mpf Exp $ */ +/* $OpenBSD: netisr.h,v 1.30 2008/04/10 23:15:45 dlg Exp $ */ /* $NetBSD: netisr.h,v 1.12 1995/08/12 23:59:24 mycroft Exp $ */ /* @@ -54,6 +54,7 @@ */ #define NETISR_RND 1 #define NETISR_IP 2 /* same as AF_INET */ +#define NETISR_TX 3 /* for if_snd processing */ #define NETISR_ATALK 16 /* same as AF_APPLETALK */ #define NETISR_ARP 18 /* same as AF_LINK */ #define NETISR_IPV6 24 /* same as AF_INET6 */ @@ -69,6 +70,7 @@ extern int netisr; /* scheduling bits for network */ void netrndintr(void); +void nettxintr(void); void arpintr(void); void ipintr(void); void ip6intr(void); diff --git a/sys/net/netisr_dispatch.h b/sys/net/netisr_dispatch.h index 3269806eaac..2f786985dac 100644 --- a/sys/net/netisr_dispatch.h +++ b/sys/net/netisr_dispatch.h @@ -1,4 +1,4 @@ -/* $OpenBSD: netisr_dispatch.h,v 1.13 2007/06/06 10:04:36 henning Exp $ */ +/* $OpenBSD: netisr_dispatch.h,v 1.14 2008/04/10 23:15:45 dlg Exp $ */ /* $NetBSD: netisr_dispatch.h,v 1.2 2000/07/02 04:40:47 cgd Exp $ */ /* @@ -63,3 +63,4 @@ #if NBLUETOOTH > 0 DONETISR(NETISR_BT,btintr); #endif + DONETISR(NETISR_TX,nettxintr); |