From dc81b36ec040feee81bc100c5396a1f2e881f77d Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 7 Mar 1998 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1998-03-07 --- ip/ethermedium.c | 26 ++++------ ip/il.c | 1 + ip/ip.c | 14 ++++- ip/ip.h | 6 ++- ip/ipifc.c | 132 +++++++++++++++-------------------------------- ip/netlog.c | 1 - ip/nullmedium.c | 1 + ip/pktmedium.c | 1 + 8 files changed, 71 insertions(+), 111 deletions(-) diff --git a/ip/ethermedium.c b/ip/ethermedium.c index 741f40480f103b6887c6debce4bb6a4b052fa09f..76571a6c94f054d45284c5d3269b1e125ffbfed7 100644 --- a/ip/ethermedium.c +++ b/ip/ethermedium.c @@ -45,6 +45,7 @@ Medium ethermedium = nil, /* flushroute */ nil, /* joinmulti */ nil, /* leavemulti */ + 0, /* don't unbind on last close */ }; typedef struct Etherrock Etherrock; @@ -205,7 +206,7 @@ etherunbind(Ipifc *ifc) } /* - * called by ipoput with a single block to write + * called by ipoput with a single block to write with ifc rlock'd */ static void etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) @@ -215,17 +216,6 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) uchar mac[6]; Etherrock *er = ifc->arg; - if(waserror()) { - print("etherbwrite failed\n"); - ipifccheckout(ifc); - return; - } - if(ipifccheckin(ifc, ðermedium) < 0){ - freeb(bp); - poperror(); - return; - } - /* get mac address of destination */ a = arpget(bp, version, ðermedium, ip, mac); if(a){ @@ -233,7 +223,7 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) bp = multicastarp(a, mac); if(bp == nil){ sendarp(ifc, a); - goto out; + return; } } @@ -261,10 +251,6 @@ etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip) devtab[er->mchan->type]->bwrite(er->mchan, bp, 0); ifc->out++; - -out: - ipifccheckout(ifc); - poperror(); } /* @@ -276,22 +262,28 @@ etherread(void *a) Ipifc *ifc; Block *bp; Etherrock *er; + int locked = 0; ifc = a; er = ifc->arg; er->readp = up; /* hide identity under a rock for unbind */ if(waserror()){ + if(locked) + runlock(ifc); er->readp = 0; pexit("hangup", 1); } for(;;){ bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0); + rlock(ifc); locked = 1; USED(locked); ifc->in++; bp->rp += ifc->m->hsize; if(ifc->lifc == nil) freeb(bp); else ipiput(ifc->lifc->local, bp); + runlock(ifc); locked = 0; USED(locked); + } } diff --git a/ip/il.c b/ip/il.c index e947a990aedd086a53f944748ec86f2229f8f299..4d8c58016fd785cffd8001f280711310ac5b0d20 100644 --- a/ip/il.c +++ b/ip/il.c @@ -347,6 +347,7 @@ ilxstats(char *buf, int len) il.csumerr, il.hlenerr, il.lenerr, il.order, il.rexmit); n += snprint(buf+n, len-n, " dupp %d dupb %d\n", ilstats.dup, ilstats.dupb); + return n; } void diff --git a/ip/ip.c b/ip/ip.c index 2761a102eaa8223d32848283ceeb98cb5276c860..b8b1a5364328318dfdf0a3e1d014190c49af4d89 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -127,6 +127,14 @@ ipoput(Block *bp, int gating, int ttl) } ifc = r->ifc; + if(waserror()){ + runlock(ifc); + nexterror(); + } + rlock(ifc); + if(ifc->m == nil) + goto raise; + /* If we dont need to fragment just send it */ medialen = ifc->m->maxmtu - ifc->m->hsize; if(len <= medialen) { @@ -141,6 +149,8 @@ ipoput(Block *bp, int gating, int ttl) /*print("ipoput %V->%V via %V\n", eh->src, eh->dst, gate);*/ ifc->m->bwrite(ifc, bp, V4, gate); + runlock(ifc); + poperror(); return; } @@ -203,7 +213,7 @@ ipoput(Block *bp, int gating, int ttl) chunk -= blklen; if(xp->rp == xp->wp) xp = xp->next; - } + } feh->cksum[0] = 0; feh->cksum[1] = 0; @@ -212,6 +222,8 @@ ipoput(Block *bp, int gating, int ttl) } raise: + runlock(ifc); + poperror(); freeblist(bp); } diff --git a/ip/ip.h b/ip/ip.h index 265926eb01bf5f54090933a8a5a17e5a7d59e864..d8f939af0cbfee24c445e541f0c211843c76a5c0 100644 --- a/ip/ip.h +++ b/ip/ip.h @@ -116,6 +116,8 @@ struct Medium /* for routing multicast groups */ void (*joinmulti)(Ipifc *ifc, uchar *a, uchar *ia, uchar **iap); void (*leavemulti)(Ipifc *ifc, uchar *a, uchar *ia); + + int unbindonclose; /* if non-zero, unbind on last close */ }; /* logical interface associated with a physical one */ @@ -132,9 +134,9 @@ struct Iplifc /* binding twixt Ipself and Ipifc */ struct Iplink { - Ipself *local; + Ipself *self; Iplifc *lifc; - Iplink *locallink; /* next link for this local address */ + Iplink *selflink; /* next link for this local address */ Iplink *lifclink; /* next link for this ifc */ ulong expire; Iplink *next; /* free list */ diff --git a/ip/ipifc.c b/ip/ipifc.c index 7a694dc1f2e51cc1bd318362ba5faeccff69075d..88a224b122cf14bf53694487bc76a428071a4125 100644 --- a/ip/ipifc.c +++ b/ip/ipifc.c @@ -23,6 +23,7 @@ extern Fs fs; Medium *media[] = { ðermedium, + &pktmedium, &nullmedium, 0 }; @@ -151,16 +152,18 @@ ipifcunbind(Ipifc *ifc) } wlock(ifc); - if(ipifcgrab(ifc) == 0); - goto out; + /* dissociate routes */ + ifc->ifcid++; + + /* disassociate device */ + (*ifc->m->unbind)(ifc); + memset(ifc->dev, 0, sizeof(ifc->dev)); + ifc->arg = nil; /* hangup queues to stop queuing of packets */ qhangup(ifc->conv->rq, "unbind"); qhangup(ifc->conv->wq, "unbind"); - /* dissociate routes */ - ifc->ifcid++; - /* disassociate logical interfaces */ av[0] = "remove"; av[1] = ip; @@ -172,14 +175,7 @@ ipifcunbind(Ipifc *ifc) ipifcrem(ifc, av, 3, 0); } - /* disassociate device */ - (*ifc->m->unbind)(ifc); - memset(ifc->dev, 0, sizeof(ifc->dev)); - ifc->arg = nil; - ifc->m = &nullmedium; - ifc->unbinding = 0; - -out: + ifc->m = nil; wunlock(ifc); poperror(); return nil; @@ -223,7 +219,7 @@ ipifclocal(Conv *c, char *state, int n) for(lifc = ifc->lifc; lifc; lifc = lifc->next){ m += snprint(state+m, n - m, "%-20.20I ->", lifc->local); for(link = lifc->link; link; link = link->lifclink) - m += snprint(state+m, n - m, " %-20.20I", link->local->a); + m += snprint(state+m, n - m, " %-20.20I", link->self->a); m += snprint(state+m, n - m, "\n"); } runlock(ifc); @@ -272,6 +268,8 @@ ipifccreate(Conv *c) c->wq = qopen(QMAX, 0, 0, 0); ifc = (Ipifc*)c->ptcl; ifc->conv = c; + ifc->unbinding = 0; + ifc->m = nil; } /* @@ -281,10 +279,13 @@ ipifccreate(Conv *c) static void ipifcclose(Conv *c) { - /* - * nothing to do since conversation stays open - * till the device is unbound. - */ + Ipifc *ifc; + Medium *m; + + ifc = (Ipifc*)c->ptcl; + m = ifc->m; + if(m != nil && m->unbindonclose) + ipifcunbind(ifc); unlock(c); } @@ -423,7 +424,7 @@ ipifcrem(Ipifc *ifc, char **argv, int argc, int dolock) /* disassociate any addresses */ while(lifc->link) - remselfcache(ifc, lifc, lifc->link->local->a); + remselfcache(ifc, lifc, lifc->link->self->a); /* remove the route for this logical interface */ if(isv4(ip)) @@ -456,6 +457,8 @@ ipifcaddroute(int vers, uchar *addr, uchar *mask, uchar *gate, int type) if(*cp != nil) { ifc = (Ipifc*)(*cp)->ptcl; m = ifc->m; + if(m == nil) + continue; if(m->addroute != nil) m->addroute(ifc, vers, addr, mask, gate, type); } @@ -473,6 +476,8 @@ ipifcremroute(int vers, uchar *addr, uchar *mask) if(*cp != nil) { ifc = (Ipifc*)(*cp)->ptcl; m = ifc->m; + if(m == nil) + continue; if(m->remroute != nil) m->remroute(ifc, vers, addr, mask); } @@ -603,7 +608,7 @@ addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type) } /* look for a link for this lifc */ - for(lp = p->link; lp; lp = lp->locallink) + for(lp = p->link; lp; lp = lp->selflink) if(lp->lifc == lifc) break; @@ -612,8 +617,8 @@ addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type) lp = smalloc(sizeof(*lp)); lp->ref = 1; lp->lifc = lifc; - lp->local = p; - lp->locallink = p->link; + lp->self = p; + lp->selflink = p->link; p->link = lp; lp->lifclink = lifc->link; lifc->link = lp; @@ -690,7 +695,7 @@ static void remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a) { Ipself *p, **l; - Iplink *lp, *llp, **ill, **lll; + Iplink *link, **l_self, **l_lifc; qlock(&selftab); @@ -709,40 +714,40 @@ remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a) * walk down links from an ifc looking for one * that matches the selftab entry */ - ill = &lifc->link; - for(lp = *ill; lp; lp = *ill){ - if(lp->local == p) + l_lifc = &lifc->link; + for(link = *l_lifc; link; link = *l_lifc){ + if(link->self == p) break; - ill = &lp->lifclink; + l_lifc = &link->lifclink; } - if(lp == nil) + if(link == nil) goto out; /* * walk down the links from the selftab looking for * the one we just found */ - lll = &p->link; - for(llp = *lll; llp; llp = *lll){ - if(llp == lp) + l_self = &p->link; + for(link = *l_self; link; link = *l_self){ + if(link == *(l_lifc)) break; - lll = &lp->locallink; + l_self = &link->selflink; } - if(llp == nil) + if(link == nil) panic("remselfcache"); - if(--(llp->ref) != 0) + if(--(link->ref) != 0) goto out; if((p->type & Rmulti) && ifc->m->remmulti != nil) (*ifc->m->remmulti)(ifc, a, lifc->local); /* ref == 0, remove from both chains and free the link */ - *ill = lp->lifclink; - *lll = llp->locallink; - iplinkfree(lp); + *l_lifc = link->lifclink; + *l_self = link->selflink; + iplinkfree(link); /* remove from routing table */ if(isv4(a)) @@ -1003,59 +1008,6 @@ ipismulticast(uchar *ip) return 0; } -/* - * used to allow on the fly unbinds, return -1 if interface unusable - */ -int -ipifccheckin(Ipifc *ifc, Medium *med) -{ - int rv; - - lock(&ifc->idlock); - if(ifc->unbinding || ifc->m != med) - rv = -1; - else - rv = ++(ifc->ref); - if(ifc->ref < 0) panic("ipifccheckin"); - unlock(&ifc->idlock); - return rv; -} - -void -ipifccheckout(Ipifc *ifc) -{ - lock(&ifc->idlock); - if(--(ifc->ref) == 0) - if(ifc->unbinding) - wakeup(&ifc->wait); - if(ifc->ref < 0) panic("ipifccheckin"); - unlock(&ifc->idlock); -} - -static int -allout(void *x) -{ - Ipifc *ifc = x; - - return ifc->ref == 0; -} - -int -ipifcgrab(Ipifc *ifc) -{ - lock(&ifc->idlock); - if(ifc->unbinding){ - unlock(&ifc->idlock); - return 0; - } - ifc->unbinding = 1; /* after this ref can only go down */ - unlock(&ifc->idlock); - - sleep(&ifc->wait, allout, ifc); - - return 1; -} - /* * add a multicast address to an interface, called with c->car locked */ diff --git a/ip/netlog.c b/ip/netlog.c index 41f6605c23eb9672265ea847b8792daf7b28448a..50f36f917c725a705a6baf955f73bfc5ea722228 100644 --- a/ip/netlog.c +++ b/ip/netlog.c @@ -152,7 +152,6 @@ netlogctl(char* s, int len) int i, n, set; Logflag *f; char *fields[10], *p, buf[256]; - uchar addr[IPaddrlen]; if(len == 0) return Ebadnetctl; diff --git a/ip/nullmedium.c b/ip/nullmedium.c index c4acd3ff5c95f3909c7622db434c5200d235952b..b848d29fbe94574024fcb2ece8c55d427cdc8399 100644 --- a/ip/nullmedium.c +++ b/ip/nullmedium.c @@ -43,4 +43,5 @@ Medium nullmedium = nil, /* flushroute */ nil, /* joinmulti */ nil, /* leave multi */ + 0, /* don't unbind on last close */ }; diff --git a/ip/pktmedium.c b/ip/pktmedium.c index 6a2500bdb7fa4f9dfdb2e0b555ee5fa3a3db9fd3..8c1b6c50675d22889f57681a3feefa7408e8b19f 100644 --- a/ip/pktmedium.c +++ b/ip/pktmedium.c @@ -32,6 +32,7 @@ Medium pktmedium = nil, /* flushroute */ nil, /* joinmulti */ nil, /* leave multi */ + 1, /* unbind on last close */ }; /*