summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if.c39
-rw-r--r--sys/net/if.h7
-rw-r--r--sys/net/if_ethersubr.c5
-rw-r--r--sys/net/netisr.h4
-rw-r--r--sys/net/netisr_dispatch.h3
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);