tripmedium.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) 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 }