direct-io.hg

changeset 1427:73eb554453db

bitkeeper revision 1.931 (40bf28b1DSY6oBu4FDeGIob6_AJvUA)

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