summaryrefslogtreecommitdiff
path: root/sys/net/if_tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if_tun.c')
-rw-r--r--sys/net/if_tun.c78
1 files changed, 58 insertions, 20 deletions
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
index e9b7ff47528..e93689d2b8b 100644
--- a/sys/net/if_tun.c
+++ b/sys/net/if_tun.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tun.c,v 1.35 2001/06/15 03:38:34 itojun Exp $ */
+/* $OpenBSD: if_tun.c,v 1.36 2001/06/27 06:07:46 kjc Exp $ */
/* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */
/*
@@ -112,6 +112,9 @@ int tunselect __P((dev_t, int, struct proc *));
static int tuninit __P((struct tun_softc *));
+#ifdef ALTQ
+static void tunstart __P((struct ifnet *));
+#endif
void
tunattach(n)
@@ -132,9 +135,13 @@ tunattach(n)
ifp->if_mtu = TUNMTU;
ifp->if_ioctl = tun_ioctl;
ifp->if_output = tun_output;
+#ifdef ALTQ
+ ifp->if_start = tunstart;
+#endif
ifp->if_flags = IFF_POINTOPOINT;
ifp->if_type = IFT_PROPVIRTUAL;
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ IFQ_SET_READY(&ifp->if_snd);
ifp->if_hdrlen = sizeof(u_int32_t);
ifp->if_collisions = 0;
ifp->if_ierrors = 0;
@@ -194,7 +201,6 @@ tunclose(dev, flag, mode, p)
register int unit, s;
struct tun_softc *tp;
struct ifnet *ifp;
- struct mbuf *m;
if ((unit = minor(dev)) >= ntun)
return (ENXIO);
@@ -206,13 +212,9 @@ tunclose(dev, flag, mode, p)
/*
* junk all pending output
*/
- do {
- s = splimp();
- IF_DEQUEUE(&ifp->if_snd, m);
- splx(s);
- if (m)
- m_freem(m);
- } while (m);
+ s = splimp();
+ IFQ_PURGE(&ifp->if_snd);
+ splx(s);
if ((ifp->if_flags & IFF_UP) && !(tp->tun_flags & TUN_STAYUP)) {
s = splimp();
@@ -330,8 +332,9 @@ tun_output(ifp, m0, dst, rt)
struct rtentry *rt;
{
struct tun_softc *tp = ifp->if_softc;
- int s;
+ int s, len, error;
u_int32_t *af;
+ ALTQ_DECL(struct altq_pktattr pktattr;)
TUNDEBUG(("%s: tun_output\n", ifp->if_xname));
@@ -342,6 +345,12 @@ tun_output(ifp, m0, dst, rt)
return EHOSTDOWN;
}
+ /*
+ * if the queueing discipline needs packet classification,
+ * do it before prepending link headers.
+ */
+ IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
+
M_PREPEND(m0, sizeof(*af), M_DONTWAIT);
af = mtod(m0, u_int32_t *);
*af = htonl(dst->sa_family);
@@ -351,19 +360,17 @@ tun_output(ifp, m0, dst, rt)
bpf_mtap(ifp->if_bpf, m0);
#endif
+ len = m0->m_pkthdr.len + sizeof(*af);
s = splimp();
- if (IF_QFULL(&ifp->if_snd)) {
- IF_DROP(&ifp->if_snd);
- m_freem(m0);
+ IFQ_ENQUEUE(&ifp->if_snd, m0, &pktattr, error);
+ if (error) {
splx(s);
ifp->if_collisions++;
- return (ENOBUFS);
+ return (error);
}
- IF_ENQUEUE(&ifp->if_snd, m0);
-
- ifp->if_opackets++;
- ifp->if_obytes += m0->m_pkthdr.len + sizeof(*af);
splx(s);
+ ifp->if_opackets++;
+ ifp->if_obytes += len;
if (tp->tun_flags & TUN_RWAIT) {
tp->tun_flags &= ~TUN_RWAIT;
@@ -510,7 +517,7 @@ tunread(dev, uio, ioflag)
splx(s);
return (error);
}
- IF_DEQUEUE(&ifp->if_snd, m0);
+ IFQ_DEQUEUE(&ifp->if_snd, m0);
if (m0 == 0) {
if (tp->tun_flags & TUN_NBIO && ioflag & IO_NDELAY) {
splx(s);
@@ -716,3 +723,34 @@ tunselect(dev, rw, p)
TUNDEBUG(("%s: tunselect waiting\n", ifp->if_xname));
return 0;
}
+
+#ifdef ALTQ
+/*
+ * Start packet transmission on the interface.
+ * when the interface queue is rate-limited by ALTQ or TBR,
+ * if_start is needed to drain packets from the queue in order
+ * to notify readers when outgoing packets become ready.
+ */
+static void
+tunstart(ifp)
+ struct ifnet *ifp;
+{
+ struct tun_softc *tp = ifp->if_softc;
+ struct mbuf *m;
+
+ if (!ALTQ_IS_ENABLED(&ifp->if_snd) && !TBR_IS_ENABLED(&ifp->if_snd))
+ return;
+
+ IFQ_POLL(&ifp->if_snd, m);
+ if (m != NULL) {
+ if (tp->tun_flags & TUN_RWAIT) {
+ tp->tun_flags &= ~TUN_RWAIT;
+ wakeup((caddr_t)tp);
+ }
+ if (tp->tun_flags & TUN_ASYNC && tp->tun_pgid)
+ csignal(tp->tun_pgid, SIGIO,
+ tp->tun_siguid, tp->tun_sigeuid);
+ selwakeup(&tp->tun_rsel);
+ }
+}
+#endif