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/norma/ipc_ether.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 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1991,1992 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        ipc_ether.c,v $
   29  * Revision 2.9  93/05/15  19:33:40  mrt
   30  *      machparam.h -> machspl.h
   31  * 
   32  * Revision 2.8  93/01/14  17:53:37  danner
   33  *      64bit cleanup. Proper spl typing.
   34  *      [92/12/01            af]
   35  * 
   36  * Revision 2.7  92/03/10  16:27:23  jsb
   37  *      Merged in norma branch changes as of NORMA_MK7.
   38  *      [92/03/09  12:48:43  jsb]
   39  * 
   40  * Revision 2.5.3.3  92/01/21  21:51:03  jsb
   41  *      Use a field in fragment header to record true length, since udp
   42  *      length field can no longer be trusted due to ETHERMIN logic.
   43  *      [92/01/21  21:30:47  jsb]
   44  * 
   45  *      Don't send packets smaller than ETHERMIN.
   46  *      [92/01/21  19:35:34  jsb]
   47  * 
   48  *      Changed parameters to netipc_net_packet in preparation for saving
   49  *      packets that arrive before a new recv_netvec has been supplied.
   50  *      Added fragment information to debugging printfs.
   51  *      [92/01/17  18:36:34  jsb]
   52  * 
   53  *      Moved node_incarnation declaration from here to norma/ipc_net.c.
   54  *      [92/01/17  14:38:17  jsb]
   55  * 
   56  *      Fixed udp checksum bug. Drop packets whose length (as claimed by
   57  *      driver) differs from length as recorded in udp header.
   58  *      Set recv_netvec to zero before calling netipc_recv_intr
   59  *      so that any new incoming packets won't corrupt netvec.
   60  *      (This shouldn't happen anyway because interrupts will be blocked.)
   61  *      Panic if fragment send completions occur out-of-order.
   62  *      (This also shouldn't happen.)
   63  *      [92/01/16  22:05:57  jsb]
   64  * 
   65  *      Replaced small, incomprehensible, and incorrect loop in netipc_send
   66  *      responsible for copying from fragments into vector elements with
   67  *      comprehensible and correct code. De-linted.
   68  *      [92/01/14  21:45:52  jsb]
   69  * 
   70  *      Moved c_netipc_frag_drop* count definitions here from norma/ipc_net.c.
   71  *      [92/01/10  20:37:07  jsb]
   72  * 
   73  * Revision 2.5.3.2  92/01/09  18:45:07  jsb
   74  *      Added netipc_node_valid.
   75  *      From durriya@ri.osf.org: added norma_ether_boot_info.
   76  *      [92/01/08  16:45:45  jsb]
   77  * 
   78  *      Added comment about reentrancy above netipc_send.
   79  *      Replaced small, incomprehensible, and incorrect loop in netipc_send
   80  *      responsible for copying from vector elements into fragments with
   81  *      comprehensible and correct code.
   82  *      [92/01/08  10:02:33  jsb]
   83  * 
   84  *      Moved ntohl, etc. here from norma/ipc_net.c.
   85  *      [92/01/04  22:11:30  jsb]
   86  * 
   87  * Revision 2.5.3.1  92/01/03  16:37:12  jsb
   88  *      Made node_incarnation be unsigned long, and changed its name.
   89  *      (It used to be node_instance. I also changed the log message below.)
   90  *      [91/12/29  10:10:30  jsb]
   91  * 
   92  *      Added code to set node_incarnation, using config info if available;
   93  *      node_incarnation will allow norma ipc to cope with node crashes.
   94  *      Fixed code that waits for nd table info to arrive from network;
   95  *      it now detects and processes the first packet that arrives.
   96  *      Split nd_reply routine into nd_reply, which calls either
   97  *      nd_table_reply or nd_config_reply based on magic number.
   98  *      Removed magic number checking code from the latter two routines,
   99  *      and removed call to nd_config from netipc_net_packet.
  100  *      [91/12/27  17:15:00  jsb]
  101  * 
  102  *      Corrected log. Fixed merge error in nd_reply.
  103  *      [91/12/24  14:34:55  jsb]
  104  * 
  105  * Revision 2.5  91/12/14  14:32:44  jsb
  106  *      Picked up bootconfig code from sjs@osf.org.
  107  * 
  108  * Revision 2.4  91/11/14  16:52:20  rpd
  109  *      Added XLAS/XLA/XSA macros to solve alignment problems.
  110  *      [91/11/00            jsb]
  111  * 
  112  * Revision 2.3  91/08/28  11:15:54  jsb
  113  *      Generalized netipc_swap_device code.
  114  *      [91/08/16  14:30:15  jsb]
  115  * 
  116  *      Added fields to support nrp (node table resolution protocol),
  117  *      allowing removal of hardwired table of node/ip/ether addresses.
  118  *      [91/08/15  08:58:04  jsb]
  119  * 
  120  * Revision 2.2  91/08/03  18:19:14  jsb
  121  *      Restructured to work with completely unmodified ethernet driver.
  122  *      Added code to automatically find a usable ethernet device.
  123  *      Removed NODE_BY_SUBNET case. Perform initialization earlier.
  124  *      [91/08/02  14:21:08  jsb]
  125  * 
  126  *      Use IO_LOANED technology.
  127  *      [91/07/27  22:56:42  jsb]
  128  * 
  129  *      Added fragmentation.
  130  *      [91/07/27  18:54:37  jsb]
  131  * 
  132  *      First checkin.
  133  *      [91/07/24  23:38:03  jsb]
  134  * 
  135  */
  136 /*
  137  *      File:   norma/ipc_ether.c
  138  *      Author: Joseph S. Barrera III
  139  *      Date:   1991
  140  *
  141  *      Functions for NORMA_IPC over ethernet.
  142  */
  143 
  144 #include <machine/machspl.h>
  145 #include <vm/vm_kern.h>
  146 #include <vm/vm_page.h>
  147 #include <mach/vm_param.h>
  148 #include <mach/port.h>
  149 #include <mach/message.h>
  150 #include <kern/assert.h>
  151 #include <kern/host.h>
  152 #include <kern/sched_prim.h>
  153 #include <kern/ipc_sched.h>
  154 #include <kern/ipc_kobject.h>
  155 #include <kern/zalloc.h>
  156 #include <ipc/ipc_mqueue.h>
  157 #include <ipc/ipc_thread.h>
  158 #include <ipc/ipc_kmsg.h>
  159 #include <ipc/ipc_port.h>
  160 #include <ipc/ipc_pset.h>
  161 #include <ipc/ipc_space.h>
  162 #include <ipc/ipc_marequest.h>
  163 #include <device/io_req.h>
  164 #include <device/if_hdr.h>
  165 #include <device/net_io.h>
  166 #include <device/net_status.h>
  167 #include <norma/ipc_net.h>
  168 #include <norma/ipc_ether.h>
  169 
  170 #define MAXFRAG                 8
  171 #define FHP_OVERHEAD            sizeof(struct netipc_fragment_header)
  172 
  173 typedef struct netipc_fragment_header   *netipc_fragment_header_t;
  174 
  175 struct netipc_fragment_header {
  176         unsigned short  f_offset;
  177         unsigned char   f_id;
  178         unsigned char   f_last;
  179         unsigned long   f_length;
  180 };
  181 
  182 int NoiseEther = 0;
  183 
  184 struct io_req                   netipc_ior[MAXFRAG];
  185 char                            netipc_ether_buf[MAXFRAG * ETHERMTU];
  186 
  187 struct netvec                   *recv_netvec = 0;
  188 int                             recv_netvec_count;
  189 
  190 /*
  191  * Quick-and-dirty macros for getting around alignment problems
  192  * XSA/XLA -> Transfer Short/Long in an Alignment friendly way.
  193  * XLAS is statement form of XLA which includes a temporary declaration,
  194  * allowing second parameter to be an arbitary (aligned) expression.
  195  */
  196 #define XSA(a,b,o)      (*(o+(short *)&(a)) = *(o+(short *)&(b)))
  197 #define XLA(a,b)        (XSA((a),(b),0),XSA((a),(b),1))
  198 #define XLAS(a,b)       {long _l = *(long *)(b); XLA((a),_l);}
  199 
  200 #define BCOPY(src, dst, len)    bcopy((char *)(src), (char *)(dst), (int)(len))
  201 #define HTONS(s)                htons((unsigned short)(s))
  202 #define NTOHS(s)                ntohs((unsigned short)(s))
  203 #define HTONL(l)                htonl((unsigned long)(l))
  204 #define NTOHL(l)                ntohl((unsigned long)(l))
  205 
  206 /*
  207  * Definitions for ntohl, etc. for architectures that don't otherwise
  208  * provide them.
  209  */
  210 #if     mips || lint
  211 unsigned long
  212 ntohl(x)
  213         register unsigned long x;
  214 {
  215         return (((x & 0x000000ff) << 24)|
  216                 ((x & 0x0000ff00) <<  8)|
  217                 ((x & 0x00ff0000) >>  8)|
  218                 ((x & 0xff000000) >> 24));
  219 }
  220 
  221 unsigned long
  222 htonl(x)
  223         register unsigned long x;
  224 {
  225         return (((x & 0x000000ff) << 24)|
  226                 ((x & 0x0000ff00) <<  8)|
  227                 ((x & 0x00ff0000) >>  8)|
  228                 ((x & 0xff000000) >> 24));
  229 }
  230 
  231 unsigned short
  232 ntohs(x)
  233         register unsigned short x;
  234 {
  235         return (((x & 0x00ff) << 8)|
  236                 ((x & 0xff00) >> 8));
  237 }
  238 
  239 unsigned short
  240 htons(x)
  241         register unsigned short x;
  242 {
  243         return (((x & 0x00ff) << 8)|
  244                 ((x & 0xff00) >> 8));
  245 }
  246 #endif
  247 
  248 /*
  249  * Netipc_recv_fragment_ip_src is 0 if no current frag.
  250  * If we get packet from ip_src which is not a completing frag,
  251  * we should ask for missing frags. This is therefor a sender timeout driven
  252  * mechanism, tied in with higher level timeouts.
  253  *
  254  * We should have several pages for reassembly. This should be tied in with
  255  * the ability to subsitute buffers of same size or smaller.
  256  * E.g. substituting small kmsgs for pages.
  257  *
  258  * For now, if a frag assembly is in progress, we drop everything
  259  * else aimed at us. An immediate refinement would be to have one
  260  * page reserved for reassembly, leaving another for recording nacks.
  261  *
  262  * Maybe upper level should be allowed to provide several receive buffers
  263  * and we find best fit. That would seem to minimize our knowledge
  264  * of what buffers are all about.
  265  */
  266 
  267 int                             netipc_recv_fragment_ip_src;
  268 int                             netipc_recv_fragment_f_id;
  269 
  270 int netipc_ip_id = 1;
  271 
  272 #define NODE_INVALID    -1
  273 int _node_self = NODE_INVALID;
  274 extern unsigned long node_incarnation;
  275 struct node_addr *node_self_addr;
  276 
  277 #define MAX_NODE_TABLE_SIZE     256
  278 
  279 struct node_addr        node_table[MAX_NODE_TABLE_SIZE];
  280 int                     node_table_size = 0;
  281 
  282 #define NODE_ID(index)  (index)
  283 
  284 struct node_addr *
  285 node_addr_by_node(node)
  286         unsigned long node;
  287 {
  288         return &node_table[node];
  289 }
  290 
  291 boolean_t
  292 netipc_node_valid(node)
  293         unsigned long node;
  294 {
  295         return (node < node_table_size);
  296 }
  297 
  298 node_self()
  299 {
  300         if (_node_self == NODE_INVALID) {
  301                 printf("... premature node_self() call\n");
  302                 netipc_network_init();
  303         }
  304         if (_node_self == NODE_INVALID) {
  305                 panic("node_self: I don't know what node I am\n");
  306         }
  307         return _node_self;
  308 }
  309 
  310 #if 1
  311 /* debugging */
  312 node_id(node_ether_addr)
  313         unsigned short *node_ether_addr;
  314 {
  315         int i;
  316 
  317         if (node_table_size == 0) {
  318                 panic("bad node_table_size\n");
  319         }
  320         for (i = 0; i < node_table_size; i++) {
  321                 if (node_ether_addr[0] == node_table[i].node_ether_addr[0] &&
  322                     node_ether_addr[1] == node_table[i].node_ether_addr[1] &&
  323                     node_ether_addr[2] == node_table[i].node_ether_addr[2]) {
  324                         return NODE_ID(i);
  325                 }
  326         }
  327         return NODE_INVALID;
  328 }
  329 
  330 node_ip_id(ip_addr)
  331         unsigned long ip_addr;
  332 {
  333         int i;
  334 
  335         if (node_table_size == 0) {
  336                 panic("bad node_table_size\n");
  337         }
  338         for (i = 0; i < node_table_size; i++) {
  339                 if (node_table[i].node_ip_addr == ip_addr) {
  340                         return NODE_ID(i);
  341                 }
  342         }
  343         return NODE_INVALID;
  344 }
  345 #endif
  346 
  347 struct dev_ops *netipc_device;
  348 int netipc_device_unit = 0;
  349 
  350 #define is_nulldev(func)        ((func)==nodev || (func)==nulldev)
  351 
  352 unsigned long eaddr_l[2];       /* XXX */
  353 
  354 char netipc_boot_config[BOOT_CONFIG_SIZE];      /* boot configuration block */
  355 
  356 char *
  357 norma_ether_boot_info()
  358 {
  359         return netipc_boot_config;
  360 }
  361 
  362 netipc_network_init()
  363 {
  364         unsigned long count;
  365         int unit = netipc_device_unit;  /* XXX */
  366         struct dev_ops *dp;
  367 
  368         /*
  369          * Return if already initialized.
  370          */
  371         if (netipc_device) {
  372                 return;
  373         }
  374 
  375         /*
  376          * Look for a network device.
  377          */
  378         dev_search(dp) {
  379                 if (is_nulldev(dp->d_write) ||
  380                     is_nulldev(dp->d_getstat) ||
  381                     ! is_nulldev(dp->d_read)) {
  382                         continue;
  383                 }
  384                 if ((*dp->d_open)(unit, 0) != 0) {
  385                         /*
  386                          * Open failed. Try another one.
  387                          */
  388                         continue;
  389                 }
  390                 if ((*dp->d_getstat)(unit, NET_ADDRESS, eaddr_l, &count) == 0){
  391                         /*
  392                          * Success!
  393                          */
  394                         netipc_device = dp;
  395                         printf("netipc: using %s%d\n",
  396                                netipc_device->d_name,
  397                                netipc_device_unit);
  398                         break;
  399                 }
  400                 /*
  401                  * Opened the wrong device. Close and try another one.
  402                  */
  403                 if (dp->d_close) {
  404                         (*dp->d_close)(unit);
  405                 }
  406         }
  407 
  408         if (! netipc_device) {
  409                 panic("netipc_network_init: could not find network device\n");
  410         }
  411 
  412         /*
  413          * Set address and calculate node number.
  414          */
  415         eaddr_l[0] = NTOHL(eaddr_l[0]);
  416         eaddr_l[1] = NTOHL(eaddr_l[1]);
  417         printf("netipc: waiting for node table\n");
  418         for (;;) {
  419                 spl_t s;
  420 
  421                 nd_request();
  422                 s = splsched();
  423                 if (node_self_addr) {
  424                         splx(s);
  425                         break;
  426                 }
  427                 assert_wait((vm_offset_t) &node_self_addr, TRUE);
  428                 thread_set_timeout(5 * hz);
  429                 thread_block((void (*)()) 0);
  430                 if (node_self_addr) {
  431                         splx(s);
  432                         break;
  433                 }
  434                 splx(s);
  435         }
  436         printf("netipc: node %d internet 0x%x ethernet %s\n",
  437                node_self(),
  438                NTOHL(node_self_addr->node_ip_addr),
  439                ether_sprintf(node_self_addr->node_ether_addr));
  440         if (netipc_boot_config[0] != '\0') {
  441                 printf("netipc: boot config:\n%s", netipc_boot_config);
  442         }
  443         printf("netipc: incarnation %d\n", node_incarnation);
  444 }
  445 
  446 boolean_t nd_request_in_progress = FALSE;
  447 
  448 request_ior_done()
  449 {
  450         nd_request_in_progress = FALSE;
  451 }
  452 
  453 nd_request()
  454 {
  455         netipc_ether_header_t ehp;
  456         netipc_udpip_header_t uhp;
  457         struct nd_request *ndrq;
  458         int i, total_length, udp_length;
  459         unsigned long checksum;
  460 
  461         if (nd_request_in_progress) {
  462                 return;
  463         }
  464         nd_request_in_progress = TRUE;
  465 
  466         ehp  = (netipc_ether_header_t) netipc_ether_buf;
  467         uhp  = (netipc_udpip_header_t) (((char *) ehp) + EHLEN);
  468         ndrq = (struct nd_request *) (uhp + 1);
  469         
  470         udp_length = UDP_OVERHEAD + sizeof(struct nd_request);
  471         total_length = EHLEN + IP_OVERHEAD + udp_length;
  472 
  473         netipc_ior[0].io_count = total_length;
  474         netipc_ior[0].io_data = (char *) ehp;
  475         netipc_ior[0].io_done = request_ior_done;
  476         netipc_ior[0].io_op = IO_LOANED;
  477         
  478         ehp->e_ptype = HTONS(ETHERTYPE_IP);
  479         BCOPY(eaddr_l, ehp->e_src, 6);
  480         ehp->e_dest[0] = 0xffff;
  481         ehp->e_dest[1] = 0xffff;
  482         ehp->e_dest[2] = 0xffff;
  483         
  484         uhp->ip_version = IPVERSION;
  485         uhp->ip_header_length = 5;
  486         uhp->ip_type_of_service = 0;
  487         uhp->ip_total_length = HTONS(udp_length + IP_OVERHEAD);
  488         uhp->ip_id = HTONS(netipc_ip_id++);
  489         uhp->ip_fragment_offset = HTONS(0);
  490         uhp->ip_time_to_live = 0xff;
  491         uhp->ip_protocol = UDP_PROTOCOL;
  492         uhp->ip_checksum = 0;
  493 
  494 #if 0
  495         uhp->ip_src = 0;
  496         uhp->ip_dst = HTONL(0xffffffff);
  497 #else
  498         {
  499                 int ip_src = 0;
  500                 int ip_dst = HTONL(0xffffffff);
  501                 
  502                 XLA(uhp->ip_src, ip_src);
  503                 XLA(uhp->ip_dst, ip_dst);
  504         }
  505 #endif          
  506 
  507         for (checksum = i = 0; i < 10; i++) {
  508                 checksum += ((unsigned short *) uhp)[i];
  509         }
  510         checksum = (checksum & 0xffff) + (checksum >> 16);
  511         checksum = (checksum & 0xffff) + (checksum >> 16);
  512         uhp->ip_checksum = (~checksum & 0xffff);
  513 
  514         uhp->udp_source_port = HTONS(IPPORT_NDREPLY);
  515         uhp->udp_dest_port = HTONS(IPPORT_NDREQUEST);
  516         uhp->udp_length = HTONS(udp_length);
  517         uhp->udp_checksum = 0;
  518 
  519 #if 0
  520         ndrq->ndrq_magic = HTONL(NDRQ_MAGIC);
  521         ndrq->ndrq_start = HTONS(0);
  522 #else
  523         {
  524                 int ndrq_magic = HTONL(NDRQ_MAGIC);
  525                 int ndrq_start = HTONS(0);
  526 
  527                 XLA(ndrq->ndrq_magic, ndrq_magic);
  528                 XLA(ndrq->ndrq_start, ndrq_start);
  529         }
  530 #endif
  531         BCOPY(eaddr_l, ndrq->ndrq_eaddr, 6);
  532 
  533         /*
  534          * Send the packet.
  535          */
  536         (*netipc_device->d_write)(netipc_device_unit, &netipc_ior[0]);
  537 }
  538 
  539 nd_config_parse_incarnation(s)
  540         char *s;
  541 {
  542         char *incarnation_env = "INCARNATION=";
  543         unsigned long incarnation = 0;
  544 
  545         if (strncmp(s, incarnation_env, strlen(incarnation_env))) {
  546                 return;
  547         }
  548         for (s += strlen(incarnation_env); *s >= '' && *s <= '9'; s++) {
  549                 incarnation = 10 * incarnation + (*s - '');
  550         }
  551         if (incarnation != 0) {
  552                 node_incarnation = incarnation;
  553         }
  554 }
  555 
  556 nd_config_reply(uhp, count)
  557         netipc_udpip_header_t uhp;
  558         unsigned long count;
  559 {
  560         struct nd_config *ndrc = (struct nd_config *) (uhp + 1);
  561         int bootconfigsize, bootmsgcnt, bootoffset;
  562 
  563         bootmsgcnt = NTOHS(ndrc->ndrc_msg_size);
  564         bootoffset = NTOHS(ndrc->ndrc_offset);
  565         if ((bootoffset + bootmsgcnt) > sizeof(netipc_boot_config)) {
  566                 printf("nd_config: Too much config data!");
  567                 return;
  568         }
  569         bootconfigsize = NTOHS(ndrc->ndrc_config_size);
  570         BCOPY(ndrc->ndrc_boot_data, &netipc_boot_config[bootoffset],
  571                bootmsgcnt);
  572         netipc_boot_config[bootconfigsize] = '\0';
  573         if (bootoffset + bootmsgcnt >= bootconfigsize) {
  574                 nd_config_parse_incarnation(netipc_boot_config);
  575         }
  576 }
  577 
  578 nd_table_reply(uhp, count)
  579         netipc_udpip_header_t uhp;
  580         unsigned long count;
  581 {
  582         struct nd_reply *ndrp = (struct nd_reply *) (uhp + 1);
  583         int i;
  584 
  585         _node_self = NTOHS(ndrp->ndrp_node_self);
  586         node_table_size = NTOHS(ndrp->ndrp_table_size);
  587         if (node_table_size < 0 || node_table_size > MAX_NODE_TABLE_SIZE) {
  588                 panic("nd_table_reply: bad table size %d\n", node_table_size);
  589         }
  590         for (i = 0; i < node_table_size; i++) {
  591                 struct nd *nd = &ndrp->ndrp_table[i];
  592                 struct node_addr *na = &node_table[i];
  593 
  594                 if (! nd->nd_valid) {
  595                         node_table[i].node_ip_addr = 0;
  596                         bzero(node_table[i].node_ether_addr, 6);
  597                         continue;
  598                 } else {
  599                         na->node_ip_addr = nd->nd_iaddr;
  600                         BCOPY(nd->nd_eaddr, na->node_ether_addr, 6);
  601                 }
  602         }
  603         node_self_addr = &node_table[_node_self];
  604         thread_wakeup((vm_offset_t) &node_self_addr);
  605 }
  606 
  607 nd_reply(uhp, count)
  608         netipc_udpip_header_t uhp;
  609         unsigned long count;
  610 {
  611         struct nd_reply *ndrp = (struct nd_reply *) (uhp + 1);
  612 
  613         if (node_self_addr) {
  614                 /*
  615                  * Table and config info already initialized.
  616                  */
  617                 return;
  618         }
  619         if (ndrp->ndrp_magic == HTONL(NDRP_MAGIC)) {
  620                 nd_table_reply(uhp, count);
  621         } else if (ndrp->ndrp_magic == HTONL(NDRC_MAGIC)) {
  622                 nd_config_reply(uhp, count);
  623         } else {
  624                 printf("nd_reply: bad magic\n");
  625         }
  626 }
  627 
  628 char netipc_swap_device[3] = "hd";
  629 int netipc_swap_node_1 = 1;
  630 int netipc_swap_node_2 = 1;
  631 int netipc_swap_xor = 1;
  632 
  633 char *
  634 dev_forward_name(name, namebuf, namelen)
  635         char *name;
  636         char *namebuf;
  637         int namelen;
  638 {
  639         if (netipc_swap_node_1 == netipc_swap_node_2) {
  640                 return name;
  641         }
  642         if (name[0] == netipc_swap_device[0] &&
  643             name[1] == netipc_swap_device[1]) {
  644                 namebuf[0] = '<';
  645                 if (node_self() == netipc_swap_node_1) {
  646                         namebuf[1] = '' + netipc_swap_node_2;
  647                 } else {
  648                         namebuf[1] = '' + netipc_swap_node_1;
  649                 }
  650                 namebuf[2] = '>';
  651                 namebuf[3] = name[0];                   /* e.g. 'h' */
  652                 namebuf[4] = name[1];                   /* e.g. 'd' */
  653                 namebuf[5] = name[2] ^ netipc_swap_xor; /* major */
  654                 namebuf[6] = name[3];                   /* minor */
  655                 namebuf[7] = '\0';
  656                 printf("[ %s -> %s ]\n", name, namebuf);
  657                 return namebuf;
  658         }
  659         return name;
  660 }
  661 
  662 int c_netipc_frag_drop0 = 0;
  663 int c_netipc_frag_drop1 = 0;
  664 int c_netipc_frag_drop2 = 0;
  665 int c_netipc_frag_drop3 = 0;
  666 int c_netipc_frag_drop4 = 0;
  667 
  668 netipc_net_packet(kmsg, count)
  669         ipc_kmsg_t kmsg;
  670         unsigned long count;
  671 {
  672         register struct netipc_ether_header *ehp;
  673         register struct netipc_udpip_header *uhp;
  674 
  675         ehp = (netipc_ether_header_t) &net_kmsg(kmsg)->header[0];
  676         uhp = (netipc_udpip_header_t) &net_kmsg(kmsg)->packet[sizeof(char *)];
  677         count = count - sizeof(struct packet_header);
  678 
  679         /*
  680          * Only consider udp packets
  681          */
  682         if (ehp->e_ptype != HTONS(ETHERTYPE_IP) ||
  683 /*          node_ip_id(uhp->ip_src) == -1 ||            ignore broadcasts? */
  684             uhp->ip_protocol != UDP_PROTOCOL) {
  685                 return FALSE;
  686         }
  687 
  688         /*
  689          * Ignore packets whose length (as claimed by driver) differs from
  690          * length as recorded in udp header.
  691          */
  692         if (count != NTOHS(uhp->udp_length) + IP_OVERHEAD) {
  693                 c_netipc_frag_drop0++;
  694                 return FALSE;
  695         }
  696 
  697         /*
  698          * Steal the kmsg iff we recognize the udp port.
  699          */
  700         if (uhp->udp_dest_port == NETIPC_UDPPORT) {
  701                 if (NoiseEther) {
  702                         netipc_fragment_header_t fhp =
  703                             (netipc_fragment_header_t) (uhp + 1);
  704                         printf("R s=%d.%x, d=%d.%x f=%04d/%d/%d len=%d\n",
  705                                node_ip_id(uhp->ip_src),
  706                                NTOHL(uhp->ip_src),
  707                                node_ip_id(uhp->ip_dst),
  708                                NTOHL(uhp->ip_dst),
  709                                NTOHS(fhp->f_offset),
  710                                fhp->f_id,
  711                                fhp->f_last,
  712                                NTOHS(uhp->udp_length) + EHLEN + IP_OVERHEAD);
  713                 }
  714                 netipc_recv_copy(kmsg);
  715                 return TRUE;
  716         } else if (NTOHS(uhp->udp_dest_port) == IPPORT_NDREPLY) {
  717                 nd_reply(uhp, count);
  718                 net_kmsg_put(kmsg);
  719                 return TRUE;
  720         } else {
  721                 return FALSE;
  722         }
  723 }
  724 
  725 netipc_recv_copy(kmsg)
  726         ipc_kmsg_t kmsg;
  727 {
  728         netipc_udpip_header_t uhp;
  729         netipc_fragment_header_t fhp;
  730         char *buf;
  731         unsigned long count;
  732         int i, offset;
  733 
  734         uhp = (netipc_udpip_header_t) &net_kmsg(kmsg)->packet[sizeof(char *)];
  735         fhp = (netipc_fragment_header_t) (uhp + 1);
  736         count = NTOHL(fhp->f_length);
  737         buf = (char *) (fhp + 1);
  738         offset = NTOHS(fhp->f_offset);
  739 
  740         if (recv_netvec == 0) {
  741                 c_netipc_frag_drop1++;
  742                 net_kmsg_put(kmsg);
  743                 return;
  744         }
  745 
  746         if (netipc_recv_fragment_ip_src) {
  747                 if (netipc_recv_fragment_ip_src != uhp->ip_src) {
  748                         /*
  749                          * Someone has a frag in progress. Drop this packet.
  750                          */
  751                         c_netipc_frag_drop2++;
  752                         net_kmsg_put(kmsg);
  753                         return;
  754                 }
  755                 if (fhp->f_last == 0) {
  756                         /*
  757                          * New nonfragged message replaces old frag.
  758                          * XXX clearly suboptimal, see discussion above
  759                          * XXX assumes only one fragged message in transit
  760                          */
  761                         c_netipc_frag_drop3++;
  762                         netipc_recv_fragment_ip_src = 0;
  763                 }
  764         }
  765 
  766         /*
  767          * First check for non fragmented packets.
  768          */
  769         if (fhp->f_last == 0) {
  770                 for (i = 0; i < recv_netvec_count; i++) {
  771                         if (count <= recv_netvec[i].size) {
  772                                 BCOPY(buf, recv_netvec[i].addr, count);
  773                                 recv_netvec[i].size = count;
  774                                 for (i++; i < recv_netvec_count; i++) {
  775                                         recv_netvec[i].size = 0;
  776                                 }
  777                                 break;
  778                         }
  779                         BCOPY(buf, recv_netvec[i].addr, recv_netvec[i].size);
  780                         buf += recv_netvec[i].size;
  781                         count -= recv_netvec[i].size;
  782                 }
  783                 recv_netvec = 0;
  784                 netipc_recv_intr();
  785                 net_kmsg_put(kmsg);
  786                 return;
  787         }
  788 
  789         /*
  790          * The packet was fragmented.
  791          * If this is the first frag of a message, set up frag info.
  792          */
  793         if (netipc_recv_fragment_ip_src == 0) {
  794                 netipc_recv_fragment_ip_src = uhp->ip_src;
  795                 netipc_recv_fragment_f_id = 0;
  796         }
  797 
  798         /*
  799          * If we missed a frag, drop the whole thing!
  800          */
  801         if (netipc_recv_fragment_f_id != fhp->f_id) {
  802                 netipc_recv_fragment_ip_src = 0;
  803                 c_netipc_frag_drop4++;
  804                 net_kmsg_put(kmsg);
  805                 return;
  806         }
  807 
  808         /*
  809          * Skip to the right offset in the receive buffer,
  810          * and copy it into the the appropriate vectors.
  811          *
  812          * First skip past all elements that we won't touch.
  813          */
  814         for (i = 0; offset >= recv_netvec[i].size; i++) {
  815                 offset -= recv_netvec[i].size;
  816         }
  817         assert(offset >= 0);
  818         assert(i < recv_netvec_count);
  819 
  820         /*
  821          * A non-zero offset will affect at most one element.
  822          * Deal with it now so that we can stop worrying about offset.
  823          */
  824         if (offset > 0) {
  825                 /*
  826                  * If this is the last element, and the last fragment,
  827                  * then set size.
  828                  */
  829                 if (count <= recv_netvec[i].size - offset) {
  830                         BCOPY(buf, recv_netvec[i].addr + offset, count);
  831                         if (fhp->f_id == fhp->f_last) {
  832                                 recv_netvec[i].size = count + offset;
  833                         }
  834                         goto did_copy;
  835                 }
  836                 /*
  837                  * This is not the last element. Copy and continue.
  838                  */
  839                 BCOPY(buf, recv_netvec[i].addr + offset,
  840                       recv_netvec[i].size - offset);
  841                 buf += recv_netvec[i].size - offset;
  842                 count -= recv_netvec[i].size - offset;
  843                 i++;
  844         }
  845 
  846         /*
  847          * Fill all the middle elements.
  848          */
  849         for (; count > recv_netvec[i].size; i++) {
  850                 BCOPY(buf, recv_netvec[i].addr, recv_netvec[i].size);
  851                 buf += recv_netvec[i].size;
  852                 count -= recv_netvec[i].size;
  853         }
  854 
  855         /*
  856          * Fill the last element; if it's the last fragment, set size.
  857          */
  858         BCOPY(buf, recv_netvec[i].addr, count);
  859         if (fhp->f_id == fhp->f_last) {
  860                 recv_netvec[i].size = count;
  861         }
  862 
  863 did_copy:
  864         /*
  865          * If this is the last frag, hand it up, after setting the
  866          * size for all remaining elements to zero.
  867          * Otherwise, simply note that we received this frag.
  868          */
  869         if (fhp->f_id == fhp->f_last) {
  870                 for (i++; i < recv_netvec_count; i++) {
  871                         recv_netvec[i].size = 0;
  872                 }
  873                 netipc_recv_fragment_ip_src = 0;
  874                 recv_netvec = 0;
  875                 netipc_recv_intr();
  876         } else {
  877                 netipc_recv_fragment_f_id++;
  878         }
  879         net_kmsg_put(kmsg);
  880 }
  881 
  882 netipc_recv(vec, count)
  883         register struct netvec *vec;
  884         int count;
  885 {
  886         recv_netvec = vec;
  887         recv_netvec_count = count;
  888 }
  889 
  890 /* (net as in usable, not as in network) */
  891 #define NETMTU  (ETHERMTU - EHLEN - IP_OVERHEAD - UDP_OVERHEAD - FHP_OVERHEAD)
  892 
  893 int netipc_fragment_last_uncompleted = 0;
  894 
  895 netipc_ether_send_complete(ior)
  896         register io_req_t ior;
  897 {
  898         register netipc_udpip_header_t uhp;
  899         register netipc_fragment_header_t fhp;
  900 
  901         uhp = (netipc_udpip_header_t) (((char *) ior->io_data) + EHLEN);
  902         fhp = (netipc_fragment_header_t) (uhp + 1);
  903         if (fhp->f_id != netipc_fragment_last_uncompleted) {
  904                 panic("netipc_ether_send_complete: f_id %d != %d!\n",
  905                       fhp->f_id, netipc_fragment_last_uncompleted);
  906         }
  907         netipc_fragment_last_uncompleted++;
  908         if (fhp->f_id == fhp->f_last) {
  909                 netipc_send_intr();
  910         }
  911 }
  912 
  913 /*
  914  * This routine is not reentrant and is not expected to be.
  915  * norma/ipc_net.c uses netipc_sending to prevent multiple entrances.
  916  * If we have a reentrant form, we can upcall on netipc_send_intr
  917  * to indicate that we can accept another netipc_send call.
  918  */
  919 netipc_send(remote, vec, count)
  920         unsigned long remote;
  921         register struct netvec *vec;
  922         unsigned int count;
  923 {
  924         int i, f, frag_count, data_len;
  925         extern struct node_addr *node_self_addr, *node_addr_by_node();
  926         struct node_addr *node_dest_addr;
  927         char *buf;
  928         netipc_ether_header_t ehp;
  929         netipc_udpip_header_t uhp;
  930         netipc_fragment_header_t fhp;
  931         int total_length, udp_length;
  932 
  933         /*
  934          * Silently drop packets destined for invalid nodes.
  935          * Sender should previously have called netipc_node_valid.
  936          * XXX
  937          * We should have sender check our return value.
  938          * If this were done, we wouldn't have to call netipc_send_intr.
  939          */
  940         if (! netipc_node_valid(remote)) {
  941                 netipc_send_intr();
  942                 return;
  943         }
  944 
  945         /*
  946          * Compute total size and number of fragments
  947          */
  948         data_len = 0;
  949         for (i = 0; i < count; i++) {
  950                 data_len += vec[i].size;
  951         }
  952         frag_count = (data_len + NETMTU - 1) / NETMTU;
  953         if (frag_count > MAXFRAG) {
  954                 panic("netipc_send: size %d: too many (%d) fragments\n",
  955                        data_len, frag_count);
  956         }
  957 
  958         /*
  959          * Get destination address
  960          */
  961         node_dest_addr = node_addr_by_node(remote);
  962 
  963         /*
  964          * Construct headers for each fragment; copy data into a contiguous
  965          * chunk (yuck). Use loaned ior's.
  966          */
  967         netipc_fragment_last_uncompleted = 0;
  968         for (f = 0; f < frag_count; f++) {
  969                 ehp = (netipc_ether_header_t) &netipc_ether_buf[f * ETHERMTU];
  970                 uhp = (netipc_udpip_header_t) (((char *) ehp) + EHLEN);
  971                 fhp = (netipc_fragment_header_t) (uhp + 1);
  972                 
  973                 if (data_len > NETMTU) {
  974                         udp_length = ETHERMTU - EHLEN - IP_OVERHEAD;
  975                         fhp->f_length = HTONL(udp_length - UDP_OVERHEAD -
  976                                               FHP_OVERHEAD);
  977                         total_length = ETHERMTU;
  978                         data_len -= NETMTU;
  979                 } else {
  980                         udp_length = UDP_OVERHEAD + FHP_OVERHEAD + data_len;
  981                         fhp->f_length = HTONL(data_len);
  982                         if (udp_length < ETHERMIN - IP_OVERHEAD) {
  983                                 udp_length = ETHERMIN - IP_OVERHEAD;
  984                         }
  985                         total_length = EHLEN + IP_OVERHEAD + udp_length;
  986                         data_len = 0;
  987                 }
  988 
  989                 netipc_ior[f].io_count = total_length;
  990                 netipc_ior[f].io_data = (char *) ehp;
  991                 netipc_ior[f].io_done = netipc_ether_send_complete;
  992                 netipc_ior[f].io_op = IO_LOANED;
  993 
  994                 ehp->e_ptype = HTONS(ETHERTYPE_IP);
  995                 ehp->e_src[0] = node_self_addr->node_ether_addr[0];
  996                 ehp->e_src[1] = node_self_addr->node_ether_addr[1];
  997                 ehp->e_src[2] = node_self_addr->node_ether_addr[2];
  998                 ehp->e_dest[0] = node_dest_addr->node_ether_addr[0];
  999                 ehp->e_dest[1] = node_dest_addr->node_ether_addr[1];
 1000                 ehp->e_dest[2] = node_dest_addr->node_ether_addr[2];
 1001                 
 1002                 uhp->ip_version = IPVERSION;
 1003                 uhp->ip_header_length = 5;
 1004                 uhp->ip_type_of_service = 0;
 1005                 uhp->ip_total_length = HTONS(total_length);
 1006                 uhp->ip_id = HTONS(netipc_ip_id++);
 1007                 uhp->ip_fragment_offset = HTONS(0);
 1008                 uhp->ip_time_to_live = 0xff;
 1009                 uhp->ip_protocol = UDP_PROTOCOL;
 1010                 uhp->ip_checksum = -1;
 1011 #if 0
 1012                 uhp->ip_src = node_self_addr->node_ip_addr;
 1013                 uhp->ip_dst = node_dest_addr->node_ip_addr;
 1014 #else
 1015                 XLA(uhp->ip_src, node_self_addr->node_ip_addr);
 1016                 XLA(uhp->ip_dst, node_dest_addr->node_ip_addr);
 1017 #endif          
 1018                 uhp->udp_source_port = HTONS(NETIPC_UDPPORT);
 1019                 uhp->udp_dest_port = HTONS(NETIPC_UDPPORT);
 1020                 uhp->udp_length = HTONS(udp_length);
 1021                 uhp->udp_checksum = -1;
 1022 
 1023                 buf = (char *) (fhp + 1);
 1024 
 1025                 if (frag_count == 0) {
 1026                         fhp->f_offset = 0;
 1027                         fhp->f_id = 0;
 1028                         fhp->f_last = 0;
 1029 
 1030                         /*
 1031                          * Everything will fit into one fragment,
 1032                          * so just copy everything into it.
 1033                          */
 1034                         for (i = 0; i < count; i++) {
 1035                                 BCOPY(vec[i].addr, buf, vec[i].size);
 1036                                 buf += vec[i].size;
 1037                         }
 1038                 } else {
 1039                         unsigned short offset = f * NETMTU;
 1040                         unsigned short remain = NETMTU;
 1041 
 1042                         fhp->f_offset = HTONS(offset);
 1043                         fhp->f_id = f;
 1044                         fhp->f_last = frag_count - 1;
 1045 
 1046                         /*
 1047                          * First skip all elements which have
 1048                          * already been completely sent.
 1049                          */
 1050                         for (i = 0; offset >= vec[i].size; i++) {
 1051                                 assert(i < count);
 1052                                 offset -= vec[i].size;
 1053                         }
 1054                         assert((long) offset >= 0);
 1055                         assert((long) offset < vec[i].size);
 1056 
 1057                         /*
 1058                          * Offset is now the offset into the current
 1059                          * element at which we begin copying.
 1060                          * If this element is all we need, then copy
 1061                          * as much of this element as will fit.
 1062                          */
 1063                         assert(i < count);
 1064                         if (vec[i].size - offset >= remain) {
 1065                                 BCOPY(vec[i].addr + offset, buf, remain);
 1066                                 goto done_copying_into_fragments;
 1067                         }
 1068 
 1069                         /*
 1070                          * Copy all of this element, starting at offset.
 1071                          * Move to the next element.
 1072                          */
 1073                         BCOPY(vec[i].addr + offset, buf, vec[i].size - offset);
 1074                         buf += (vec[i].size - offset);
 1075                         remain -= (vec[i].size - offset);
 1076                         i++;
 1077 
 1078                         /*
 1079                          * For each remaining element: if it's all we need,
 1080                          * then copy all that will fit and stop. Otherwise,
 1081                          * copy all of it, and continue.
 1082                          */
 1083                         for (; i < count; i++) {
 1084                                 if (vec[i].size >= remain) {
 1085                                         BCOPY(vec[i].addr, buf, remain);
 1086                                         break;
 1087                                 }
 1088                                 BCOPY(vec[i].addr, buf, vec[i].size);
 1089                                 buf += vec[i].size;
 1090                                 remain -= vec[i].size;
 1091                         }
 1092 done_copying_into_fragments:
 1093                         ;
 1094                 }
 1095 
 1096                 if (NoiseEther) {
 1097                         printf("S s=%d.%x, d=%d.%x f=%04d/%d/%d len=%d\n",
 1098                                node_ip_id(uhp->ip_src),
 1099                                NTOHL(node_self_addr->node_ip_addr),
 1100                                node_ip_id(uhp->ip_dst),
 1101                                NTOHL(node_dest_addr->node_ip_addr),
 1102                                NTOHS(fhp->f_offset),
 1103                                fhp->f_id,
 1104                                fhp->f_last,
 1105                                udp_length + EHLEN + IP_OVERHEAD);
 1106                 }
 1107 
 1108                 /*
 1109                  * Send the packet.
 1110                  */
 1111                 (*netipc_device->d_write)(netipc_device_unit, &netipc_ior[f]);
 1112         }
 1113 }

Cache object: 8b26acda37054a5853b58bbbabe0200f


[ 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.