vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

tripmedium.c (7120B)


      1 #include "u.h"
      2 #include "lib.h"
      3 #include "mem.h"
      4 #include "dat.h"
      5 #include "fns.h"
      6 #include "error.h"
      7 
      8 #include "ip.h"
      9 #include "trip.h"
     10 
     11 static void	tripread(void *a);
     12 static void	tripbind(Ipifc *ifc, int argc, char **argv);
     13 static void	tripunbind(Ipifc *ifc);
     14 static void	tripbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
     15 static void	tripaddmulti(Ipifc *ifc, uchar*, uchar*);
     16 static void	tripremmulti(Ipifc *ifc, uchar*, uchar*);
     17 static void	tripaddroute(Ipifc *ifc, int, uchar*, uchar*, uchar*, int);
     18 static void	tripremroute(Ipifc *ifc, int, uchar*, uchar*);
     19 static void	tripares(Fs*, int, uchar*, uchar*, int, int);
     20 
     21 Medium tripmedium =
     22 {
     23 .name=		"trip",
     24 .mintu=	20,
     25 .maxtu=	64*1024,
     26 .maclen=	LCIMACSIZE,
     27 .bind=		tripbind,
     28 .unbind=	tripunbind,
     29 .bwrite=	tripbwrite,
     30 .addmulti=	tripaddmulti,
     31 .remmulti=	tripremmulti,
     32 .addroute=	tripaddroute,
     33 .remroute=	tripremroute,
     34 .ares=		tripares,
     35 };
     36 
     37 typedef struct	Tripinfo Tripinfo;
     38 struct Tripinfo
     39 {
     40 	Fs*	fs;		/* my instance of the IP stack */
     41 	Ipifc*	ifc;		/* IP interface */
     42 	Card*	dev;
     43 	Proc*	readp;		/* reading process */
     44 	Chan*	mchan;		/* Data channel */
     45 };
     46 
     47 /*
     48  *  called to bind an IP ifc to an ethernet device
     49  *  called with ifc qlock'd
     50  */
     51 static void
     52 tripbind(Ipifc *ifc, int argc, char **argv)
     53 {
     54 	int fd;
     55 	Chan *mchan;
     56 	Tripinfo *er;
     57 
     58 	if(argc < 2)
     59 		error(Ebadarg);
     60 
     61 	fd = kopen(argv[2], ORDWR);
     62 	if(fd < 0)
     63 		error("trip open failed");
     64 
     65 	mchan = fdtochan(up->env->fgrp, fd, ORDWR, 0, 1);
     66 	kclose(fd);
     67 
     68 	if(devtab[mchan->type]->dc != 'T') {
     69 		cclose(mchan);
     70 		error(Enoport);
     71 	}
     72 
     73 	er = smalloc(sizeof(*er));
     74 	er->mchan = mchan;
     75 	er->ifc = ifc;
     76 	er->dev = tripsetifc(mchan, ifc);
     77 	er->fs = ifc->conv->p->f;
     78 
     79 	ifc->arg = er;
     80 
     81 	kproc("tripread", tripread, ifc);
     82 }
     83 
     84 /*
     85  *  called with ifc qlock'd
     86  */
     87 static void
     88 tripunbind(Ipifc *ifc)
     89 {
     90 	Tripinfo *er = ifc->arg;
     91 /*
     92 	if(er->readp)
     93 		postnote(er->readp, 1, "unbind", 0);
     94 */
     95 	tsleep(&up->sleep, return0, 0, 300);
     96 
     97 	if(er->mchan != nil)
     98 		cclose(er->mchan);
     99 
    100 	free(er);
    101 }
    102 
    103 /*
    104  *  called by ipoput with a single block to write
    105  */
    106 static void
    107 tripbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
    108 {
    109 	Tripinfo *er = ifc->arg;
    110 
    111 	/*
    112 	 * Packet is rerouted at linecard
    113 	 * so the gateway is ignored
    114 	 */
    115 	USED(ip);
    116 	USED(version);
    117 
    118 	if(waserror()) {
    119 		print("tripwrite failed\n");
    120 		return;
    121 	}
    122 
    123 	devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
    124 	poperror();
    125 	ifc->out++;
    126 }
    127 
    128 /*
    129  *  process to read from the trip interface
    130  */
    131 static void
    132 tripread(void *a)
    133 {
    134 	Ipifc *ifc;
    135 	Block *bp;
    136 	Tripinfo *er;
    137 
    138 	ifc = a;
    139 	er = ifc->arg;
    140 	er->readp = up;	/* hide identity under a rock for unbind */
    141 
    142 	for(;;) {
    143 		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
    144 		ifc->in++;
    145 		ipiput4(er->fs, ifc, bp);
    146 	}
    147 
    148 	pexit("hangup", 1);
    149 }
    150 
    151 static void
    152 tripaddroute(Ipifc *ifc, int v, uchar *addr, uchar *mask, uchar *gate, int t)
    153 {
    154 	int alen;
    155 	MTroute mtr;
    156 	Tripinfo *tinfo;
    157 
    158 	tinfo = ifc->arg;
    159 	if(!tinfo->dev->routing)
    160 		return;
    161 
    162 	/*
    163 	 * Multicast addresses are handled on the linecard by
    164 	 * the multicast port driver, so the route load is dumped.
    165 	 *	loaded by addmulti/remmulti for SBC routes
    166 	 *		  joinmulti/leavemulti for inter LC
    167 	 */
    168 	if(ipismulticast(addr))
    169 		return;
    170 
    171 	mtr.type = T_ROUTEADMIN;
    172 	if(v & Rv4) {
    173 		mtr.op = RTADD4;
    174 		alen = IPv4addrlen;
    175 	}
    176 	else {
    177 		mtr.op = RTADD6;
    178 		alen = IPaddrlen;
    179 	}
    180 	mtr.rtype = t;
    181 	memmove(mtr.addr, addr, alen);
    182 	memmove(mtr.mask, mask, alen);
    183 	memmove(mtr.gate, gate, alen);
    184 
    185 	i2osend(tinfo->dev, &mtr, sizeof(mtr));
    186 }
    187 
    188 static void
    189 tripremroute(Ipifc *ifc, int v, uchar *addr, uchar *mask)
    190 {
    191 	int alen;
    192 	MTroute mtr;
    193 	Tripinfo *tinfo;
    194 
    195 	tinfo = ifc->arg;
    196 	if(!tinfo->dev->routing)
    197 		return;
    198 
    199 	if(ipismulticast(addr))
    200 		return;
    201 
    202 	mtr.type = T_ROUTEADMIN;
    203 	if(v & Rv4) {
    204 		mtr.op = RTDEL4;
    205 		alen = IPv4addrlen;
    206 	}
    207 	else {
    208 		mtr.op = RTDEL6;
    209 		alen = IPaddrlen;
    210 	}
    211 	memmove(mtr.addr, addr, alen);
    212 	memmove(mtr.mask, mask, alen);
    213 
    214 	i2osend(tinfo->dev, &mtr, sizeof(mtr));
    215 }
    216 
    217 static void
    218 tripxmitroute(Route *r, Routewalk *rw)
    219 {
    220 	int nifc;
    221 	char t[5];
    222 	uchar a[IPaddrlen], m[IPaddrlen], g[IPaddrlen];
    223 
    224 	convroute(r, a, m, g, t, &nifc);
    225 	if(!(r->type & Rv4)) {
    226 		tripaddroute(rw->state, 0, a, m, g, r->type);
    227 		return;
    228 	}
    229 
    230 	tripaddroute(rw->state, Rv4, a+IPv4off, m+IPv4off, g+IPv4off, r->type);
    231 }
    232 
    233 static void
    234 sendifcinfo(Ipifc *dest)
    235 {
    236 	Conv **cp, **e;
    237 	Iplifc *l;
    238 	Ipifc *ifc;
    239 	MTifctl mtc;
    240 	Tripinfo *tinfo, *oinfo;
    241 	Proto *p;
    242 
    243 	tinfo = dest->arg;
    244 
    245 	/* Install interfaces */
    246 	p = tinfo->fs->ipifc;
    247 	e = &p->conv[p->nc];
    248 	for(cp = p->conv; cp < e; cp++) {
    249 
    250 		if(*cp == nil)
    251 			continue;
    252 
    253 		ifc = (Ipifc*)(*cp)->ptcl;
    254 		if(dest == ifc)
    255 			continue;
    256 
    257 		mtc.type = T_CTLIFADMIN;
    258 		mtc.maxtu = ifc->maxtu;
    259 		mtc.mintu = ifc->mintu;
    260 
    261 		mtc.port = 0;
    262 		if(ifc->m == &tripmedium) {
    263 			oinfo = ifc->arg;
    264 			mtc.port = oinfo->dev->bar[0].bar;
    265 		}
    266 
    267 		for(l = ifc->lifc; l != nil; l = l->next) {
    268 			if(isv4(l->local)) {
    269 				mtc.op = IFADD4;
    270 				memmove(mtc.addr, l->local+IPv4off, IPv4addrlen);
    271 				memmove(mtc.mask, l->mask+IPv4off, IPv4addrlen);
    272 			}
    273 			else {
    274 				mtc.op = IFADD6;
    275 				memmove(mtc.addr, l->local, sizeof(mtc.addr));
    276 				memmove(mtc.mask, l->mask, sizeof(mtc.mask));
    277 			}
    278 
    279 			i2osend(tinfo->dev, &mtc, sizeof(mtc));
    280 		}
    281 	}
    282 }
    283 
    284 void
    285 tripsync(Ipifc *ifc)
    286 {
    287 	Routewalk rw;
    288 
    289 	if(ifc == nil) {
    290 		print("tripsync: interface not bound\n");
    291 		return;
    292 	}
    293 
    294 	/* Mirror the route table into the lincard */
    295 	rw.o = 0;
    296 	rw.n = (1<<22);
    297 	rw.state = ifc;
    298 	rw.walk = tripxmitroute;
    299 
    300 	ipwalkroutes(ifc->conv->p->f, &rw);
    301 
    302 	/*
    303 	 * Tell the linecard about interfaces that already
    304 	 * exist elsewhere
    305 	 */
    306 	sendifcinfo(ifc);
    307 }
    308 
    309 /* Tell a line card the SBC is interested in listening
    310  * to a multicast address
    311  */
    312 static void
    313 tripaddmulti(Ipifc *ifc, uchar *addr, uchar *ifca)
    314 {
    315 	MTmultiears mt;
    316 	Tripinfo *tinfo;
    317 
    318 	/* print("tripaddmulti %I %I\n", addr, ifca); /**/
    319 
    320 	tinfo = ifc->arg;
    321 	if(!tinfo->dev->routing)
    322 		return;
    323 
    324 	mt.type = T_MULTIEAR;
    325 	mt.op = ADDMULTI;
    326 	memmove(mt.addr, addr, sizeof(mt.addr));
    327 	memmove(mt.ifca, ifca, sizeof(mt.ifca));
    328 
    329 	i2osend(tinfo->dev, &mt, sizeof(mt));
    330 }
    331 
    332 /* Tell a line card the SBC is no longer interested in listening
    333  * to a multicast address
    334  */
    335 static void
    336 tripremmulti(Ipifc *ifc, uchar *addr, uchar *ifca)
    337 {
    338 	MTmultiears mt;
    339 	Tripinfo *tinfo;
    340 
    341 	tinfo = ifc->arg;
    342 	if(!tinfo->dev->routing)
    343 		return;
    344 
    345 	mt.type = T_MULTIEAR;
    346 	mt.op = REMMULTI;
    347 	memmove(mt.addr, addr, sizeof(mt.addr));
    348 	memmove(mt.ifca, ifca, sizeof(mt.ifca));
    349 
    350 	i2osend(tinfo->dev, &mt, sizeof(mt));
    351 }
    352 
    353 static void
    354 tripares(Fs *fs, int vers, uchar *ip, uchar *mac, int l, int)
    355 {
    356 	Route *r;
    357 	Ipifc *ifc;
    358 	MTaresenter ta;
    359 	Tripinfo *tinfo;
    360 	uchar v6ip[IPaddrlen];
    361 
    362 	if(vers == V4) {
    363 		r = v4lookup(fs, ip);
    364 		v4tov6(v6ip, ip);
    365 		ip = v6ip;
    366 	}
    367 	else
    368 		r = v6lookup(fs, ip);
    369 
    370 	if(r == nil) {
    371 		print("tripares: no route for entry\n");
    372 		return;
    373 	}
    374 
    375 	ifc = r->ifc;
    376 
    377 	tinfo = ifc->arg;
    378 	if(!tinfo->dev->routing)
    379 		return;
    380 
    381 	if(vers == V4) {
    382 		v4tov6(v6ip, ip);
    383 		ip = v6ip;
    384 	}
    385 
    386 	ta.type = T_ARESENTER;
    387 	ta.maclen = l;
    388 	memmove(ta.addr, ip, IPaddrlen);
    389 	memmove(ta.amac, mac, l);
    390 
    391 	i2osend(tinfo->dev, &ta, sizeof(ta));
    392 }
    393 
    394 void
    395 tripmediumlink(void)
    396 {
    397 	addipmedium(&tripmedium);
    398 }