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,
};
--
⑨