📄 tripmedium.c
字号:
#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 voidtripbind(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 voidtripunbind(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 voidtripbwrite(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 voidtripread(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 voidtripaddroute(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 voidtripremroute(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 voidtripxmitroute(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 voidsendifcinfo(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)); } }}voidtripsync(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 voidtripaddmulti(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 voidtripremmulti(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 voidtripares(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));}voidtripmediumlink(void){ addipmedium(&tripmedium);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -