ia64/xen-unstable

view tools/python/xen/xend/server/netif.py @ 1992:d004111c84fe

bitkeeper revision 1.1108.35.6 (41091d99KjjPC1MDTpjZgbI8NuFnog)

Fix mac formatting.
author mjw@wray-m-3.hpl.hp.com
date Thu Jul 29 15:54:01 2004 +0000 (2004-07-29)
parents 7fdc6f3e894c
children 0fe3e389d7e0
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 Vifctl
10 from xen.xend.XendError import XendError
11 from xen.xend.XendLogging import log
12 from xen.xend import XendVnet
14 import channel
15 import controller
16 from messages import *
18 class NetifControllerFactory(controller.ControllerFactory):
19 """Factory for creating network interface controllers.
20 Also handles the 'back-end' channel to the device driver domain.
21 """
23 def __init__(self):
24 controller.ControllerFactory.__init__(self)
26 self.majorTypes = [ CMSG_NETIF_BE ]
28 self.subTypes = {
29 #CMSG_NETIF_BE_CREATE : self.recv_be_create,
30 #CMSG_NETIF_BE_CONNECT: self.recv_be_connect,
31 CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
32 }
33 self.attached = 1
34 self.registerChannel()
36 def createInstance(self, dom, recreate=0):
37 """Create or find the network interface controller for a domain.
39 dom domain
40 recreate if true this is a recreate (xend restarted)
42 returns netif controller
43 """
44 netif = self.getInstanceByDom(dom)
45 if netif is None:
46 netif = NetifController(self, dom)
47 self.addInstance(netif)
48 return netif
50 def getDomainDevices(self, dom):
51 """Get the network device controllers for a domain.
53 dom domain
55 returns netif controller
56 """
57 netif = self.getInstanceByDom(dom)
58 return (netif and netif.getDevices()) or []
60 def getDomainDevice(self, dom, vif):
61 """Get a virtual network interface device for a domain.
63 dom domain
64 vif virtual interface index
66 returns NetDev
67 """
68 netif = self.getInstanceByDom(dom)
69 return (netif and netif.getDevice(vif)) or None
71 def setControlDomain(self, dom, recreate=0):
72 """Set the 'back-end' device driver domain.
74 dom domain
75 recreate if true this is a recreate (xend restarted)
76 """
77 if self.dom == dom: return
78 self.deregisterChannel()
79 if not recreate:
80 self.attached = 0
81 self.dom = dom
82 self.registerChannel()
84 def getControlDomain(self):
85 """Get the domain id of the back-end control domain.
86 """
87 return self.dom
89 def respond_be_connect(self, msg):
90 val = unpackMsg('netif_be_connect_t', msg)
91 dom = val['domid']
92 vif = val['netif_handle']
93 netif = self.getInstanceByDom(dom)
94 if netif:
95 netif.send_interface_connected(vif)
96 else:
97 log.warning("respond_be_connect> unknown dom=%d vif=%d", dom, vif)
98 pass
100 def recv_be_driver_status_changed(self, msg, req):
101 val = unpackMsg('netif_be_driver_status_changed_t', msg)
102 status = val['status']
103 if status == NETIF_DRIVER_STATUS_UP and not self.attached:
104 # If we are not attached the driver domain was changed, and
105 # this signals the new driver domain is ready.
106 for netif in self.getInstances():
107 netif.reattach_devices()
108 self.attached = 1
110 class NetDev(controller.Dev):
111 """Info record for a network device.
112 """
114 def __init__(self, ctrl, vif, config):
115 controller.Dev.__init__(self, vif, ctrl)
116 self.vif = vif
117 self.evtchn = None
118 self.configure(config)
120 def configure(self, config):
121 self.config = config
122 self.mac = None
123 self.bridge = None
124 self.script = None
125 self.ipaddr = []
127 vmac = sxp.child_value(config, 'mac')
128 if not vmac: raise XendError("invalid mac")
129 mac = [ int(x, 16) for x in vmac.split(':') ]
130 if len(mac) != 6: raise XendError("invalid mac")
131 self.mac = mac
133 self.bridge = sxp.child_value(config, 'bridge')
134 self.script = sxp.child_value(config, 'script')
136 ipaddrs = sxp.children(config, elt='ip')
137 for ipaddr in ipaddrs:
138 self.ipaddr.append(sxp.child0(ipaddr))
140 def sxpr(self):
141 vif = str(self.vif)
142 mac = self.get_mac()
143 val = ['vif',
144 ['idx', self.idx],
145 ['vif', vif],
146 ['mac', mac]]
147 if self.bridge:
148 val.append(['bridge', self.bridge])
149 if self.script:
150 val.append(['script', self.script])
151 for ip in self.ipaddr:
152 val.append(['ip', ip])
153 if self.evtchn:
154 val.append(['evtchn',
155 self.evtchn['port1'],
156 self.evtchn['port2']])
157 return val
159 def get_vifname(self):
160 """Get the virtual interface device name.
161 """
162 return "vif%d.%d" % (self.controller.dom, self.vif)
164 def get_mac(self):
165 """Get the MAC address as a string.
166 """
167 return ':'.join(map(lambda x: "%02x" % x, self.mac))
169 def vifctl_params(self, vmname=None):
170 dom = self.controller.dom
171 name = vmname or ('DOM%d' % dom)
172 return { 'domain': name,
173 'vif' : self.get_vifname(),
174 'mac' : self.get_mac(),
175 'bridge': self.bridge,
176 'script': self.script,
177 'ipaddr': self.ipaddr, }
179 def vifctl(self, op, vmname=None):
180 """Bring the device up or down.
181 """
182 Vifctl.vifctl(op, **self.vifctl_params(vmname=vmname))
183 vnet = XendVnet.instance().vnet_of_bridge(self.bridge)
184 if vnet:
185 vnet.vifctl(op, self.get_vifname(), self.get_mac())
187 def destroy(self):
188 """Destroy the device's resources and disconnect from the back-end
189 device controller.
190 """
191 def cb_destroy(val):
192 self.controller.send_be_destroy(self.vif)
193 log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif)
194 self.vifctl('down')
195 d = defer.Deferred()
196 d.addCallback(cb_destroy)
197 self.controller.send_be_disconnect(self.vif, response=d)
200 class NetifController(controller.Controller):
201 """Network interface controller. Handles all network devices for a domain.
202 """
204 def __init__(self, factory, dom):
205 controller.Controller.__init__(self, factory, dom)
206 self.devices = {}
208 self.majorTypes = [ CMSG_NETIF_FE ]
210 self.subTypes = {
211 CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
212 self.recv_fe_driver_status_changed,
213 CMSG_NETIF_FE_INTERFACE_CONNECT :
214 self.recv_fe_interface_connect,
215 }
216 self.registerChannel()
218 def sxpr(self):
219 val = ['netif', ['dom', self.dom]]
220 return val
222 def lostChannel(self):
223 """Method called when the channel has been lost.
224 """
225 controller.Controller.lostChannel(self)
227 def getDevices(self):
228 """Get a list of the devices.
229 """
230 return self.devices.values()
232 def getDevice(self, vif):
233 """Get a device.
235 vif device index
237 returns device (or None)
238 """
239 return self.devices.get(vif)
241 def addDevice(self, vif, config):
242 """Add a network interface.
244 vif device index
245 config device configuration
247 returns device
248 """
249 dev = NetDev(self, vif, config)
250 self.devices[vif] = dev
251 return dev
253 def destroy(self):
254 """Destroy the controller and all devices.
255 """
256 self.destroyDevices()
258 def destroyDevices(self):
259 for dev in self.getDevices():
260 dev.destroy()
262 def attachDevice(self, vif, config, recreate=0):
263 """Attach a network device.
264 If vmac is None a random mac address is assigned.
266 @param vif interface index
267 @param vmac mac address (string)
268 """
269 self.addDevice(vif, config)
270 d = defer.Deferred()
271 if recreate:
272 d.callback(self)
273 else:
274 self.send_be_create(vif, response=d)
275 return d
277 def reattach_devices(self):
278 """Reattach all devices when the back-end control domain has changed.
279 """
280 self.send_be_create(vif)
281 self.attach_fe_devices()
283 def attach_fe_devices(self):
284 for dev in self.devices.values():
285 msg = packMsg('netif_fe_interface_status_changed_t',
286 { 'handle' : dev.vif,
287 'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
288 'evtchn' : 0,
289 'mac' : dev.mac })
290 self.writeRequest(msg)
292 def recv_fe_driver_status_changed(self, msg, req):
293 if not req: return
294 msg = packMsg('netif_fe_driver_status_changed_t',
295 { 'status' : NETIF_DRIVER_STATUS_UP,
296 'nr_interfaces' : len(self.devices) })
297 self.writeRequest(msg)
298 self.attach_fe_devices()
300 def recv_fe_interface_connect(self, msg, req):
301 val = unpackMsg('netif_fe_interface_connect_t', msg)
302 dev = self.devices[val['handle']]
303 dev.evtchn = channel.eventChannel(0, self.dom)
304 msg = packMsg('netif_be_connect_t',
305 { 'domid' : self.dom,
306 'netif_handle' : dev.vif,
307 'evtchn' : dev.evtchn['port1'],
308 'tx_shmem_frame' : val['tx_shmem_frame'],
309 'rx_shmem_frame' : val['rx_shmem_frame'] })
310 d = defer.Deferred()
311 d.addCallback(self.factory.respond_be_connect)
312 self.factory.writeRequest(msg, response=d)
314 def send_interface_connected(self, vif, response=None):
315 dev = self.devices[vif]
316 msg = packMsg('netif_fe_interface_status_changed_t',
317 { 'handle' : dev.vif,
318 'status' : NETIF_INTERFACE_STATUS_CONNECTED,
319 'evtchn' : dev.evtchn['port2'],
320 'mac' : dev.mac })
321 self.writeRequest(msg, response=response)
323 def send_be_create(self, vif, response=None):
324 dev = self.devices[vif]
325 msg = packMsg('netif_be_create_t',
326 { 'domid' : self.dom,
327 'netif_handle' : dev.vif,
328 'mac' : dev.mac })
329 self.factory.writeRequest(msg, response=response)
331 def send_be_disconnect(self, vif, response=None):
332 dev = self.devices[vif]
333 msg = packMsg('netif_be_disconnect_t',
334 { 'domid' : self.dom,
335 'netif_handle' : dev.vif })
336 self.factory.writeRequest(msg, response=response)
338 def send_be_destroy(self, vif, response=None):
339 dev = self.devices[vif]
340 del self.devices[vif]
341 msg = packMsg('netif_be_destroy_t',
342 { 'domid' : self.dom,
343 'netif_handle' : vif })
344 self.factory.writeRequest(msg, response=response)