git: 9front

Download patch

ref: 2dbddd386595eda64f97b1fae3747451c47dd4f2
parent: 518dc15822630929e5190cd96ca6f98cd48e7675
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Oct 19 08:16:19 EDT 2025

ip: Handle all loopback traffic with loopbackmedium

Move the loopback queue into the Ipifc struct, and
divert all traffic with Runi route destination to
the loopback queue.

This means that loopback traffic now always skips
fragmentation step and never reaches the medium
(skipping arp).

--- a/sys/src/9/ip/ip.c
+++ b/sys/src/9/ip/ip.c
@@ -146,6 +146,23 @@
 	} else {
 		eh->vihl = IP_VER4|IP_HLEN4;
 		eh->tos = tos;
+
+		/* bypass for loopback */
+		if(r->type & Runi){
+			eh->ttl = ttl;
+			hnputs(eh->length, len);
+			hnputs(eh->id, incref(&ip->id4));
+			eh->frag[0] = 0;
+			eh->frag[1] = 0;
+			eh->cksum[0] = 0;
+			eh->cksum[1] = 0;
+			hnputs(eh->cksum, ipcsum(&eh->vihl));
+			bp->flag |= Bipck;
+			(*loopbackmedium.bwrite)(ifc, concatblock(bp), V4, gate, rh);
+			runlock(ifc);
+			poperror();
+			return 0;
+		}
 	}
 	eh->ttl = ttl;
 
@@ -160,7 +177,6 @@
 		eh->cksum[0] = 0;
 		eh->cksum[1] = 0;
 		hnputs(eh->cksum, ipcsum(&eh->vihl));
-
 		ipifcoput(ifc, bp, V4, gate, rh);
 		runlock(ifc);
 		poperror();
@@ -244,7 +260,6 @@
 		feh->cksum[0] = 0;
 		feh->cksum[1] = 0;
 		hnputs(feh->cksum, ipcsum(&feh->vihl));
-
 		ipifcoput(ifc, nb, V4, gate, rh);
 		ip->stats[FragCreates]++;
 	}
--- a/sys/src/9/ip/ip.h
+++ b/sys/src/9/ip/ip.h
@@ -391,6 +391,7 @@
 	uchar	mac[MAClen];	/* MAC address */
 
 	Iplifc	*lifc;		/* logical interfaces on this physical one */
+	Queue	*loopback;
 
 	ulong	in, out;	/* message statistics */
 	ulong	inerr, outerr;	/* ... */
@@ -719,6 +720,8 @@
  */
 extern Medium	ethermedium;
 extern Medium	nullmedium;
+extern Medium	unboundmedium;	/* same as nullmedium, to prevent unbind while bind or unbind is in progress */
+extern Medium	loopbackmedium;
 extern Medium	pktmedium;
 
 /*
--- a/sys/src/9/ip/ipifc.c
+++ b/sys/src/9/ip/ipifc.c
@@ -122,9 +122,6 @@
 	return *mp;
 }
 
-/* same as nullmedium, to prevent unbind while bind or unbind is in progress */
-extern Medium unboundmedium;
-
 /*
  *  attach a device (or pkt driver) to the interface.
  *  called with c locked
@@ -174,6 +171,8 @@
 		wunlock(ifc);
 		nexterror();
 	}
+	if(m != &loopbackmedium)
+		(*loopbackmedium.bind)(ifc, argc, argv);
 	(*m->bind)(ifc, argc, argv);
 	poperror();
 
@@ -466,6 +465,7 @@
 	c->sq = qopen(QMAX, 0, 0, 0);
 	if(c->rq == nil || c->wq == nil || c->sq == nil)
 		error(Enomem);
+
 	ifc = (Ipifc*)c->ptcl;
 	ifc->conv = c;
 	ifc->m = nil;
--- a/sys/src/9/ip/ipv6.c
+++ b/sys/src/9/ip/ipv6.c
@@ -101,6 +101,16 @@
 		eh->vcf[0] = IP_VER6;
 		eh->vcf[0] |= tos >> 4;
 		eh->vcf[1]  = tos << 4;
+
+		/* bypass for loopback */
+		if(r->type & Runi){
+			eh->ttl = ttl;
+			hnputs(eh->ploadlen, len - IP6HDR);
+			(*loopbackmedium.bwrite)(ifc, concatblock(bp), V6, gate, rh);
+			runlock(ifc);
+			poperror();
+			return 0;
+		}
 	}
 	eh->ttl = ttl;
 
