File: netif.py

package info (click to toggle)
xen-3.0 3.0.3-0-2
  • links: PTS
  • area: main
  • in suites: etch-m68k
  • size: 31,772 kB
  • ctags: 70,362
  • sloc: ansic: 417,153; python: 28,855; asm: 23,892; sh: 5,157; makefile: 4,830; objc: 613; perl: 372; xml: 351
file content (215 lines) | stat: -rw-r--r-- 6,920 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#============================================================================
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
# Copyright (C) 2005 XenSource Ltd
#============================================================================


"""Support for virtual network interfaces.
"""

import os
import random
import re

from xen.xend import sxp
from xen.xend import XendRoot

from xen.xend.server.DevController import DevController


xroot = XendRoot.instance()


def randomMAC():
    """Generate a random MAC address.

    Uses OUI (Organizationally Unique Identifier) 00-16-3E, allocated to
    Xensource, Inc. The OUI list is available at
    http://standards.ieee.org/regauth/oui/oui.txt.

    The remaining 3 fields are random, with the first bit of the first
    random field set 0.

    @return: MAC address string
    """
    mac = [ 0x00, 0x16, 0x3e,
            random.randint(0x00, 0x7f),
            random.randint(0x00, 0xff),
            random.randint(0x00, 0xff) ]
    return ':'.join(map(lambda x: "%02x" % x, mac))

rate_re = re.compile("^([0-9]+)([GMK]?)([Bb])/s(@([0-9]+)([mu]?)s)?$")

def parseRate(ratestr):
    """if parsing fails this will return default of unlimited rate"""
    bytes_per_interval = 0xffffffffL # 0xffffffff # big default
    interval_usecs     = 0L          # disabled

    m = rate_re.match(ratestr)
    if m:
        bytes_per_sec = long(m.group(1))

        if m.group(2) == 'G':
            bytes_per_sec *= 1000 * 1000 * 1000
        elif m.group(2) == 'M':
            bytes_per_sec *= 1000 * 1000
        elif m.group(2) == 'K':
            bytes_per_sec *= 1000

        if m.group(3) == 'b':
            bytes_per_sec /= 8

        if m.group(5) is None:
            interval_usecs = 50000L      # 50ms default
        else:
            interval_usecs = long(m.group(5))
            if m.group(6) == '':
                interval_usecs *= 1000 * 1000
            elif m.group(6) == 'm':
                interval_usecs *= 1000

        bytes_per_interval = (bytes_per_sec * interval_usecs) / 1000000L

        # overflow / underflow checking: default to unlimited rate
        if bytes_per_interval == 0 or bytes_per_interval > 0xffffffffL or \
           interval_usecs == 0 or interval_usecs > 0xffffffffL:
            bytes_per_interval = 0xffffffffL
            interval_usecs     = 0L

    return "%lu,%lu" % (bytes_per_interval, interval_usecs)


write_rate_G_re = re.compile('^([0-9]+)000000000(B/s@[0-9]+us)$')
write_rate_M_re = re.compile('^([0-9]+)000000(B/s@[0-9]+us)$')
write_rate_K_re = re.compile('^([0-9]+)000(B/s@[0-9]+us)$')
write_rate_s_re = re.compile('^([0-9]+[GMK]?B/s@[0-9]+)000000us$')
write_rate_m_re = re.compile('^([0-9]+[GMK]?B/s@[0-9]+)000us$')

def formatRate(rate):
    (bytes_per_interval, interval_usecs) = map(long, rate.split(','))

    if interval_usecs != 0:
        bytes_per_second = (bytes_per_interval * 1000 * 1000) / interval_usecs
    else:
        bytes_per_second = 0xffffffffL

    ratestr = "%uB/s@%uus" % (bytes_per_second, interval_usecs)

    # look for '000's
    m = write_rate_G_re.match(ratestr)
    if m:
        ratestr = m.group(1) + "G" + m.group(2)
    else:
        m = write_rate_M_re.match(ratestr)
        if m:
            ratestr = m.group(1) + "M" + m.group(2)
        else:
            m = write_rate_K_re.match(ratestr)
            if m:
                ratestr = m.group(1) + "K" + m.group(2)

    m = write_rate_s_re.match(ratestr)
    if m:
        ratestr = m.group(1) + "s"
    else:
        m = write_rate_m_re.match(ratestr)
        if m:
            ratestr = m.group(1) + "ms"

    return ratestr


class NetifController(DevController):
    """Network interface controller. Handles all network devices for a domain.
    """
    
    def __init__(self, vm):
        DevController.__init__(self, vm)


    def getDeviceDetails(self, config):
        """@see DevController.getDeviceDetails"""

        def _get_config_ipaddr(config):
            val = []
            for ipaddr in sxp.children(config, elt='ip'):
                val.append(sxp.child0(ipaddr))
            return val

        script = os.path.join(xroot.network_script_dir,
                              sxp.child_value(config, 'script',
                                              xroot.get_vif_script()))
        typ = sxp.child_value(config, 'type')
        bridge  = sxp.child_value(config, 'bridge')
        mac     = sxp.child_value(config, 'mac')
        vifname = sxp.child_value(config, 'vifname')
        rate    = sxp.child_value(config, 'rate')
        ipaddr  = _get_config_ipaddr(config)

        devid = self.allocateDeviceID()

        if not mac:
            mac = randomMAC()

        back = { 'script' : script,
                 'mac'    : mac,
                 'handle' : "%i" % devid }

        if typ == 'ioemu':
            front = {}
            back['type'] = 'ioemu'
        else:
            front = { 'handle' : "%i" % devid,
                      'mac'    : mac }
        if ipaddr:
            back['ip'] = ' '.join(ipaddr)
        if bridge:
            back['bridge'] = bridge
        if vifname:
            back['vifname'] = vifname
        if rate:
            back['rate'] = parseRate(rate)

        return (devid, back, front)


    def configuration(self, devid):
        """@see DevController.configuration"""

        result = DevController.configuration(self, devid)

        (script, ip, bridge, mac, typ, vifname, rate) = self.readBackend(
            devid, 'script', 'ip', 'bridge', 'mac', 'type', 'vifname', 'rate')

        if script:
            result.append(['script',
                           script.replace(xroot.network_script_dir + os.sep,
                                          "")])
        if ip:
            for i in ip.split(" "):
                result.append(['ip', i])
        if bridge:
            result.append(['bridge', bridge])
        if mac:
            result.append(['mac', mac])
        if typ:
            result.append(['type', typ])
        if vifname:
            result.append(['vifname', vifname])
        if rate:
            result.append(['rate', formatRate(rate)])

        return result