The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ip/tripmedium.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include "u.h"
    2 #include "../port/lib.h"
    3 #include "mem.h"
    4 #include "dat.h"
    5 #include "fns.h"
    6 #include "../port/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 }

Cache object: 6acad5d2b763588f0a97c307ceb33c35


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.