ia64/xen-unstable
changeset 1427:73eb554453db
bitkeeper revision 1.931 (40bf28b1DSY6oBu4FDeGIob6_AJvUA)
Initial support for restartable network driver domains.
Initial support for restartable network driver domains.
author | mwilli2@equilibrium.research.intel-research.net |
---|---|
date | Thu Jun 03 13:33:37 2004 +0000 (2004-06-03) |
parents | 00e1d3ae9894 |
children | d4eecc615039 |
files | tools/examples/xc_dom_create.py tools/xc/lib/xc.h tools/xc/lib/xc_linux_build.c tools/xc/py/Xc.c tools/xend/lib/main.py tools/xend/lib/manager.py tools/xend/lib/netif.py xen/common/physdev.c xen/include/hypervisor-ifs/hypervisor-if.h xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/main.c |
line diff
1.1 --- a/tools/examples/xc_dom_create.py Thu Jun 03 11:45:16 2004 +0000 1.2 +++ b/tools/examples/xc_dom_create.py Thu Jun 03 13:33:37 2004 +0000 1.3 @@ -25,6 +25,7 @@ Arguments to control the parsing of the 1.4 -h -- Print extended help message, including all arguments 1.5 -n -- Dry run only, don't actually create domain 1.6 -q -- Quiet - write output only to the system log 1.7 + -s -- Don't start the domain, just build it. 1.8 """ % (sys.argv[0], xc_config_file) 1.9 1.10 def extra_usage (): 1.11 @@ -89,12 +90,13 @@ vbd_expert=0; auto_restart=False; 1.12 vbd_list = []; cmdline_ip = ''; cmdline_root=''; cmdline_extra='' 1.13 pci_device_list = []; console_port = -1 1.14 auto_console = False 1.15 +dontstart = False 1.16 1.17 ##### Determine location of defaults file 1.18 ##### 1.19 1.20 try: 1.21 - opts, args = getopt.getopt(sys.argv[1:], "h?nqcf:D:k:r:b:m:N:a:e:d:i:I:R:E:L:" ) 1.22 + opts, args = getopt.getopt(sys.argv[1:], "h?nqcsf:D:k:r:b:m:N:a:e:d:i:I:R:E:L:" ) 1.23 1.24 for opt in opts: 1.25 if opt[0] == '-f': config_file= opt[1] 1.26 @@ -106,6 +108,7 @@ try: 1.27 exec "%s='%s'" % (l,r) 1.28 if opt[0] == '-q': quiet = True 1.29 if opt[0] == '-L': restore = True; state_file = opt[1] 1.30 + if opt[0] == '-s': dontstart = True 1.31 1.32 1.33 except getopt.GetoptError: 1.34 @@ -258,7 +261,7 @@ def make_domain(): 1.35 sys.exit() 1.36 else: 1.37 1.38 - ret = eval('xc.%s_build ( dom=id, image=image, ramdisk=ramdisk, cmdline=cmdline, control_evtchn=cons_response["remote_port"] )' % builder_fn ) 1.39 + ret = eval('xc.%s_build ( dom=id, image=image, ramdisk=ramdisk, cmdline=cmdline, control_evtchn=cons_response["remote_port"], flags=flags )' % builder_fn ) 1.40 if ret < 0: 1.41 print "Error building Linux guest OS: " 1.42 print "Return code = " + str(ret) 1.43 @@ -334,16 +337,28 @@ def make_domain(): 1.44 sys.exit() 1.45 1.46 if new_io_world: 1.47 - cmsg = 'new_network_interface(dom='+str(id)+')' 1.48 - xend_response = xenctl.utils.xend_control_message(cmsg) 1.49 - if not xend_response['success']: 1.50 - print "Error creating network interface" 1.51 - print "Error type: " + xend_response['error_type'] 1.52 - if xend_response['error_type'] == 'exception': 1.53 - print "Exception type: " + xend_response['exception_type'] 1.54 - print "Exception val: " + xend_response['exception_value'] 1.55 - xc.domain_destroy ( dom=id ) 1.56 - sys.exit() 1.57 + if not (flags & 8): # If it's not the net backend, give it a frontend. 1.58 + cmsg = 'new_network_interface(dom='+str(id)+')' 1.59 + xend_response = xenctl.utils.xend_control_message(cmsg) 1.60 + if not xend_response['success']: 1.61 + print "Error creating network interface" 1.62 + print "Error type: " + xend_response['error_type'] 1.63 + if xend_response['error_type'] == 'exception': 1.64 + print "Exception type: " + xend_response['exception_type'] 1.65 + print "Exception val: " + xend_response['exception_value'] 1.66 + xc.domain_destroy ( dom=id ) 1.67 + sys.exit() 1.68 + else: # It's a new net backend - notify Xend. 1.69 + cmsg = 'set_network_backend(dom='+str(id)+')' 1.70 + xend_response = xenctl.utils.xend_control_message(cmsg) 1.71 + if not xend_response['success']: 1.72 + print "Error registering network backend" 1.73 + print "Error type: " + xend_response['error_type'] 1.74 + if xend_response['error_type'] == 'exception': 1.75 + print "Exception type: " + xend_response['exception_type'] 1.76 + print "Exception val: " + xend_response['exception_value'] 1.77 + xc.domain_destroy ( dom=id ) 1.78 + sys.exit() 1.79 else: 1.80 # setup virtual firewall rules for all aliases 1.81 for ip in vfr_ipaddr: 1.82 @@ -372,10 +387,11 @@ def make_domain(): 1.83 os.system('/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip,gw)) 1.84 if not nlb: print >>open('/proc/sys/net/ipv4/ip_nonlocal_bind','w'), '0' 1.85 1.86 - if xc.domain_start( dom=id ) < 0: 1.87 - print "Error starting domain" 1.88 - xc.domain_destroy ( dom=id ) 1.89 - sys.exit() 1.90 + if not dontstart: 1.91 + if xc.domain_start( dom=id ) < 0: 1.92 + print "Error starting domain" 1.93 + xc.domain_destroy ( dom=id ) 1.94 + sys.exit() 1.95 1.96 return (id, cons_response['console_port']) 1.97 # end of make_domain()
2.1 --- a/tools/xc/lib/xc.h Thu Jun 03 11:45:16 2004 +0000 2.2 +++ b/tools/xc/lib/xc.h Thu Jun 03 13:33:37 2004 +0000 2.3 @@ -86,7 +86,8 @@ int xc_linux_build(int xc_handle, 2.4 const char *image_name, 2.5 const char *ramdisk_name, 2.6 const char *cmdline, 2.7 - unsigned int control_evtchn); 2.8 + unsigned int control_evtchn, 2.9 + unsigned long flags); 2.10 2.11 int xc_netbsd_build(int xc_handle, 2.12 u32 domid,
3.1 --- a/tools/xc/lib/xc_linux_build.c Thu Jun 03 11:45:16 2004 +0000 3.2 +++ b/tools/xc/lib/xc_linux_build.c Thu Jun 03 13:33:37 2004 +0000 3.3 @@ -74,7 +74,8 @@ static int setup_guestos(int xc_handle, 3.4 full_execution_context_t *ctxt, 3.5 const char *cmdline, 3.6 unsigned long shared_info_frame, 3.7 - unsigned int control_evtchn) 3.8 + unsigned int control_evtchn, 3.9 + unsigned long flags) 3.10 { 3.11 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; 3.12 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL; 3.13 @@ -268,7 +269,7 @@ static int setup_guestos(int xc_handle, 3.14 memset(start_info, 0, sizeof(*start_info)); 3.15 start_info->nr_pages = nr_pages; 3.16 start_info->shared_info = shared_info_frame << PAGE_SHIFT; 3.17 - start_info->flags = 0; 3.18 + start_info->flags = flags; 3.19 start_info->pt_base = vpt_start; 3.20 start_info->nr_pt_frames = nr_pt_pages; 3.21 start_info->mfn_list = vphysmap_start; 3.22 @@ -381,7 +382,8 @@ int xc_linux_build(int xc_handle, 3.23 const char *image_name, 3.24 const char *ramdisk_name, 3.25 const char *cmdline, 3.26 - unsigned int control_evtchn) 3.27 + unsigned int control_evtchn, 3.28 + unsigned long flags) 3.29 { 3.30 dom0_op_t launch_op, op; 3.31 int initrd_fd = -1; 3.32 @@ -446,7 +448,7 @@ int xc_linux_build(int xc_handle, 3.33 &vstartinfo_start, &vkern_entry, 3.34 ctxt, cmdline, 3.35 op.u.getdomaininfo.shared_info_frame, 3.36 - control_evtchn) < 0 ) 3.37 + control_evtchn, flags) < 0 ) 3.38 { 3.39 ERROR("Error constructing guest OS"); 3.40 goto error_out;
4.1 --- a/tools/xc/py/Xc.c Thu Jun 03 11:45:16 2004 +0000 4.2 +++ b/tools/xc/py/Xc.c Thu Jun 03 13:33:37 2004 +0000 4.3 @@ -513,18 +513,19 @@ static PyObject *pyxc_linux_build(PyObje 4.4 4.5 u32 dom; 4.6 char *image, *ramdisk = NULL, *cmdline = ""; 4.7 - int control_evtchn; 4.8 + int control_evtchn, flags = 0; 4.9 4.10 static char *kwd_list[] = { "dom", "control_evtchn", 4.11 - "image", "ramdisk", "cmdline", NULL }; 4.12 + "image", "ramdisk", "cmdline", "flags", 4.13 + NULL }; 4.14 4.15 - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ss", kwd_list, 4.16 + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iis|ssi", kwd_list, 4.17 &dom, &control_evtchn, 4.18 - &image, &ramdisk, &cmdline) ) 4.19 + &image, &ramdisk, &cmdline, &flags) ) 4.20 return NULL; 4.21 4.22 - if ( xc_linux_build(xc->xc_handle, dom, image, 4.23 - ramdisk, cmdline, control_evtchn) != 0 ) 4.24 + if ( xc_linux_build(xc->xc_handle, dom, image, 4.25 + ramdisk, cmdline, control_evtchn, flags) != 0 ) 4.26 return PyErr_SetFromErrno(xc_error); 4.27 4.28 Py_INCREF(zero);
5.1 --- a/tools/xend/lib/main.py Thu Jun 03 11:45:16 2004 +0000 5.2 +++ b/tools/xend/lib/main.py Thu Jun 03 13:33:37 2004 +0000 5.3 @@ -47,7 +47,7 @@ def daemon_loop(): 5.4 5.5 # Lists of all interfaces, indexed by local event-channel port. 5.6 port_list = {} 5.7 - 5.8 + 5.9 xc = Xc.new() 5.10 5.11 # Ignore writes to disconnected sockets. We clean up differently. 5.12 @@ -199,7 +199,7 @@ def daemon_loop(): 5.13 xend.blkif.backend_rx_req(port, msg) 5.14 elif type == CMSG_NETIF_FE and net_if: 5.15 net_if.ctrlif_rx_req(port, msg) 5.16 - elif type == CMSG_NETIF_BE and port == dom0_port: 5.17 + elif type == CMSG_NETIF_BE and port == xend.netif.be_port: 5.18 xend.netif.backend_rx_req(port, msg) 5.19 else: 5.20 port.write_response(msg) 5.21 @@ -211,7 +211,7 @@ def daemon_loop(): 5.22 type = (msg.get_header())['type'] 5.23 if type == CMSG_BLKIF_BE and port == dom0_port: 5.24 xend.blkif.backend_rx_rsp(port, msg) 5.25 - elif type == CMSG_NETIF_BE and port == dom0_port: 5.26 + elif type == CMSG_NETIF_BE and port == xend.netif.be_port: 5.27 xend.netif.backend_rx_rsp(port, msg) 5.28 5.29 # Send console data. 5.30 @@ -231,7 +231,7 @@ def daemon_loop(): 5.31 work_done = True 5.32 5.33 # Back-end network-device work. 5.34 - if port == dom0_port and xend.netif.backend_do_work(port): 5.35 + if port == xend.netif.be_port and xend.netif.backend_do_work(port): 5.36 work_done = True 5.37 5.38 # Finally, notify the remote end of any work that we did.
6.1 --- a/tools/xend/lib/manager.py Thu Jun 03 11:45:16 2004 +0000 6.2 +++ b/tools/xend/lib/manager.py Thu Jun 03 13:33:37 2004 +0000 6.3 @@ -150,3 +150,14 @@ def new_network_interface(dom, handle=-1 6.4 6.5 # Response is deferred until back-end driver sends acknowledgement. 6.6 return None 6.7 + 6.8 +## 6.9 +## set_network_backend 6.10 +## Authorise a domain to act as the net backend (assumes we only have one 6.11 +## backend driver for now). After this call, back end "up" notifications 6.12 +## for the network will only be accepted from this domain. 6.13 +## 6.14 +def set_network_backend(dom): 6.15 + if xend.netif.be_port: xend.netif.recovery = True 6.16 + xend.netif.be_port = xend.main.port_from_dom(dom) 6.17 + return { 'success' : True }
7.1 --- a/tools/xend/lib/netif.py Thu Jun 03 11:45:16 2004 +0000 7.2 +++ b/tools/xend/lib/netif.py Thu Jun 03 13:33:37 2004 +0000 7.3 @@ -11,6 +11,7 @@ CMSG_NETIF_BE = 3 7.4 CMSG_NETIF_FE = 4 7.5 CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED = 0 7.6 CMSG_NETIF_FE_DRIVER_STATUS_CHANGED = 32 7.7 +CMSG_NETIF_BE_DRIVER_STATUS_CHANGED = 32 7.8 CMSG_NETIF_FE_INTERFACE_CONNECT = 33 7.9 CMSG_NETIF_FE_INTERFACE_DISCONNECT = 34 7.10 CMSG_NETIF_BE_CREATE = 0 7.11 @@ -18,19 +19,50 @@ CMSG_NETIF_BE_DESTROY = 1 7.12 CMSG_NETIF_BE_CONNECT = 2 7.13 CMSG_NETIF_BE_DISCONNECT = 3 7.14 7.15 +NETIF_DRIVER_STATUS_DOWN = 0 7.16 +NETIF_DRIVER_STATUS_UP = 1 7.17 + 7.18 pendmsg = None 7.19 pendaddr = None 7.20 7.21 +recovery = False # Is a recovery in progress? (if so, we'll need to notify guests) 7.22 +be_port = None # Port object for backend domain 7.23 + 7.24 def backend_tx_req(msg): 7.25 - port = xend.main.dom0_port 7.26 - if port.space_to_write_request(): 7.27 - port.write_request(msg) 7.28 - port.notify() 7.29 + if not xend.netif.be_port: 7.30 + print "BUG: attempt to transmit request to non-existant netif driver" 7.31 + if xend.netif.be_port.space_to_write_request(): 7.32 + xend.netif.be_port.write_request(msg) 7.33 + xend.netif.be_port.notify() 7.34 else: 7.35 xend.netif.pendmsg = msg 7.36 7.37 def backend_rx_req(port, msg): 7.38 port.write_response(msg) 7.39 + subtype = (msg.get_header())['subtype'] 7.40 + print "Received netif-be request, subtype %d" % subtype 7.41 + if subtype == CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: 7.42 + (status, dummy) = struct.unpack("II", msg.get_payload()) 7.43 + if status == NETIF_DRIVER_STATUS_UP: 7.44 + if xend.netif.recovery: 7.45 + print "New netif backend now UP, notifying guests:" 7.46 + for netif_key in interface.list.keys(): 7.47 + netif = interface.list[netif_key] 7.48 + netif.create() 7.49 + print " Notifying %d" % netif.dom 7.50 + msg = xend.utils.message(CMSG_NETIF_FE, \ 7.51 + CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0) 7.52 + msg.append_payload(struct.pack("IIIBBBBBBBB", \ 7.53 + 0,1,0,0,0,0,0,0,0,0,0)) 7.54 + netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom), msg) 7.55 + print "Done notifying guests" 7.56 + recovery = False 7.57 + else: # No recovery in progress. 7.58 + if xend.netif.be_port: # This should never be true! (remove later) 7.59 + print "BUG: unexpected netif backend UP message from %d" \ 7.60 + % port.remote_dom 7.61 + else: 7.62 + print "Unexpected net backend driver status: %d" % status 7.63 7.64 def backend_rx_rsp(port, msg): 7.65 subtype = (msg.get_header())['subtype'] 7.66 @@ -44,8 +76,8 @@ def backend_rx_rsp(port, msg): 7.67 netif = interface.list[xend.main.port_from_dom(dom).local_port] 7.68 msg = xend.utils.message(CMSG_NETIF_FE, \ 7.69 CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0) 7.70 - msg.append_payload(struct.pack("IIIBBBBBBBB",0,2, \ 7.71 - netif.evtchn['port2'], \ 7.72 + msg.append_payload(struct.pack("IIIBBBBBBBB",0,2, \ 7.73 + netif.evtchn['port2'], \ 7.74 netif.mac[0],netif.mac[1], \ 7.75 netif.mac[2],netif.mac[3], \ 7.76 netif.mac[4],netif.mac[5], \ 7.77 @@ -66,6 +98,7 @@ class interface: 7.78 # Dictionary of all network-device interfaces. 7.79 list = {} 7.80 7.81 + drvdom = None 7.82 7.83 # NB. 'key' is an opaque value that has no meaning in this class. 7.84 def __init__(self, dom, key): 7.85 @@ -87,11 +120,16 @@ class interface: 7.86 self.mac.append(int(random.random()*256)) 7.87 7.88 interface.list[key] = self 7.89 + self.create() 7.90 + 7.91 + def create(self): 7.92 + """Notify the current network back end to create the virtual interface 7.93 + represented by this object.""" 7.94 msg = xend.utils.message(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE, 0) 7.95 - msg.append_payload(struct.pack("IIBBBBBBBBI",dom,0, \ 7.96 - self.mac[0],self.mac[1], \ 7.97 - self.mac[2],self.mac[3], \ 7.98 - self.mac[4],self.mac[5], \ 7.99 + msg.append_payload(struct.pack("IIBBBBBBBBI",self.dom,0, \ 7.100 + self.mac[0],self.mac[1], \ 7.101 + self.mac[2],self.mac[3], \ 7.102 + self.mac[4],self.mac[5], \ 7.103 0,0,0)) 7.104 xend.netif.pendaddr = xend.main.mgmt_req_addr 7.105 backend_tx_req(msg) 7.106 @@ -125,6 +163,7 @@ class interface: 7.107 port.write_response(msg) 7.108 subtype = (msg.get_header())['subtype'] 7.109 if subtype == CMSG_NETIF_FE_DRIVER_STATUS_CHANGED: 7.110 + print "netif driver up message from %d" % port.remote_dom 7.111 msg = xend.utils.message(CMSG_NETIF_FE, \ 7.112 CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0) 7.113 msg.append_payload(struct.pack("IIIBBBBBBBB",0,1,0,self.mac[0], \ 7.114 @@ -133,9 +172,12 @@ class interface: 7.115 self.mac[5],0,0)) 7.116 self.ctrlif_tx_req(port, msg) 7.117 elif subtype == CMSG_NETIF_FE_INTERFACE_CONNECT: 7.118 + print "netif connect request from %d" % port.remote_dom 7.119 (hnd,tx_frame,rx_frame) = struct.unpack("ILL", msg.get_payload()) 7.120 xc = Xc.new() 7.121 - self.evtchn = xc.evtchn_bind_interdomain(dom1=0,dom2=self.dom) 7.122 + self.evtchn = xc.evtchn_bind_interdomain( \ 7.123 + dom1=xend.netif.be_port.remote_dom, \ 7.124 + dom2=self.dom) 7.125 msg = xend.utils.message(CMSG_NETIF_BE, \ 7.126 CMSG_NETIF_BE_CONNECT, 0) 7.127 msg.append_payload(struct.pack("IIILLI",self.dom,0, \
8.1 --- a/xen/common/physdev.c Thu Jun 03 11:45:16 2004 +0000 8.2 +++ b/xen/common/physdev.c Thu Jun 03 13:33:37 2004 +0000 8.3 @@ -147,6 +147,9 @@ int physdev_pci_access_modify( 8.4 8.5 /* Make the domain privileged. */ 8.6 set_bit(PF_PHYSDEV, &p->flags); 8.7 + /* FIXME: MAW for now make the domain REALLY privileged so that it 8.8 + * can run a backend driver (hw access should work OK otherwise) */ 8.9 + set_bit(PF_PRIVILEGED, &p->flags); 8.10 8.11 /* Grant write access to the specified device. */ 8.12 if ( (pdev = pci_find_slot(bus, PCI_DEVFN(dev, func))) == NULL )
9.1 --- a/xen/include/hypervisor-ifs/hypervisor-if.h Thu Jun 03 11:45:16 2004 +0000 9.2 +++ b/xen/include/hypervisor-ifs/hypervisor-if.h Thu Jun 03 13:33:37 2004 +0000 9.3 @@ -398,7 +398,9 @@ typedef struct { 9.4 9.5 /* These flags are passed in the 'flags' field of start_info_t. */ 9.6 #define SIF_PRIVILEGED 1 /* Is the domain privileged? */ 9.7 -#define SIF_INITDOMAIN 2 /* Is thsi the initial control domain? */ 9.8 +#define SIF_INITDOMAIN 2 /* Is this the initial control domain? */ 9.9 +#define SIF_BLK_BE_DOMAIN 4 /* Is this a block backend domain? */ 9.10 +#define SIF_NET_BE_DOMAIN 8 /* Is this a net backend domain? */ 9.11 9.12 /* For use in guest OSes. */ 9.13 extern shared_info_t *HYPERVISOR_shared_info;
10.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c Thu Jun 03 11:45:16 2004 +0000 10.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/backend/main.c Thu Jun 03 13:33:37 2004 +0000 10.3 @@ -732,9 +732,12 @@ static int __init init_module(void) 10.4 { 10.5 int i; 10.6 10.7 - if ( !(start_info.flags & SIF_INITDOMAIN) ) 10.8 + if ( !(start_info.flags & SIF_NET_BE_DOMAIN) && 10.9 + !(start_info.flags & SIF_INIT_DOMAIN) ) 10.10 return 0; 10.11 10.12 + printk("Initialising Xen virtual ethernet backend driver\n"); 10.13 + 10.14 skb_queue_head_init(&rx_queue); 10.15 skb_queue_head_init(&tx_queue); 10.16
11.1 --- a/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/main.c Thu Jun 03 11:45:16 2004 +0000 11.2 +++ b/xenolinux-2.4.26-sparse/arch/xen/drivers/netif/frontend/main.c Thu Jun 03 13:33:37 2004 +0000 11.3 @@ -28,6 +28,8 @@ 11.4 #include <asm/evtchn.h> 11.5 #include <asm/ctrl_if.h> 11.6 11.7 +#include <asm/page.h> 11.8 + 11.9 #include "../netif.h" 11.10 11.11 #define RX_BUF_SIZE ((PAGE_SIZE/2)+1) /* Fool the slab allocator :-) */ 11.12 @@ -55,6 +57,7 @@ struct net_private 11.13 netif_rx_interface_t *rx; 11.14 11.15 spinlock_t tx_lock; 11.16 + spinlock_t rx_lock; 11.17 11.18 unsigned int handle; 11.19 unsigned int evtchn; 11.20 @@ -83,7 +86,6 @@ struct net_private 11.21 (_list)[0] = (_list)[_id]; \ 11.22 (unsigned short)_id; }) 11.23 11.24 - 11.25 static struct net_device *find_dev_by_handle(unsigned int handle) 11.26 { 11.27 struct list_head *ent; 11.28 @@ -109,6 +111,7 @@ static int network_open(struct net_devic 11.29 np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0; 11.30 memset(&np->stats, 0, sizeof(np->stats)); 11.31 spin_lock_init(&np->tx_lock); 11.32 + spin_lock_init(&np->rx_lock); 11.33 11.34 /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */ 11.35 for ( i = 0; i <= NETIF_TX_RING_SIZE; i++ ) 11.36 @@ -198,8 +201,9 @@ static void network_alloc_rx_buffers(str 11.37 panic("alloc_skb needs to provide us page-aligned buffers."); 11.38 11.39 id = GET_ID_FROM_FREELIST(np->rx_skbs); 11.40 + 11.41 np->rx_skbs[id] = skb; 11.42 - 11.43 + 11.44 np->rx->ring[MASK_NET_RX_IDX(i)].req.id = id; 11.45 11.46 rx_pfn_array[nr_pfns] = virt_to_machine(skb->head) >> PAGE_SHIFT; 11.47 @@ -267,6 +271,13 @@ static int network_start_xmit(struct sk_ 11.48 11.49 spin_lock_irq(&np->tx_lock); 11.50 11.51 + /* if the backend isn't available then don't do anything! */ 11.52 + if ( !netif_carrier_ok(dev) ) 11.53 + { 11.54 + spin_unlock_irq(&np->tx_lock); 11.55 + return 1; 11.56 + } 11.57 + 11.58 i = np->tx->req_prod; 11.59 11.60 id = GET_ID_FROM_FREELIST(np->tx_skbs); 11.61 @@ -310,6 +321,13 @@ static void netif_int(int irq, void *dev 11.62 unsigned long flags; 11.63 11.64 spin_lock_irqsave(&np->tx_lock, flags); 11.65 + 11.66 + if( !netif_carrier_ok(dev) ) 11.67 + { 11.68 + spin_unlock_irqrestore(&np->tx_lock, flags); 11.69 + return; 11.70 + } 11.71 + 11.72 network_tx_buf_gc(dev); 11.73 spin_unlock_irqrestore(&np->tx_lock, flags); 11.74 11.75 @@ -330,6 +348,15 @@ static int netif_poll(struct net_device 11.76 struct sk_buff_head rxq; 11.77 unsigned long flags; 11.78 11.79 + spin_lock(&np->rx_lock); 11.80 + 11.81 + /* if the device is undergoing recovery then don't do anything */ 11.82 + if ( !netif_carrier_ok(dev) ) 11.83 + { 11.84 + spin_unlock(&np->rx_lock); 11.85 + return 0; 11.86 + } 11.87 + 11.88 skb_queue_head_init(&rxq); 11.89 11.90 if ( (budget = *pbudget) > dev->quota ) 11.91 @@ -425,6 +452,8 @@ static int netif_poll(struct net_device 11.92 local_irq_restore(flags); 11.93 } 11.94 11.95 + spin_unlock(&np->rx_lock); 11.96 + 11.97 return more_to_do; 11.98 } 11.99 11.100 @@ -465,7 +494,10 @@ static void netif_status_change(netif_fe 11.101 netif_fe_interface_connect_t up; 11.102 struct net_device *dev; 11.103 struct net_private *np; 11.104 - 11.105 + int i; 11.106 + 11.107 + unsigned long tsc; 11.108 + 11.109 if ( status->handle != 0 ) 11.110 { 11.111 printk(KERN_WARNING "Status change on unsupported netif %d\n", 11.112 @@ -488,7 +520,29 @@ static void netif_status_change(netif_fe 11.113 { 11.114 printk(KERN_WARNING "Unexpected netif-DISCONNECTED message" 11.115 " in state %d\n", np->state); 11.116 - break; 11.117 + printk(KERN_INFO "Attempting to reconnect network interface\n"); 11.118 + 11.119 + /* Begin interface recovery. 11.120 + * TODO: Change the Xend<->Guest protocol so that a recovery 11.121 + * is initiated by a special "RESET" message - disconnect could 11.122 + * just mean we're not allowed to use this interface any more. 11.123 + */ 11.124 + 11.125 + /* Stop old i/f to prevent errors whilst we rebuild the state. */ 11.126 + spin_lock_irq(&np->tx_lock); 11.127 + spin_lock_irq(&np->rx_lock); 11.128 + netif_stop_queue(dev); 11.129 + netif_carrier_off(dev); 11.130 + np->state = NETIF_STATE_DISCONNECTED; 11.131 + spin_unlock_irq(&np->rx_lock); 11.132 + spin_unlock_irq(&np->tx_lock); 11.133 + 11.134 + /* Free resources. */ 11.135 + free_irq(np->irq, dev); 11.136 + unbind_evtchn_from_irq(np->evtchn); 11.137 + 11.138 + free_page((unsigned long)np->tx); 11.139 + free_page((unsigned long)np->rx); 11.140 } 11.141 11.142 /* Move from CLOSED to DISCONNECTED state. */ 11.143 @@ -521,12 +575,83 @@ static void netif_status_change(netif_fe 11.144 11.145 memcpy(dev->dev_addr, status->mac, ETH_ALEN); 11.146 11.147 + if(netif_carrier_ok(dev)) 11.148 + np->state = NETIF_STATE_CONNECTED; 11.149 + else 11.150 + { 11.151 + int i, requeue_idx; 11.152 + netif_tx_request_t *tx; 11.153 + 11.154 + spin_lock_irq(&np->rx_lock); 11.155 + spin_lock(&np->tx_lock); 11.156 + 11.157 + /* Recovery procedure: */ 11.158 + 11.159 + /* Step 1: Reinitialise variables. */ 11.160 + np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0; 11.161 + np->rx->event = 1; 11.162 + 11.163 + /* Step 1: Rebuild the RX and TX ring contents. 11.164 + * NB. We could just throw away the queued TX packets but we hope 11.165 + * that sending them out might do some good. We have to rebuild 11.166 + * the RX ring because some of our pages are currently flipped out 11.167 + * so we can't just free the RX skbs. 11.168 + * NB2. Freelist index entries are always going to be less than 11.169 + * __PAGE_OFFSET, whereas pointers to skbs will always be equal or 11.170 + * greater than __PAGE_OFFSET, so we use this to distinguish them. 11.171 + */ 11.172 + 11.173 + /* Rebuild the TX buffer freelist and the TX ring itself. 11.174 + * NB. This reorders packets :-( We could keep more private state 11.175 + * to avoid this but maybe it doesn't matter so much given the 11.176 + * interface has been down. 11.177 + */ 11.178 + for ( requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++ ) 11.179 + { 11.180 + if ( np->tx_skbs[i] >= __PAGE_OFFSET ) 11.181 + { 11.182 + struct sk_buff *skb = np->tx_skbs[i]; 11.183 + 11.184 + tx = &np->tx->ring[MASK_NET_TX_IDX(requeue_idx++)].req; 11.185 + 11.186 + tx->id = i; 11.187 + tx->addr = virt_to_machine(skb->data); 11.188 + tx->size = skb->len; 11.189 + 11.190 + np->stats.tx_bytes += skb->len; 11.191 + np->stats.tx_packets++; 11.192 + } 11.193 + } 11.194 + wmb(); 11.195 + np->tx->req_prod = requeue_idx; 11.196 + 11.197 + /* Rebuild the RX buffer freelist and the RX ring itself. */ 11.198 + for ( requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++ ) 11.199 + if ( np->rx_skbs[i] >= __PAGE_OFFSET ) 11.200 + np->rx->ring[requeue_idx++].req.id = i; 11.201 + wmb(); 11.202 + np->rx->req_prod = requeue_idx; 11.203 + 11.204 + /* Step 4: All public and private state should now be sane. Start 11.205 + * sending and receiving packets again and give the driver domain a 11.206 + * kick because we've probably just queued some packets. */ 11.207 + 11.208 + netif_carrier_on(dev); 11.209 + netif_start_queue(dev); 11.210 + np->state = NETIF_STATE_ACTIVE; 11.211 + 11.212 + notify_via_evtchn(status->evtchn); 11.213 + 11.214 + printk(KERN_INFO "Recovery completed\n"); 11.215 + 11.216 + spin_unlock(&np->tx_lock); 11.217 + spin_unlock_irq(&np->rx_lock); 11.218 + } 11.219 + 11.220 np->evtchn = status->evtchn; 11.221 np->irq = bind_evtchn_to_irq(np->evtchn); 11.222 (void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM, 11.223 - dev->name, dev); 11.224 - 11.225 - np->state = NETIF_STATE_CONNECTED; 11.226 + dev->name, dev); 11.227 break; 11.228 11.229 default: 11.230 @@ -568,9 +693,12 @@ static int __init init_module(void) 11.231 struct net_device *dev; 11.232 struct net_private *np; 11.233 11.234 - if ( start_info.flags & SIF_INITDOMAIN ) 11.235 + if ( start_info.flags & SIF_INITDOMAIN 11.236 + || start_info.flags & SIF_NET_BE_DOMAIN ) 11.237 return 0; 11.238 11.239 + printk("Initialising Xen virtual ethernet frontend driver"); 11.240 + 11.241 INIT_LIST_HEAD(&dev_list); 11.242 11.243 if ( (dev = alloc_etherdev(sizeof(struct net_private))) == NULL ) 11.244 @@ -608,8 +736,9 @@ static int __init init_module(void) 11.245 cmsg.length = sizeof(netif_fe_driver_status_changed_t); 11.246 st.status = NETIF_DRIVER_STATUS_UP; 11.247 memcpy(cmsg.msg, &st, sizeof(st)); 11.248 + 11.249 ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); 11.250 - 11.251 + 11.252 /* 11.253 * We should read 'nr_interfaces' from response message and wait 11.254 * for notifications before proceeding. For now we assume that we