ia64/xen-unstable

view tools/python/xen/xend/server/netif.py @ 1727:ea24a5b766a2

bitkeeper revision 1.1058 (40ee95423ht4Gq0VKvBW7yu6DP8hZA)

Pass domain name down to vifctl to avoid recursion.
author mjw@wray-m-3.hpl.hp.com
date Fri Jul 09 12:53:22 2004 +0000 (2004-07-09)
parents e04e40b4615f
children e4a326567073
line source
1 # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 import random
5 from twisted.internet import defer
6 #defer.Deferred.debug = 1
8 from xen.xend import sxp
9 from xen.xend import PrettyPrint
10 from xen.xend import Vifctl
12 import channel
13 import controller
14 from messages import *
16 class NetifControllerFactory(controller.ControllerFactory):
17 """Factory for creating network interface controllers.
18 Also handles the 'back-end' channel to the device driver domain.
19 """
21 def __init__(self):
22 controller.ControllerFactory.__init__(self)
24 self.majorTypes = [ CMSG_NETIF_BE ]
26 self.subTypes = {
27 #CMSG_NETIF_BE_CREATE : self.recv_be_create,
28 #CMSG_NETIF_BE_CONNECT: self.recv_be_connect,
29 CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
30 }
31 self.attached = 1
32 self.registerChannel()
34 def createInstance(self, dom, recreate=0):
35 """Create or find the network interface controller for a domain.
37 dom domain
38 recreate if true this is a recreate (xend restarted)
40 returns netif controller
41 """
42 netif = self.getInstanceByDom(dom)
43 if netif is None:
44 netif = NetifController(self, dom)
45 self.addInstance(netif)
46 return netif
48 def getDomainDevices(self, dom):
49 """Get the network device controllers for a domain.
51 dom domain
53 returns netif controller
54 """
55 netif = self.getInstanceByDom(dom)
56 return (netif and netif.getDevices()) or []
58 def getDomainDevice(self, dom, vif):
59 """Get a virtual network interface device for a domain.
61 dom domain
62 vif virtual interface index
64 returns NetDev
65 """
66 netif = self.getInstanceByDom(dom)
67 return (netif and netif.getDevice(vif)) or None
69 def setControlDomain(self, dom, recreate=0):
70 """Set the 'back-end' device driver domain.
72 dom domain
73 recreate if true this is a recreate (xend restarted)
74 """
75 if self.dom == dom: return
76 self.deregisterChannel()
77 if not recreate:
78 self.attached = 0
79 self.dom = dom
80 self.registerChannel()
82 def getControlDomain(self):
83 """Get the domain id of the back-end control domain.
84 """
85 return self.dom
87 def respond_be_connect(self, msg):
88 val = unpackMsg('netif_be_connect_t', msg)
89 dom = val['domid']
90 vif = val['netif_handle']
91 netif = self.getInstanceByDom(dom)
92 if netif:
93 netif.send_interface_connected(vif)
94 else:
95 print "respond_be_connect> unknown vif=", vif
96 pass
98 def recv_be_driver_status_changed(self, msg, req):
99 val = unpackMsg('netif_be_driver_status_changed_t', msg)
100 status = val['status']
101 if status == NETIF_DRIVER_STATUS_UP and not self.attached:
102 # If we are not attached the driver domain was changed, and
103 # this signals the new driver domain is ready.
104 for netif in self.getInstances():
105 netif.reattach_devices()
106 self.attached = 1
108 class NetDev(controller.Dev):
109 """Info record for a network device.
110 """
112 def __init__(self, ctrl, vif, config):
113 controller.Dev.__init__(self, ctrl)
114 self.vif = vif
115 self.evtchn = None
116 self.configure(config)
118 def configure(self, config):
119 self.config = config
120 self.mac = None
121 self.bridge = None
122 self.script = None
123 self.ipaddr = None
125 vmac = sxp.child_value(config, 'mac')
126 if not vmac: raise ValueError("invalid mac")
127 mac = [ int(x, 16) for x in vmac.split(':') ]
128 if len(mac) != 6: raise ValueError("invalid mac")
129 self.mac = mac
131 self.bridge = sxp.child_value(config, 'bridge')
132 self.script = sxp.child_value(config, 'script')
134 ipaddrs = sxp.children(config, elt='ip')
135 for ipaddr in ipaddrs:
136 self.ipaddr.append(sxp.child0(ipaddr))
138 def sxpr(self):
139 vif = str(self.vif)
140 mac = self.get_mac()
141 val = ['vif', ['idx', vif], ['mac', mac]]
142 if self.bridge:
143 val.append(['bridge', self.bridge])
144 if self.script:
145 val.append(['script', self.script])
146 for ip in self.ipaddr:
147 val.append(['ip', ip])
148 if self.evtchn:
149 val.append(['evtchn',
150 self.evtchn['port1'],
151 self.evtchn['port2']])
152 return val
154 def get_vifname(self):
155 """Get the virtual interface device name.
156 """
157 return "vif%d.%d" % (self.controller.dom, self.vif)
159 def get_mac(self):
160 """Get the MAC address as a string.
161 """
162 return ':'.join(map(lambda x: "%x" % x, self.mac))
164 def vifctl_params(self, vmname=None):
165 dom = self.controller.dom
166 name = vmname or ('DOM%d' % dom)
167 return { 'domain': name,
168 'vif' : self.get_vifname(),
169 'mac' : self.get_mac(),
170 'bridge': self.bridge,
171 'script': self.script,
172 'ipaddr': self.ipaddr, }
174 def vifctl(self, op, vmname=None):
175 """Bring the device up or down.
176 """
177 Vifctl.vifctl(op, **self.vifctl_params(vmname=vmname))
179 def destroy(self):
180 """Destroy the device's resources and disconnect from the back-end
181 device controller.
182 """
183 def cb_destroy(val):
184 self.controller.send_be_destroy(self.vif)
185 self.vifctl('down')
186 d = defer.Deferred()
187 d.addCallback(cb_destroy)
188 self.controller.send_be_disconnect(self.vif, response=d)
191 class NetifController(controller.Controller):
192 """Network interface controller. Handles all network devices for a domain.
193 """
195 def __init__(self, factory, dom):
196 controller.Controller.__init__(self, factory, dom)
197 self.devices = {}
199 self.majorTypes = [ CMSG_NETIF_FE ]
201 self.subTypes = {
202 CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
203 self.recv_fe_driver_status_changed,
204 CMSG_NETIF_FE_INTERFACE_CONNECT :
205 self.recv_fe_interface_connect,
206 }
207 self.registerChannel()
209 def sxpr(self):
210 val = ['netif', ['dom', self.dom]]
211 return val
213 def lostChannel(self):
214 """Method called when the channel has been lost.
215 """
216 controller.Controller.lostChannel(self)
218 def getDevices(self):
219 """Get a list of the devices.
220 """
221 return self.devices.values()
223 def getDevice(self, vif):
224 """Get a device.
226 vif device index
228 returns device (or None)
229 """
230 return self.devices.get(vif)
232 def addDevice(self, vif, config):
233 """Add a network interface.
235 vif device index
236 config device configuration
238 returns device
239 """
240 dev = NetDev(self, vif, config)
241 self.devices[vif] = dev
242 return dev
244 def destroy(self):
245 """Destroy the controller and all devices.
246 """
247 self.destroyDevices()
249 def destroyDevices(self):
250 for dev in self.getDevices():
251 dev.destroy()
253 def attachDevice(self, vif, config, recreate=0):
254 """Attach a network device.
255 If vmac is None a random mac address is assigned.
257 @param vif interface index
258 @param vmac mac address (string)
259 """
260 self.addDevice(vif, config)
261 d = defer.Deferred()
262 if recreate:
263 d.callback(self)
264 else:
265 self.send_be_create(vif, response=d)
266 return d
268 def reattach_devices(self):
269 """Reattach all devices when the back-end control domain has changed.
270 """
271 self.send_be_create(vif)
272 self.attach_fe_devices()
274 def attach_fe_devices(self):
275 for dev in self.devices.values():
276 msg = packMsg('netif_fe_interface_status_changed_t',
277 { 'handle' : dev.vif,
278 'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
279 'evtchn' : 0,
280 'mac' : dev.mac })
281 self.writeRequest(msg)
283 def recv_fe_driver_status_changed(self, msg, req):
284 if not req: return
285 msg = packMsg('netif_fe_driver_status_changed_t',
286 { 'status' : NETIF_DRIVER_STATUS_UP,
287 'nr_interfaces' : len(self.devices) })
288 self.writeRequest(msg)
289 self.attach_fe_devices()
291 def recv_fe_interface_connect(self, msg, req):
292 val = unpackMsg('netif_fe_interface_connect_t', msg)
293 dev = self.devices[val['handle']]
294 dev.evtchn = channel.eventChannel(0, self.dom)
295 msg = packMsg('netif_be_connect_t',
296 { 'domid' : self.dom,
297 'netif_handle' : dev.vif,
298 'evtchn' : dev.evtchn['port1'],
299 'tx_shmem_frame' : val['tx_shmem_frame'],
300 'rx_shmem_frame' : val['rx_shmem_frame'] })
301 d = defer.Deferred()
302 d.addCallback(self.factory.respond_be_connect)
303 self.factory.writeRequest(msg, response=d)
305 def send_interface_connected(self, vif, response=None):
306 dev = self.devices[vif]
307 msg = packMsg('netif_fe_interface_status_changed_t',
308 { 'handle' : dev.vif,
309 'status' : NETIF_INTERFACE_STATUS_CONNECTED,
310 'evtchn' : dev.evtchn['port2'],
311 'mac' : dev.mac })
312 self.writeRequest(msg, response=response)
314 def send_be_create(self, vif, response=None):
315 dev = self.devices[vif]
316 msg = packMsg('netif_be_create_t',
317 { 'domid' : self.dom,
318 'netif_handle' : dev.vif,
319 'mac' : dev.mac })
320 self.factory.writeRequest(msg, response=response)
322 def send_be_disconnect(self, vif, response=None):
323 dev = self.devices[vif]
324 msg = packMsg('netif_be_disconnect_t',
325 { 'domid' : self.dom,
326 'netif_handle' : dev.vif })
327 self.factory.writeRequest(msg, response=response)
329 def send_be_destroy(self, vif, response=None):
330 PrettyPrint.prettyprint(self.sxpr())
331 dev = self.devices[vif]
332 del self.devices[vif]
333 msg = packMsg('netif_be_destroy_t',
334 { 'domid' : self.dom,
335 'netif_handle' : vif })
336 self.factory.writeRequest(msg, response=response)