ip: add some primitive rate limiting knobs to counteract bufferbloat
This commit is contained in:
parent
b2599999be
commit
298f239695
6 changed files with 81 additions and 8 deletions
11
sys/man/3/ip
11
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
|
The mtu is the maximum size of the packet including any
|
||||||
medium-specific headers.
|
medium-specific headers.
|
||||||
.TP
|
.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
|
.BI iprouting\ n
|
||||||
Allow
|
Allow
|
||||||
.RI ( n
|
.RI ( n
|
||||||
|
|
|
@ -303,7 +303,7 @@ arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, uchar *ia, Ipifc *if
|
||||||
freeblistchain(next);
|
freeblistchain(next);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ifc->m->bwrite(ifc, concatblock(bp), version, ip);
|
ipifcoput(ifc, bp, version, ip);
|
||||||
poperror();
|
poperror();
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -180,6 +180,7 @@ ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
|
||||||
runlock(ifc);
|
runlock(ifc);
|
||||||
nexterror();
|
nexterror();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ifc->m == nil)
|
if(ifc->m == nil)
|
||||||
goto raise;
|
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[0] = 0;
|
||||||
eh->cksum[1] = 0;
|
eh->cksum[1] = 0;
|
||||||
hnputs(eh->cksum, ipcsum(&eh->vihl));
|
hnputs(eh->cksum, ipcsum(&eh->vihl));
|
||||||
ifc->m->bwrite(ifc, concatblock(bp), V4, gate);
|
ipifcoput(ifc, bp, V4, gate);
|
||||||
runlock(ifc);
|
runlock(ifc);
|
||||||
poperror();
|
poperror();
|
||||||
return 0;
|
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[0] = 0;
|
||||||
feh->cksum[1] = 0;
|
feh->cksum[1] = 0;
|
||||||
hnputs(feh->cksum, ipcsum(&feh->vihl));
|
hnputs(feh->cksum, ipcsum(&feh->vihl));
|
||||||
ifc->m->bwrite(ifc, nb, V4, gate);
|
ipifcoput(ifc, nb, V4, gate);
|
||||||
ip->stats[FragCreates]++;
|
ip->stats[FragCreates]++;
|
||||||
}
|
}
|
||||||
ip->stats[FragOKs]++;
|
ip->stats[FragOKs]++;
|
||||||
|
|
|
@ -327,6 +327,12 @@ struct Ipifc
|
||||||
uchar recvra6; /* flag: recv router advs on this ifc */
|
uchar recvra6; /* flag: recv router advs on this ifc */
|
||||||
Routerparams rp; /* router parameters as in RFC 2461, pp.40—43.
|
Routerparams rp; /* router parameters as in RFC 2461, pp.40—43.
|
||||||
used only if node is router */
|
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 Medium* ipfindmedium(char *name);
|
||||||
extern void addipmedium(Medium *med);
|
extern void addipmedium(Medium *med);
|
||||||
|
extern void ipifcoput(Ipifc *ifc, Block *bp, int version, uchar *ip);
|
||||||
extern int ipforme(Fs*, uchar *addr);
|
extern int ipforme(Fs*, uchar *addr);
|
||||||
extern int ipismulticast(uchar *ip);
|
extern int ipismulticast(uchar *ip);
|
||||||
extern Ipifc* findipifc(Fs*, uchar *local, uchar *remote, int type);
|
extern Ipifc* findipifc(Fs*, uchar *local, uchar *remote, int type);
|
||||||
|
|
|
@ -250,7 +250,7 @@ ipifcunbind(Ipifc *ifc)
|
||||||
|
|
||||||
char sfixedformat[] = "device %s maxtu %d sendra %d recvra %d mflag %d oflag"
|
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 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";
|
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.mflag, ifc->rp.oflag, ifc->rp.maxraint,
|
||||||
ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
|
ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
|
||||||
ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt,
|
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);
|
rlock(ifc);
|
||||||
for(lifc = ifc->lifc; lifc != nil && n > m; lifc = lifc->next)
|
for(lifc = ifc->lifc; lifc != nil && n > m; lifc = lifc->next)
|
||||||
|
@ -309,6 +310,50 @@ ipifcinuse(Conv *c)
|
||||||
return ifc->m != nil;
|
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'
|
* called when a process writes to an interface's 'data'
|
||||||
*/
|
*/
|
||||||
|
@ -358,6 +403,8 @@ ipifccreate(Conv *c)
|
||||||
ifc->m = nil;
|
ifc->m = nil;
|
||||||
ifc->reflect = 0;
|
ifc->reflect = 0;
|
||||||
ifc->reassemble = 0;
|
ifc->reassemble = 0;
|
||||||
|
ipifcsetspeed(ifc, 0);
|
||||||
|
ipifcsetdelay(ifc, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -772,6 +819,14 @@ ipifcctl(Conv* c, char **argv, int argc)
|
||||||
return ipifcunbind(ifc);
|
return ipifcunbind(ifc);
|
||||||
else if(strcmp(argv[0], "mtu") == 0)
|
else if(strcmp(argv[0], "mtu") == 0)
|
||||||
return ipifcsetmtu(ifc, argv, argc);
|
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){
|
else if(strcmp(argv[0], "iprouting") == 0){
|
||||||
iprouting(c->p->f, argc>1? atoi(argv[1]): 1);
|
iprouting(c->p->f, argc>1? atoi(argv[1]): 1);
|
||||||
return nil;
|
return nil;
|
||||||
|
|
|
@ -103,7 +103,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
|
||||||
medialen = ifc->maxtu - ifc->m->hsize;
|
medialen = ifc->maxtu - ifc->m->hsize;
|
||||||
if(len <= medialen) {
|
if(len <= medialen) {
|
||||||
hnputs(eh->ploadlen, len - IP6HDR);
|
hnputs(eh->ploadlen, len - IP6HDR);
|
||||||
ifc->m->bwrite(ifc, concatblock(bp), V6, gate);
|
ipifcoput(ifc, bp, V6, gate);
|
||||||
runlock(ifc);
|
runlock(ifc);
|
||||||
poperror();
|
poperror();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -193,8 +193,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
|
||||||
if(xp->rp == xp->wp)
|
if(xp->rp == xp->wp)
|
||||||
xp = xp->next;
|
xp = xp->next;
|
||||||
}
|
}
|
||||||
|
ipifcoput(ifc, nb, V6, gate);
|
||||||
ifc->m->bwrite(ifc, nb, V6, gate);
|
|
||||||
ip->stats[FragCreates]++;
|
ip->stats[FragCreates]++;
|
||||||
}
|
}
|
||||||
ip->stats[FragOKs]++;
|
ip->stats[FragOKs]++;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue