Use a "one block at a time" policy for snoop queues
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 21 Sep 2016 19:49:21 +0000 (15:49 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 21 Sep 2016 21:28:46 +0000 (17:28 -0400)
This fixes snoopy's packet loss.

Snoopy expects to receive a packet at a time.  If you send more than one
packet in a read, the later packets get dropped.  We could change snoopy,
but it is a little easier to tell the kernel to just return one block
(packet) at a time when we do a qread.

In part, I went with this approach since we'll probably want more kernel
support for packet tracing, not less.  For instance, right now, snoopy's
time stamps are taken in userspace when the queue is read, not when the
packet is received or sent.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/src/net/devip.c
kern/src/net/ipifc.c
kern/src/net/netif.c

index 59321e2..ed069c5 100644 (file)
@@ -447,6 +447,7 @@ static struct chan *ipopen(struct chan *c, int omode)
                case Qsnoop:
                        if (omode & O_WRITE)
                                error(EPERM, ERROR_FIXME);
+                       /* might be racy.  note the lack of a proto lock, unlike Qdata */
                        p = f->p[PROTO(c->qid)];
                        cv = p->conv[CONV(c->qid)];
                        if (strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
index 5447bf4..6ae9bad 100644 (file)
@@ -336,7 +336,7 @@ static void ipifccreate(struct conv *c)
        struct Ipifc *ifc;
 
        c->rq = qopen(QMAX, 0, 0, 0);
-       c->sq = qopen(2 * QMAX, 0, 0, 0);
+       c->sq = qopen(2 * QMAX, Qmsg | Qcoalesce, 0, 0);
        c->wq = qopen(QMAX, Qkick, ipifckick, c);
        ifc = (struct Ipifc *)c->ptcl;
        ifc->conv = c;
index e46df7a..f7d2a73 100644 (file)
@@ -437,6 +437,10 @@ long netifwrite(struct ether *nif, struct chan *c, void *a, long n)
                p = netmulti(nif, f, binaddr, 0);
                if (p)
                        error(EFAIL, p);
+       } else if (matchtoken(buf, "oneblock")) {
+               /* Qmsg + Qcoal = one block at a time. */
+               q_toggle_qmsg(f->in, TRUE);
+               q_toggle_qcoalesce(f->in, TRUE);
        } else
                n = -1;
        qunlock(&nif->qlock);