--- a/sys/src/9/ip/loopbackmedium.c
+++ b/sys/src/9/ip/loopbackmedium.c
@@ -7,112 +7,62 @@
 
 #include "ip.h"
 
-enum
-{
-	Maxtu=	64*1024,
-};
-
-typedef struct LB LB;
-struct LB
-{
-	Proc	*readp;
-	Queue	*q;
-	Fs	*f;
-};
-
-static void loopbackread(void *a);
-
 static void
-loopbackbind(Ipifc *ifc, int, char**)
+readloopback(void *x)
 {
-	LB *lb;
+	Ipifc *ifc = (Ipifc*)x;
+	Fs *f = ifc->conv->p->f;
+	Block *bp;
 
-	lb = smalloc(sizeof(*lb));
-	lb->readp = (void*)-1;
-	lb->f = ifc->conv->p->f;
-	lb->q = qopen(1024*1024, Qmsg, nil, nil);
-	ifc->arg = lb;
-
-	kproc("loopbackread", loopbackread, ifc);
-
-}
-
-static void
-loopbackunbind(Ipifc *ifc)
-{
-	LB *lb = ifc->arg;
-
 	while(waserror())
 		;
-	/* wat for reader to start */
-	while(lb->readp == (void*)-1)
-		tsleep(&up->sleep, return0, 0, 300);
-		
-	if(lb->readp != nil)
-		postnote(lb->readp, 1, "unbind", 0);
-	poperror();
-
-	while(waserror())
-		;
-	/* wait for reader to die */
-	while(lb->readp != nil)
-		tsleep(&up->sleep, return0, 0, 300);
-	poperror();
-
-	/* clean up */
-	qfree(lb->q);
-	free(lb);
-}
-
-static void
-loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*, Routehint*)
-{
-	LB *lb;
-
-	lb = ifc->arg;
-	if(qpass(lb->q, bp) < 0)
-		ifc->outerr++;
-	ifc->out++;
-}
-
-static void
-loopbackread(void *a)
-{
-	Ipifc *ifc;
-	Block *bp;
-	LB *lb;
-
-	ifc = a;
-	lb = ifc->arg;
-	lb->readp = up;	/* hide identity under a rock for unbind */
-	if(!waserror())
-	while((bp = qbread(lb->q, Maxtu)) != nil){
+	while((bp = qbread(ifc->loopback, IP_MAX)) != nil){
 		rlock(ifc);
 		if(waserror()){
 			runlock(ifc);
 			continue;
 		}
-		ifc->in++;
 		if(ifc->lifc == nil)
 			freeb(bp);
-		else
-			ipiput4(lb->f, ifc, bp);
+		else {
+			ifc->in++;
+			ipiput4(f, ifc, bp);
+		}
 		runlock(ifc);
 		poperror();
 	}
-	lb->readp = nil;
 	pexit("hangup", 1);
 }
 
+static void
+loopbackbind(Ipifc *ifc, int, char**)
+{
+	if(ifc->loopback != nil)
+		return;
+
+	ifc->loopback = qopen(1024*1024, Qmsg, 0, 0);
+	if(ifc->loopback == nil)
+		error(Enomem);
+	kproc("loopbackread", readloopback, ifc);
+
+}
+
+static void
+loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*, Routehint*)
+{
+	if(qpass(ifc->loopback, bp) < 0)
+		ifc->outerr++;
+	ifc->out++;
+}
+
 Medium loopbackmedium =
 {
 .hsize=		0,
 .mintu=		0,
-.maxtu=		Maxtu,
+.maxtu=		IP_MAX,
 .maclen=	0,
 .name=		"loopback",
 .bind=		loopbackbind,
-.unbind=	loopbackunbind,
 .bwrite=	loopbackbwrite,
 };
 
--