diff options
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/examples/xc_dom_create.py | 13 | ||||
-rw-r--r-- | tools/xenctl/lib/utils.py | 10 | ||||
-rw-r--r-- | tools/xend/lib/domain_controller.h | 1 | ||||
-rwxr-xr-x | tools/xend/lib/main.py | 25 | ||||
-rw-r--r-- | tools/xend/lib/manager.py | 39 | ||||
-rw-r--r-- | tools/xend/lib/netif.py | 144 |
6 files changed, 222 insertions, 10 deletions
diff --git a/tools/examples/xc_dom_create.py b/tools/examples/xc_dom_create.py index 22479a9d14..19bb2ac9df 100755 --- a/tools/examples/xc_dom_create.py +++ b/tools/examples/xc_dom_create.py @@ -333,7 +333,18 @@ def make_domain(): xc.domain_destroy ( dom=id ) sys.exit() - if not new_io_world: + if new_io_world: + cmsg = 'new_network_interface(dom='+str(id)+')' + xend_response = xenctl.utils.xend_control_message(cmsg) + if not xend_response['success']: + print "Error creating network interface" + print "Error type: " + xend_response['error_type'] + if xend_response['error_type'] == 'exception': + print "Exception type: " + xend_response['exception_type'] + print "Exception val: " + xend_response['exception_value'] + xc.domain_destroy ( dom=id ) + sys.exit() + else: # setup virtual firewall rules for all aliases for ip in vfr_ipaddr: xenctl.utils.setup_vfr_rules_for_vif( id, 0, ip ) diff --git a/tools/xenctl/lib/utils.py b/tools/xenctl/lib/utils.py index 3f0914f73f..11aadb4f08 100644 --- a/tools/xenctl/lib/utils.py +++ b/tools/xenctl/lib/utils.py @@ -54,15 +54,13 @@ def get_current_ipmask(dev='eth0'): return m.group(1) return None -def get_current_ipgw(dev='eth0'): - """Return a string containing the IP gateway for the given - network interface (default 'eth0'). - """ +def get_current_ipgw(): + """Return a string containing the default IP gateway.""" fd = os.popen( '/sbin/route -n' ) lines = fd.readlines() for line in lines: - m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' + - '\s+\S+\s+\S*G.*' + dev + '.*', line ) + m = re.search( '^0.0.0.0+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' + + '\s+0.0.0.0+\s+\S*G.*', line ) if m: return m.group(1) return None diff --git a/tools/xend/lib/domain_controller.h b/tools/xend/lib/domain_controller.h index d5c397fe96..566967dc38 100644 --- a/tools/xend/lib/domain_controller.h +++ b/tools/xend/lib/domain_controller.h @@ -468,7 +468,6 @@ typedef struct { unsigned int evtchn; /* Event channel for notifications. */ unsigned long tx_shmem_frame; /* Page cont. tx shared comms window. */ unsigned long rx_shmem_frame; /* Page cont. rx shared comms window. */ - unsigned long shmem_frame; /* OUT */ unsigned int status; } netif_be_connect_t; diff --git a/tools/xend/lib/main.py b/tools/xend/lib/main.py index 7b5adbab83..0056783d7f 100755 --- a/tools/xend/lib/main.py +++ b/tools/xend/lib/main.py @@ -5,7 +5,7 @@ ########################################################### import errno, re, os, pwd, select, signal, socket, struct, sys, time -import xend.blkif, xend.console, xend.manager, xend.utils, Xc +import xend.blkif, xend.netif, xend.console, xend.manager, xend.utils, Xc # The following parameters could be placed in a configuration file. @@ -19,6 +19,8 @@ UNIX_SOCK = 'management_sock' # relative to CONTROL_DIR CMSG_CONSOLE = 0 CMSG_BLKIF_BE = 1 CMSG_BLKIF_FE = 2 +CMSG_NETIF_BE = 3 +CMSG_NETIF_FE = 4 def port_from_dom(dom): @@ -162,6 +164,10 @@ def daemon_loop(): if xend.blkif.interface.list.has_key(idx): blk_if = xend.blkif.interface.list[idx] + net_if = False + if xend.netif.interface.list.has_key(idx): + net_if = xend.netif.interface.list[idx] + # If we pick up a disconnect notification then we do any necessary # cleanup. if type == notifier.EXCEPTION: @@ -175,6 +181,9 @@ def daemon_loop(): if blk_if: blk_if.destroy() del blk_if + if net_if: + net_if.destroy() + del net_if continue # Process incoming requests. @@ -188,6 +197,10 @@ def daemon_loop(): blk_if.ctrlif_rx_req(port, msg) elif type == CMSG_BLKIF_BE and port == dom0_port: xend.blkif.backend_rx_req(port, msg) + elif type == CMSG_NETIF_FE and net_if: + net_if.ctrlif_rx_req(port, msg) + elif type == CMSG_NETIF_BE and port == dom0_port: + xend.netif.backend_rx_req(port, msg) else: port.write_response(msg) @@ -198,6 +211,8 @@ def daemon_loop(): type = (msg.get_header())['type'] if type == CMSG_BLKIF_BE and port == dom0_port: xend.blkif.backend_rx_rsp(port, msg) + elif type == CMSG_NETIF_BE and port == dom0_port: + xend.netif.backend_rx_rsp(port, msg) # Send console data. if con_if and con_if.ctrlif_transmit_work(port): @@ -207,10 +222,18 @@ def daemon_loop(): if blk_if and blk_if.ctrlif_transmit_work(port): work_done = True + # Send netif messages. + if net_if and net_if.ctrlif_transmit_work(port): + work_done = True + # Back-end block-device work. if port == dom0_port and xend.blkif.backend_do_work(port): work_done = True + # Back-end network-device work. + if port == dom0_port and xend.netif.backend_do_work(port): + work_done = True + # Finally, notify the remote end of any work that we did. if work_done: port.notify() diff --git a/tools/xend/lib/manager.py b/tools/xend/lib/manager.py index ea7398cd4c..2f15683d66 100644 --- a/tools/xend/lib/manager.py +++ b/tools/xend/lib/manager.py @@ -4,7 +4,7 @@ ## Copyright (c) 2004, K A Fraser (University of Cambridge) ############################################################# -import xend.blkif, xend.console, xend.main, xend.utils +import xend.blkif, xend.netif, xend.console, xend.main, xend.utils ## @@ -113,3 +113,40 @@ def new_block_device(dom, handle, vdev, pdev, start_sect, nr_sect, readonly): # Response is deferred until back-end driver sends acknowledgement. return None + + +## +## new_network_interface: +## Create a new network interface for the specified domain @dom. +## +def new_network_interface(dom, handle=-1): + # By default we create an interface with handle zero. + if handle < 0: + handle = 0 + + # We only support one interface per domain, which must have handle zero. + if handle != 0: + response = { 'success': False } + response['error_type'] = 'Bad handle %d (only handle 0 ' + \ + 'is supported)' % handle + return response + + # Find local event-channel port associated with the specified domain. + port = xend.main.port_from_dom(dom) + if not port: + response = { 'success': False } + response['error_type'] = 'Unknown domain %d' % dom + return response + + # The interface must not already exist. + if xend.netif.interface.list.has_key(port.local_port): + response = { 'success': False } + response['error_type'] = 'Interface (dom=%d,handle=%d) already ' + \ + 'exists' % (dom, handle) + return response + + # Create the new interface. Initially no virtual devices are attached. + xend.netif.interface(dom, port.local_port) + + # Response is deferred until back-end driver sends acknowledgement. + return None diff --git a/tools/xend/lib/netif.py b/tools/xend/lib/netif.py new file mode 100644 index 0000000000..11756c5e56 --- /dev/null +++ b/tools/xend/lib/netif.py @@ -0,0 +1,144 @@ + +################################################################### +## xend/netif.py -- Network-interface management functions for Xend +## Copyright (c) 2004, K A Fraser (University of Cambridge) +################################################################### + +import errno, random, re, os, select, signal, socket, struct, sys +import xend.main, xend.console, xend.manager, xend.utils, Xc + +CMSG_NETIF_BE = 3 +CMSG_NETIF_FE = 4 +CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED = 0 +CMSG_NETIF_FE_DRIVER_STATUS_CHANGED = 32 +CMSG_NETIF_FE_INTERFACE_CONNECT = 33 +CMSG_NETIF_FE_INTERFACE_DISCONNECT = 34 +CMSG_NETIF_BE_CREATE = 0 +CMSG_NETIF_BE_DESTROY = 1 +CMSG_NETIF_BE_CONNECT = 2 +CMSG_NETIF_BE_DISCONNECT = 3 + +pendmsg = None +pendaddr = None + +def backend_tx_req(msg): + port = xend.main.dom0_port + if port.space_to_write_request(): + port.write_request(msg) + port.notify() + else: + xend.netif.pendmsg = msg + +def backend_rx_req(port, msg): + port.write_response(msg) + +def backend_rx_rsp(port, msg): + subtype = (msg.get_header())['subtype'] + print "Received netif-be response, subtype %d" % subtype + if subtype == CMSG_NETIF_BE_CREATE: + rsp = { 'success': True } + xend.main.send_management_response(rsp, xend.netif.pendaddr) + elif subtype == CMSG_NETIF_BE_CONNECT: + (dom,hnd,evtchn,tx_frame,rx_frame,st) = \ + struct.unpack("QIILLI", msg.get_payload()) + netif = interface.list[xend.main.port_from_dom(dom).local_port] + msg = xend.utils.message(CMSG_NETIF_FE, \ + CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0) + msg.append_payload(struct.pack("IIIBBBBBBBB",0,2, \ + netif.evtchn['port2'], \ + netif.mac[0],netif.mac[1], \ + netif.mac[2],netif.mac[3], \ + netif.mac[4],netif.mac[5], \ + 0,0)) + netif.ctrlif_tx_req(xend.main.port_list[netif.key], msg) + +def backend_do_work(port): + global pendmsg + if pendmsg and port.space_to_write_request(): + port.write_request(pendmsg) + pendmsg = None + return True + return False + + +class interface: + + # Dictionary of all network-device interfaces. + list = {} + + + # NB. 'key' is an opaque value that has no meaning in this class. + def __init__(self, dom, key): + self.dom = dom + self.key = key + self.pendmsg = None + + # VIFs get a random MAC address with a "special" vendor id. + # + # NB. The vendor is currently an "obsolete" one that used to belong + # to DEC (AA-00-00). Using it is probably a bit rude :-) + # + # NB2. The first bit of the first random octet is set to zero for + # all dynamic MAC addresses. This may allow us to manually specify + # MAC addresses for some VIFs with no fear of clashes. + self.mac = [ 0xaa, 0x00, 0x00 ] + self.mac.append(int(random.random()*128)) + self.mac.append(int(random.random()*256)) + self.mac.append(int(random.random()*256)) + + interface.list[key] = self + msg = xend.utils.message(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE, 0) + msg.append_payload(struct.pack("QIBBBBBBBBI",dom,0, \ + self.mac[0],self.mac[1], \ + self.mac[2],self.mac[3], \ + self.mac[4],self.mac[5], \ + 0,0,0)) + xend.netif.pendaddr = xend.main.mgmt_req_addr + backend_tx_req(msg) + + + # Completely destroy this interface. + def destroy(self): + del interface.list[self.key] + msg = xend.utils.message(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY, 0) + msg.append_payload(struct.pack("QII",self.dom,0,0)) + backend_tx_req(msg) + + + # The parameter @port is the control-interface event channel. This method + # returns True if messages were written to the control interface. + def ctrlif_transmit_work(self, port): + if self.pendmsg and port.space_to_write_request(): + port.write_request(self.pendmsg) + self.pendmsg = None + return True + return False + + def ctrlif_tx_req(self, port, msg): + if port.space_to_write_request(): + port.write_request(msg) + port.notify() + else: + self.pendmsg = msg + + def ctrlif_rx_req(self, port, msg): + port.write_response(msg) + subtype = (msg.get_header())['subtype'] + if subtype == CMSG_NETIF_FE_DRIVER_STATUS_CHANGED: + msg = xend.utils.message(CMSG_NETIF_FE, \ + CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0) + msg.append_payload(struct.pack("IIIBBBBBBBB",0,1,0,self.mac[0], \ + self.mac[1],self.mac[2], \ + self.mac[3],self.mac[4], \ + self.mac[5],0,0)) + self.ctrlif_tx_req(port, msg) + elif subtype == CMSG_NETIF_FE_INTERFACE_CONNECT: + (hnd,tx_frame,rx_frame) = struct.unpack("ILL", msg.get_payload()) + xc = Xc.new() + self.evtchn = xc.evtchn_bind_interdomain(dom1=0,dom2=self.dom) + msg = xend.utils.message(CMSG_NETIF_BE, \ + CMSG_NETIF_BE_CONNECT, 0) + msg.append_payload(struct.pack("QIILLI",self.dom,0, \ + self.evtchn['port1'],tx_frame, \ + rx_frame,0)) + backend_tx_req(msg) |