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 }