diff options
| author | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-05-10 19:31:58 +0200 |
|---|---|---|
| committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2018-05-10 19:31:58 +0200 |
| commit | 298f2396957bea59cf0985227a6dd903813b5938 (patch) | |
| tree | 741cee6cc83e7b1f4be4a4d4c0cad298b28247f6 | |
| parent | b2599999be1d51eedc0e11a15cec9e7fac253250 (diff) | |
| download | plan9front-298f2396957bea59cf0985227a6dd903813b5938.tar.xz | |
ip: add some primitive rate limiting knobs to counteract bufferbloat
| -rw-r--r-- | sys/man/3/ip | 11 | ||||
| -rw-r--r-- | sys/src/9/ip/arp.c | 2 | ||||
| -rw-r--r-- | sys/src/9/ip/ip.c | 5 | ||||
| -rw-r--r-- | sys/src/9/ip/ip.h | 7 | ||||
| -rw-r--r-- | sys/src/9/ip/ipifc.c | 59 | ||||
| -rw-r--r-- | sys/src/9/ip/ipv6.c | 5 |
6 files changed, 81 insertions, 8 deletions
diff --git a/sys/man/3/ip b/sys/man/3/ip index 76430cd01..38ae273bc 100644 --- a/sys/man/3/ip +++ b/sys/man/3/ip @@ -194,6 +194,17 @@ Set the maximum transfer unit for this device to The mtu is the maximum size of the packet including any medium-specific headers. .TP +.BI speed\ n +Set the maximum transmit speed in bits per second. +TP +.BI delay\ n +Set the maximum burst delay in milliseconds. (Default is 40ms) +When +.B speed +has been set and packets in flight exceed the maximum burst +delay then packets send on the interface are discarded until +the load drops below the maximum. +.TP .BI iprouting\ n Allow .RI ( n diff --git a/sys/src/9/ip/arp.c b/sys/src/9/ip/arp.c index 12cb42fd1..03897c705 100644 --- a/sys/src/9/ip/arp.c +++ b/sys/src/9/ip/arp.c @@ -303,7 +303,7 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *ia, Ipifc *if freeblistchain(next); break; } - ifc->m->bwrite(ifc, concatblock(bp), version, ip); + ipifcoput(ifc, bp, version, ip); poperror(); } return 1; diff --git a/sys/src/9/ip/ip.c b/sys/src/9/ip/ip.c index 7166619dd..f1cd74c10 100644 --- a/sys/src/9/ip/ip.c +++ b/sys/src/9/ip/ip.c @@ -180,6 +180,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh) runlock(ifc); nexterror(); } + if(ifc->m == nil) goto raise; @@ -196,7 +197,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh) eh->cksum[0] = 0; eh->cksum[1] = 0; hnputs(eh->cksum, ipcsum(&eh->vihl)); - ifc->m->bwrite(ifc, concatblock(bp), V4, gate); + ipifcoput(ifc, bp, V4, gate); runlock(ifc); poperror(); return 0; @@ -280,7 +281,7 @@ if((eh->frag[0] & (IP_DF>>8)) && !gating) print("%V: DF set\n", eh->dst); feh->cksum[0] = 0; feh->cksum[1] = 0; hnputs(feh->cksum, ipcsum(&feh->vihl)); - ifc->m->bwrite(ifc, nb, V4, gate); + ipifcoput(ifc, nb, V4, gate); ip->stats[FragCreates]++; } ip->stats[FragOKs]++; diff --git a/sys/src/9/ip/ip.h b/sys/src/9/ip/ip.h index 84edd761e..de1908dcd 100644 --- a/sys/src/9/ip/ip.h +++ b/sys/src/9/ip/ip.h @@ -327,6 +327,12 @@ struct Ipifc uchar recvra6; /* flag: recv router advs on this ifc */ Routerparams rp; /* router parameters as in RFC 2461, pp.40—43. used only if node is router */ + + int speed; /* link speed in bits per second */ + int delay; /* burst delay in ms */ + int burst; /* burst delay in bytes */ + int load; /* bytes in flight */ + ulong ticks; }; /* @@ -652,6 +658,7 @@ extern Medium pktmedium; */ extern Medium* ipfindmedium(char *name); extern void addipmedium(Medium *med); +extern void ipifcoput(Ipifc *ifc, Block *bp, int version, uchar *ip); extern int ipforme(Fs*, uchar *addr); extern int ipismulticast(uchar *ip); extern Ipifc* findipifc(Fs*, uchar *local, uchar *remote, int type); diff --git a/sys/src/9/ip/ipifc.c b/sys/src/9/ip/ipifc.c index 037f2abd9..d0d0557a9 100644 --- a/sys/src/9/ip/ipifc.c +++ b/sys/src/9/ip/ipifc.c @@ -250,7 +250,7 @@ ipifcunbind(Ipifc *ifc) char sfixedformat[] = "device %s maxtu %d sendra %d recvra %d mflag %d oflag" " %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt" -" %d pktin %lud pktout %lud errin %lud errout %lud\n"; +" %d pktin %lud pktout %lud errin %lud errout %lud speed %d delay %d\n"; char slineformat[] = " %-40I %-10M %-40I %-12lud %-12lud\n"; @@ -267,7 +267,8 @@ ipifcstate(Conv *c, char *state, int n) ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint, ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime, ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt, - ifc->in, ifc->out, ifc->inerr, ifc->outerr); + ifc->in, ifc->out, ifc->inerr, ifc->outerr, + ifc->speed, ifc->delay); rlock(ifc); for(lifc = ifc->lifc; lifc != nil && n > m; lifc = lifc->next) @@ -309,6 +310,50 @@ ipifcinuse(Conv *c) return ifc->m != nil; } +static void +ipifcsetdelay(Ipifc *ifc, int delay) +{ + if(delay < 0) + delay = 0; + else if(delay > 1000) + delay = 1000; + ifc->delay = delay; + ifc->burst = ((vlong)delay * ifc->speed) / 8000; + if(ifc->burst < ifc->maxtu) + ifc->burst = ifc->maxtu; +} + +static void +ipifcsetspeed(Ipifc *ifc, int speed) +{ + if(speed < 0) + speed = 0; + ifc->speed = speed; + ifc->load = 0; + ipifcsetdelay(ifc, ifc->delay); +} + +void +ipifcoput(Ipifc *ifc, Block *bp, int version, uchar *ip) +{ + if(ifc->speed){ + ulong now = MACHP(0)->ticks; + int dt = TK2MS(now - ifc->ticks); + ifc->ticks = now; + ifc->load -= ((vlong)dt * ifc->speed) / 8000; + if(ifc->load < 0 || dt < 0 || dt > 1000) + ifc->load = 0; + else if(ifc->load > ifc->burst){ + freeblist(bp); + return; + } + } + bp = concatblock(bp); + ifc->load += BLEN(bp); + ifc->m->bwrite(ifc, bp, version, ip); +} + + /* * called when a process writes to an interface's 'data' */ @@ -358,6 +403,8 @@ ipifccreate(Conv *c) ifc->m = nil; ifc->reflect = 0; ifc->reassemble = 0; + ipifcsetspeed(ifc, 0); + ipifcsetdelay(ifc, 40); } /* @@ -772,6 +819,14 @@ ipifcctl(Conv* c, char **argv, int argc) return ipifcunbind(ifc); else if(strcmp(argv[0], "mtu") == 0) return ipifcsetmtu(ifc, argv, argc); + else if(strcmp(argv[0], "speed") == 0){ + ipifcsetspeed(ifc, argc>1? atoi(argv[1]): 0); + return nil; + } + else if(strcmp(argv[0], "delay") == 0){ + ipifcsetdelay(ifc, argc>1? atoi(argv[1]): 0); + return nil; + } else if(strcmp(argv[0], "iprouting") == 0){ iprouting(c->p->f, argc>1? atoi(argv[1]): 1); return nil; diff --git a/sys/src/9/ip/ipv6.c b/sys/src/9/ip/ipv6.c index aab473c87..6b6d4eeca 100644 --- a/sys/src/9/ip/ipv6.c +++ b/sys/src/9/ip/ipv6.c @@ -103,7 +103,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh) medialen = ifc->maxtu - ifc->m->hsize; if(len <= medialen) { hnputs(eh->ploadlen, len - IP6HDR); - ifc->m->bwrite(ifc, concatblock(bp), V6, gate); + ipifcoput(ifc, bp, V6, gate); runlock(ifc); poperror(); return 0; @@ -193,8 +193,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh) if(xp->rp == xp->wp) xp = xp->next; } - - ifc->m->bwrite(ifc, nb, V6, gate); + ipifcoput(ifc, nb, V6, gate); ip->stats[FragCreates]++; } ip->stats[FragOKs]++; |
