proposal to allow access to a device's mtu limits. mintu <= mtu <= maxtu. mintu and maxtu are supposed to be "hardware" limits. in the case of igbe, it's difficult to shuffle the pool so no reconfiguration is required, but in the general case, Netif->mtu() is called (if it exists) to modify mtu. the file /net/ether$i/mtu contains the three 11-digit numbers: mintu, mtu, maxtu. this is part of a script i use to set up interfaces for my aoe initiator mtu = 8192 for(n in 1 2 3){ bind -a '#l'^$n /net ether = /net/ether^$n <>$ether/clone{ i=`{read} echo mtu $mtu>$ether/$i/ctl } } this does not yet play nicely in an ethernet configuration or with ip/ipconfig because they don't know about it and the ipifc mtu is not directly connected to the hardware mtu. perhaps a new option could force setting of the hardware's mtu. and in all cases the hardware's mtu setting should be a ceiling to the ipifc mtu. in any event, i think that's to tackle later after we have access to hw mtu settings. - erik Notes: Wed Jun 6 16:16:56 EDT 2007 geoff please resubmit with a diff relative to your previous driver, not ours. Reference: /n/sources/patch/saved/netif-mtu Date: Fri Jun 1 18:22:39 CES 2007 Signed-off-by: quanstro@quanstro.net Reviewed-by: geoff --- /sys/src/9/port/netif.c Fri Jun 1 18:13:34 2007 +++ /sys/src/9/port/netif.c Fri Jun 1 18:13:29 2007 @@ -66,7 +66,7 @@ /* second level contains clone plus all the conversations */ t = NETTYPE(c->qid.path); - if(t == N2ndqid || t == Ncloneqid || t == Naddrqid){ + if(t == N2ndqid || t == Ncloneqid || t == Naddrqid || t == Nmtuqid){ switch(i) { case DEVDOTDOT: q.type = QTDIR; @@ -89,8 +89,12 @@ q.path = Nifstatqid; devdir(c, q, "ifstats", 0, eve, 0444, dp); break; + case 4: + q.path = Nmtuqid; + devdir(c, q, "mtu", 0, eve, 0444, dp); + break; default: - i -= 4; + i -= 5; if(i >= nif->nfile) return -1; if(nif->f[i] == 0) @@ -244,6 +248,9 @@ return readnum(offset, a, n, f->type, NUMSIZE); case Nifstatqid: return 0; + case Nmtuqid: + snprint(up->genbuf, sizeof up->genbuf, "%11.ud %11.ud %11.ud\n", nif->minmtu, nif->mtu, nif->maxmtu); + return readstr(offset, a, n, up->genbuf); } error(Ebadarg); return -1; /* not reached */ @@ -287,7 +294,7 @@ netifwrite(Netif *nif, Chan *c, void *a, long n) { Netfile *f; - int type; + int type, mtu; char *p, buf[64]; uchar binaddr[Nmaxaddr]; @@ -331,6 +338,16 @@ f->scan = type; nif->scan++; } + } else if((p = matchtoken(buf, "mtu")) != 0){ + mtu = atoi(p); + // zero resets default. + if(mtu != 0) + if(mtu < nif->minmtu || mtu > nif->maxmtu) + error(Ebadarg); + if(nif->hwmtu) + nif->mtu = nif->hwmtu(nif->arg, mtu); + else + nif->mtu = mtu; } else if(matchtoken(buf, "bridge")){ f->bridge = 1; } else if(matchtoken(buf, "headersonly")){ @@ -558,7 +575,7 @@ } void -hnputv(void *p, uvlong v) +hnputv(void *p, vlong v) { uchar *a; @@ -568,7 +585,7 @@ } void -hnputl(void *p, uint v) +hnputl(void *p, ulong v) { uchar *a; @@ -589,7 +606,7 @@ a[1] = v; } -uvlong +vlong nhgetv(void *p) { uchar *a; @@ -598,7 +615,7 @@ return ((vlong)nhgetl(a) << 32) | nhgetl(a+4); } -uint +ulong nhgetl(void *p) { uchar *a; --- /sys/src/9/port/netif.h Fri Jun 1 18:13:45 2007 +++ /sys/src/9/port/netif.h Fri Jun 1 18:13:42 2007 @@ -17,6 +17,7 @@ Nstatqid, Ntypeqid, Nifstatqid, + Nmtuqid, }; /* @@ -76,6 +77,9 @@ int alen; /* address length */ int mbps; /* megabits per sec */ int link; /* link status */ + int minmtu; + int maxmtu; + int mtu; uchar addr[Nmaxaddr]; uchar bcast[Nmaxaddr]; Netaddr *maddr; /* known multicast addresses */ @@ -100,6 +104,7 @@ void *arg; void (*promiscuous)(void*, int); void (*multicast)(void*, uchar*, int); + int (*hwmtu)(void*, int); /* get/set mtu */ void (*scanbs)(void*, uint); /* scan for base stations */ }; --- /sys/src/9/pc/devether.c Fri Jun 1 18:14:00 2007 +++ /sys/src/9/pc/devether.c Fri Jun 1 18:13:55 2007 @@ -4,7 +4,6 @@ #include "dat.h" #include "fns.h" #include "io.h" -#include "pool.h" #include "ureg.h" #include "../port/error.h" #include "../port/netif.h" @@ -263,11 +262,11 @@ free(cb); if(ether->ctl!=nil) return ether->ctl(ether,buf,n); - + error(Ebadctl); } - if(n > ether->maxmtu) + if(n > ether->mtu) error(Etoobig); if(n < ether->minmtu) error(Etoosmall); @@ -304,7 +303,7 @@ } ether = etherxx[chan->dev]; - if(n > ether->maxmtu){ + if(n > ether->mtu){ freeb(bp); error(Etoobig); } @@ -359,8 +358,7 @@ static Ether* etherprobe(int cardno, int ctlrno) { - int i, lg; - ulong mb, bsz; + int i, j; Ether *ether; char buf[128], name[32]; @@ -370,6 +368,7 @@ ether->tbdf = BUSUNKNOWN; ether->mbps = 10; ether->minmtu = ETHERMINTU; + ether->mtu = ETHERMAXTU; ether->maxmtu = ETHERMAXTU; if(cardno < 0){ @@ -415,8 +414,8 @@ if(ether->irq >= 0) intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name); - i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d", - ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq); + i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d tu %d", + ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq, ether->mtu); if(ether->mem) i += sprint(buf+i, " addr 0x%luX", ether->mem); if(ether->size) @@ -427,25 +426,16 @@ sprint(buf+i, "\n"); print(buf); - /* compute log10(ether->mbps) into lg */ - for(lg = 0, mb = ether->mbps; mb >= 10; lg++) - mb /= 10; - if (lg > 0) - lg--; - if (lg > 14) /* 2^(14+17) = 2⁳ⁱ */ - lg = 14; - /* allocate larger output queues for higher-speed interfaces */ - bsz = 1UL << (lg + 17); /* 2ⁱ⁷ = 128K, bsz = 2ⁿ × 128K */ - while (bsz > mainmem->maxsize && bsz >= 128*1024) - bsz /= 2; - - netifinit(ether, name, Ntypes, bsz); - while (ether->oq == nil && bsz >= 128*1024) { - bsz /= 2; - ether->oq = qopen(bsz, Qmsg, 0, 0); - ether->limit = bsz; - } - if(ether->oq == nil) + j = ether->mbps; + for(i = 0; j >= 10; i++) + j /= 10; + if(i > 0) + i--; + i = (128<oq == 0) + ether->oq = qopen(i, Qmsg, 0, 0); + if(ether->oq == 0) panic("etherreset %s", name); ether->alen = Eaddrlen; memmove(ether->addr, ether->ea, Eaddrlen); --- /sys/src/9/pc/etherif.h Fri Jun 1 18:14:13 2007 +++ /sys/src/9/pc/etherif.h Fri Jun 1 18:14:11 2007 @@ -9,8 +9,6 @@ int ctlrno; int tbdf; /* type+busno+devno+funcno */ - int minmtu; - int maxmtu; uchar ea[Eaddrlen]; void (*attach)(Ether*); /* filled in by reset routine */