123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "../port/error.h"
- #include "ip.h"
- #include "trip.h"
- static void tripread(void *a);
- static void tripbind(Ipifc *ifc, int argc, char **argv);
- static void tripunbind(Ipifc *ifc);
- static void tripbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
- static void tripaddmulti(Ipifc *ifc, uchar*, uchar*);
- static void tripremmulti(Ipifc *ifc, uchar*, uchar*);
- static void tripaddroute(Ipifc *ifc, int, uchar*, uchar*, uchar*, int);
- static void tripremroute(Ipifc *ifc, int, uchar*, uchar*);
- static void tripares(Fs*, int, uchar*, uchar*, int, int);
- Medium tripmedium =
- {
- .name= "trip",
- .mintu= 20,
- .maxtu= 64*1024,
- .maclen= LCIMACSIZE,
- .bind= tripbind,
- .unbind= tripunbind,
- .bwrite= tripbwrite,
- .addmulti= tripaddmulti,
- .remmulti= tripremmulti,
- .addroute= tripaddroute,
- .remroute= tripremroute,
- .ares= tripares,
- };
- typedef struct Tripinfo Tripinfo;
- struct Tripinfo
- {
- Fs* fs; /* my instance of the IP stack */
- Ipifc* ifc; /* IP interface */
- Card* dev;
- Proc* readp; /* reading process */
- Chan* mchan; /* Data channel */
- };
- /*
- * called to bind an IP ifc to an ethernet device
- * called with ifc qlock'd
- */
- static void
- tripbind(Ipifc *ifc, int argc, char **argv)
- {
- int fd;
- Chan *mchan;
- Tripinfo *er;
- if(argc < 2)
- error(Ebadarg);
- fd = kopen(argv[2], ORDWR);
- if(fd < 0)
- error("trip open failed");
- mchan = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);
- kclose(fd);
- if(devtab[mchan->type]->dc != 'T') {
- cclose(mchan);
- error(Enoport);
- }
- er = smalloc(sizeof(*er));
- er->mchan = mchan;
- er->ifc = ifc;
- er->dev = tripsetifc(mchan, ifc);
- er->fs = ifc->conv->p->f;
- ifc->arg = er;
- kproc("tripread", tripread, ifc);
- }
- /*
- * called with ifc qlock'd
- */
- static void
- tripunbind(Ipifc *ifc)
- {
- Tripinfo *er = ifc->arg;
- /*
- if(er->readp)
- postnote(er->readp, 1, "unbind", 0);
- */
- tsleep(&up->sleep, return0, 0, 300);
- if(er->mchan != nil)
- cclose(er->mchan);
- free(er);
- }
- /*
- * called by ipoput with a single block to write
- */
- static void
- tripbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
- {
- Tripinfo *er = ifc->arg;
- /*
- * Packet is rerouted at linecard
- * so the gateway is ignored
- */
- USED(ip);
- USED(version);
- if(waserror()) {
- print("tripwrite failed\n");
- return;
- }
- devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
- poperror();
- ifc->out++;
- }
- /*
- * process to read from the trip interface
- */
- static void
- tripread(void *a)
- {
- Ipifc *ifc;
- Block *bp;
- Tripinfo *er;
- ifc = a;
- er = ifc->arg;
- er->readp = up; /* hide identity under a rock for unbind */
- for(;;) {
- bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
- ifc->in++;
- ipiput4(er->fs, ifc, bp);
- }
- pexit("hangup", 1);
- }
- static void
- tripaddroute(Ipifc *ifc, int v, uchar *addr, uchar *mask, uchar *gate, int t)
- {
- int alen;
- MTroute mtr;
- Tripinfo *tinfo;
- tinfo = ifc->arg;
- if(!tinfo->dev->routing)
- return;
- /*
- * Multicast addresses are handled on the linecard by
- * the multicast port driver, so the route load is dumped.
- * loaded by addmulti/remmulti for SBC routes
- * joinmulti/leavemulti for inter LC
- */
- if(ipismulticast(addr))
- return;
- mtr.type = T_ROUTEADMIN;
- if(v & Rv4) {
- mtr.op = RTADD4;
- alen = IPv4addrlen;
- }
- else {
- mtr.op = RTADD6;
- alen = IPaddrlen;
- }
- mtr.rtype = t;
- memmove(mtr.addr, addr, alen);
- memmove(mtr.mask, mask, alen);
- memmove(mtr.gate, gate, alen);
- i2osend(tinfo->dev, &mtr, sizeof(mtr));
- }
- static void
- tripremroute(Ipifc *ifc, int v, uchar *addr, uchar *mask)
- {
- int alen;
- MTroute mtr;
- Tripinfo *tinfo;
- tinfo = ifc->arg;
- if(!tinfo->dev->routing)
- return;
- if(ipismulticast(addr))
- return;
- mtr.type = T_ROUTEADMIN;
- if(v & Rv4) {
- mtr.op = RTDEL4;
- alen = IPv4addrlen;
- }
- else {
- mtr.op = RTDEL6;
- alen = IPaddrlen;
- }
- memmove(mtr.addr, addr, alen);
- memmove(mtr.mask, mask, alen);
- i2osend(tinfo->dev, &mtr, sizeof(mtr));
- }
- static void
- tripxmitroute(Route *r, Routewalk *rw)
- {
- int nifc;
- char t[5];
- uchar a[IPaddrlen], m[IPaddrlen], g[IPaddrlen];
- convroute(r, a, m, g, t, &nifc);
- if(!(r->type & Rv4)) {
- tripaddroute(rw->state, 0, a, m, g, r->type);
- return;
- }
- tripaddroute(rw->state, Rv4, a+IPv4off, m+IPv4off, g+IPv4off, r->type);
- }
- static void
- sendifcinfo(Ipifc *dest)
- {
- Conv **cp, **e;
- Iplifc *l;
- Ipifc *ifc;
- MTifctl mtc;
- Tripinfo *tinfo, *oinfo;
- Proto *p;
- tinfo = dest->arg;
- /* Install interfaces */
- p = tinfo->fs->ipifc;
- e = &p->conv[p->nc];
- for(cp = p->conv; cp < e; cp++) {
- if(*cp == nil)
- continue;
- ifc = (Ipifc*)(*cp)->ptcl;
- if(dest == ifc)
- continue;
- mtc.type = T_CTLIFADMIN;
- mtc.maxtu = ifc->maxtu;
- mtc.mintu = ifc->mintu;
- mtc.port = 0;
- if(ifc->m == &tripmedium) {
- oinfo = ifc->arg;
- mtc.port = oinfo->dev->bar[0].bar;
- }
- for(l = ifc->lifc; l != nil; l = l->next) {
- if(isv4(l->local)) {
- mtc.op = IFADD4;
- memmove(mtc.addr, l->local+IPv4off, IPv4addrlen);
- memmove(mtc.mask, l->mask+IPv4off, IPv4addrlen);
- }
- else {
- mtc.op = IFADD6;
- memmove(mtc.addr, l->local, sizeof(mtc.addr));
- memmove(mtc.mask, l->mask, sizeof(mtc.mask));
- }
- i2osend(tinfo->dev, &mtc, sizeof(mtc));
- }
- }
- }
- void
- tripsync(Ipifc *ifc)
- {
- Routewalk rw;
- if(ifc == nil) {
- print("tripsync: interface not bound\n");
- return;
- }
- /* Mirror the route table into the lincard */
- rw.o = 0;
- rw.n = (1<<22);
- rw.state = ifc;
- rw.walk = tripxmitroute;
- ipwalkroutes(ifc->conv->p->f, &rw);
- /*
- * Tell the linecard about interfaces that already
- * exist elsewhere
- */
- sendifcinfo(ifc);
- }
- /* Tell a line card the SBC is interested in listening
- * to a multicast address
- */
- static void
- tripaddmulti(Ipifc *ifc, uchar *addr, uchar *ifca)
- {
- MTmultiears mt;
- Tripinfo *tinfo;
- /* print("tripaddmulti %I %I\n", addr, ifca); /**/
- tinfo = ifc->arg;
- if(!tinfo->dev->routing)
- return;
- mt.type = T_MULTIEAR;
- mt.op = ADDMULTI;
- memmove(mt.addr, addr, sizeof(mt.addr));
- memmove(mt.ifca, ifca, sizeof(mt.ifca));
- i2osend(tinfo->dev, &mt, sizeof(mt));
- }
- /* Tell a line card the SBC is no longer interested in listening
- * to a multicast address
- */
- static void
- tripremmulti(Ipifc *ifc, uchar *addr, uchar *ifca)
- {
- MTmultiears mt;
- Tripinfo *tinfo;
- tinfo = ifc->arg;
- if(!tinfo->dev->routing)
- return;
- mt.type = T_MULTIEAR;
- mt.op = REMMULTI;
- memmove(mt.addr, addr, sizeof(mt.addr));
- memmove(mt.ifca, ifca, sizeof(mt.ifca));
- i2osend(tinfo->dev, &mt, sizeof(mt));
- }
- static void
- tripares(Fs *fs, int vers, uchar *ip, uchar *mac, int l, int)
- {
- Route *r;
- Ipifc *ifc;
- MTaresenter ta;
- Tripinfo *tinfo;
- uchar v6ip[IPaddrlen];
- if(vers == V4) {
- r = v4lookup(fs, ip);
- v4tov6(v6ip, ip);
- ip = v6ip;
- }
- else
- r = v6lookup(fs, ip);
- if(r == nil) {
- print("tripares: no route for entry\n");
- return;
- }
- ifc = r->ifc;
- tinfo = ifc->arg;
- if(!tinfo->dev->routing)
- return;
- if(vers == V4) {
- v4tov6(v6ip, ip);
- ip = v6ip;
- }
- ta.type = T_ARESENTER;
- ta.maclen = l;
- memmove(ta.addr, ip, IPaddrlen);
- memmove(ta.amac, mac, l);
- i2osend(tinfo->dev, &ta, sizeof(ta));
- }
- void
- tripmediumlink(void)
- {
- addipmedium(&tripmedium);
- }
|