ref: 7d7e8ae31ac01434c7017afce4eb0a033281a757
dir: /sys/src/cmd/cwfs/net.c/
/* network i/o */ #include "all.h" #include "io.h" /* * the kernel file server read packets directly from * its ethernet(s) and did all the protocol processing. * if the incoming packets were 9p (over il/ip), they * were queued for the server processes to operate upon. * * in user mode, we have one process per incoming connection * instead, and those processes get just the data, minus * tcp and ip headers, so they just see a stream of 9p messages, * which they then queue for the server processes. * * there used to be more queueing (in the kernel), with separate * processes for ethernet input, il input, 9p processing, il output * and ethernet output, and queues connecting them. we now let * the kernel's network queues, protocol stacks and processes do * much of this work. * * partly as a result of this, we can now process 9p messages * transported via tcp, exploit multiple x86 processors, and * were able to shed 70% of the file server's source, by line count. * * the upshot is that Ether (now Network) is no longer a perfect fit for * the way network i/o is done now. the notion of `connection' * is being introduced to complement it. */ typedef struct Network Network; /* a network, not necessarily an ethernet */ struct Network { int ctlrno; char name[NAMELEN]; char *dialstr; char anndir[40]; char lisdir[40]; int annfd; /* fd from announce */ }; static Network netif[Maxnets]; char *annstrs[Maxnets]; static void neti(void *v) { NetConnInfo *nci; Network *net; char *addr; int nctl, data; net = v; for(;;) { if((nctl = listen(net->anndir, net->lisdir)) < 0){ fprint(2, "%s: listen %s failed: %r\n", argv0, net->anndir); break; } if((data = accept(nctl, net->lisdir)) < 0){ fprint(2, "%s: accept %s failed: %r\n", argv0, net->lisdir); close(nctl); continue; } close(nctl); nci = getnetconninfo(net->lisdir, data); addr = nci == nil ? "unknown" : nci->raddr; if(srvchan(data, addr) == nil){ fprint(2, "%s: srvchan failed for: %s\n", argv0, addr); close(data); } freenetconninfo(nci); } } void netstart(void) { Network *net; for(net = &netif[0]; net < &netif[Maxnets]; net++){ if(net->dialstr == nil || *net->anndir == 0) continue; sprint(net->name, "net%di", net->ctlrno); newproc(neti, net, net->name); } } void netinit(void) { Network *net; for (net = netif; net < netif + Maxnets; net++) { net->dialstr = annstrs[net - netif]; if(net->dialstr == nil) continue; if((net->annfd = announce(net->dialstr, net->anndir)) < 0){ fprint(2, "can't announce %s: %r\n", net->dialstr); net->dialstr = nil; continue; } if(chatty) print("netinit: announced on %s\n", net->dialstr); } }