2011-03-30 12:46:40 +00:00
|
|
|
/* 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;
|
2011-04-12 15:53:55 +00:00
|
|
|
char name[NAMELEN];
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
char *dialstr;
|
|
|
|
char anndir[40];
|
|
|
|
char lisdir[40];
|
|
|
|
int annfd; /* fd from announce */
|
|
|
|
};
|
|
|
|
|
|
|
|
static Network netif[Maxnets];
|
|
|
|
|
2011-04-17 09:29:38 +00:00
|
|
|
char *annstrs[Maxnets];
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
neti(void *v)
|
|
|
|
{
|
|
|
|
int lisfd, accfd;
|
2011-04-12 15:53:55 +00:00
|
|
|
NetConnInfo *nci;
|
2011-04-17 04:06:33 +00:00
|
|
|
Network *net;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
net = v;
|
|
|
|
print("net%di\n", net->ctlrno);
|
2011-04-17 04:06:33 +00:00
|
|
|
Listen:
|
|
|
|
if((lisfd = listen(net->anndir, net->lisdir)) < 0){
|
|
|
|
print("listen %s failed: %r\n", net->anndir);
|
|
|
|
return;
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
for(;;) {
|
|
|
|
/* got new call on lisfd */
|
2011-04-17 04:06:33 +00:00
|
|
|
if((accfd = accept(lisfd, net->lisdir)) < 0){
|
2011-03-30 12:46:40 +00:00
|
|
|
print("accept %d (from %s) failed: %r\n",
|
|
|
|
lisfd, net->lisdir);
|
2011-04-17 04:06:33 +00:00
|
|
|
close(lisfd);
|
|
|
|
goto Listen;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2011-04-12 15:53:55 +00:00
|
|
|
nci = getnetconninfo(net->lisdir, accfd);
|
|
|
|
srvchan(accfd, nci->raddr);
|
|
|
|
freenetconninfo(nci);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
netstart(void)
|
|
|
|
{
|
|
|
|
Network *net;
|
|
|
|
|
|
|
|
for(net = &netif[0]; net < &netif[Maxnets]; net++){
|
2011-04-17 04:06:33 +00:00
|
|
|
if(net->dialstr == nil || *net->anndir == 0)
|
2011-03-30 12:46:40 +00:00
|
|
|
continue;
|
2011-04-12 15:53:55 +00:00
|
|
|
sprint(net->name, "net%di", net->ctlrno);
|
|
|
|
newproc(neti, net, net->name);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
netinit(void)
|
|
|
|
{
|
|
|
|
Network *net;
|
|
|
|
|
|
|
|
for (net = netif; net < netif + Maxnets; net++) {
|
|
|
|
net->dialstr = annstrs[net - netif];
|
2011-04-17 04:06:33 +00:00
|
|
|
if(net->dialstr == nil)
|
2011-03-30 12:46:40 +00:00
|
|
|
continue;
|
2011-04-17 04:06:33 +00:00
|
|
|
if((net->annfd = announce(net->dialstr, net->anndir)) < 0){
|
2011-04-17 02:14:26 +00:00
|
|
|
print("can't announce %s: %r", net->dialstr);
|
2011-04-17 04:06:33 +00:00
|
|
|
net->dialstr = nil;
|
|
|
|
continue;
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
print("netinit: announced on %s\n", net->dialstr);
|
|
|
|
}
|
|
|
|
}
|