Statistics
| Branch: | Tag: | Revision:

mininet / mininet / test / test_hifi.py @ 93ddd926

History | View | Annotate | Download (6.49 KB)

1
#!/usr/bin/env python
2

    
3
"""Package: mininet
4
   Test creation and pings for topologies with link and/or CPU options."""
5

    
6
import unittest
7
from functools import partial
8

    
9
from mininet.net import Mininet
10
from mininet.node import OVSSwitch, UserSwitch, IVSSwitch
11
from mininet.node import CPULimitedHost
12
from mininet.link import TCLink
13
from mininet.topo import Topo
14
from mininet.log import setLogLevel
15
from mininet.util import quietRun
16

    
17
# Number of hosts for each test
18
N = 2
19

    
20

    
21
class SingleSwitchOptionsTopo(Topo):
22
    "Single switch connected to n hosts."
23
    def __init__(self, n=2, hopts=None, lopts=None):
24
        if not hopts:
25
            hopts = {}
26
        if not lopts:
27
            lopts = {}
28
        Topo.__init__(self, hopts=hopts, lopts=lopts)
29
        switch = self.addSwitch('s1')
30
        for h in range(n):
31
            host = self.addHost('h%s' % (h + 1))
32
            self.addLink(host, switch)
33

    
34
# Tell pylint not to complain about calls to other class
35
# pylint: disable=E1101
36

    
37
class testOptionsTopoCommon( object ):
38
    """Verify ability to create networks with host and link options
39
       (common code)."""
40

    
41
    switchClass = None # overridden in subclasses
42

    
43
    def runOptionsTopoTest( self, n, hopts=None, lopts=None ):
44
        "Generic topology-with-options test runner."
45
        mn = Mininet( topo=SingleSwitchOptionsTopo( n=n, hopts=hopts,
46
                                                    lopts=lopts ),
47
                      host=CPULimitedHost, link=TCLink,
48
                      switch=self.switchClass )
49
        dropped = mn.run( mn.ping )
50
        self.assertEqual( dropped, 0 )
51

    
52
    def assertWithinTolerance(self, measured, expected, tolerance_frac):
53
        """Check that a given value is within a tolerance of expected
54
        tolerance_frac: less-than-1.0 value; 0.8 would yield 20% tolerance.
55
        """
56
        self.assertGreaterEqual( float(measured),
57
                                 float(expected) * tolerance_frac )
58
        self.assertLessEqual( float( measured ),
59
                                 float(expected) + (1-tolerance_frac)
60
                                 * float( expected ) )
61

    
62
    def testCPULimits( self ):
63
        "Verify topology creation with CPU limits set for both schedulers."
64
        CPU_FRACTION = 0.1
65
        CPU_TOLERANCE = 0.8  # CPU fraction below which test should fail
66
        hopts = { 'cpu': CPU_FRACTION }
67
        #self.runOptionsTopoTest( N, hopts=hopts )
68

    
69
        mn = Mininet( SingleSwitchOptionsTopo( n=N, hopts=hopts ),
70
                      host=CPULimitedHost, switch=self.switchClass )
71
        mn.start()
72
        results = mn.runCpuLimitTest( cpu=CPU_FRACTION )
73
        mn.stop()
74
        for pct in results:
75
            #divide cpu by 100 to convert from percentage to fraction
76
            self.assertWithinTolerance( pct/100, CPU_FRACTION, CPU_TOLERANCE )
77

    
78
    def testLinkBandwidth( self ):
79
        "Verify that link bandwidths are accurate within a bound."
80
        BW = .5  # Mbps
81
        BW_TOLERANCE = 0.8  # BW fraction below which test should fail
82
        # Verify ability to create limited-link topo first;
83
        lopts = { 'bw': BW, 'use_htb': True }
84
        # Also verify correctness of limit limitng within a bound.
85
        mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ),
86
                      link=TCLink, switch=self.switchClass )
87
        bw_strs = mn.run( mn.iperf, format='m' )
88
        for bw_str in bw_strs:
89
            bw = float( bw_str.split(' ')[0] )
90
            self.assertWithinTolerance( bw, BW, BW_TOLERANCE )
91

    
92
    def testLinkDelay( self ):
93
        "Verify that link delays are accurate within a bound."
94
        DELAY_MS = 15
95
        DELAY_TOLERANCE = 0.8  # Delay fraction below which test should fail
96
        lopts = { 'delay': '%sms' % DELAY_MS, 'use_htb': True }
97
        mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ),
98
                      link=TCLink, switch=self.switchClass, autoStaticArp=True )
99
        ping_delays = mn.run( mn.pingFull )
100
        test_outputs = ping_delays[0]
101
        # Ignore unused variables below
102
        # pylint: disable-msg=W0612
103
        node, dest, ping_outputs = test_outputs
104
        sent, received, rttmin, rttavg, rttmax, rttdev = ping_outputs
105
        self.assertEqual( sent, received )
106
        # pylint: enable-msg=W0612
107
        for rttval in [rttmin, rttavg, rttmax]:
108
            # Multiply delay by 4 to cover there & back on two links
109
            self.assertWithinTolerance( rttval, DELAY_MS * 4.0, 
110
                                        DELAY_TOLERANCE)
111

    
112

    
113
    def testLinkLoss( self ):
114
        "Verify that we see packet drops with a high configured loss rate."
115
        LOSS_PERCENT = 99
116
        REPS = 1
117
        lopts = { 'loss': LOSS_PERCENT, 'use_htb': True }
118
        mn = Mininet( topo=SingleSwitchOptionsTopo( n=N, lopts=lopts ),
119
                      host=CPULimitedHost, link=TCLink,
120
                      switch=self.switchClass )
121
        # Drops are probabilistic, but the chance of no dropped packets is
122
        # 1 in 100 million with 4 hops for a link w/99% loss.
123
        dropped_total = 0
124
        mn.start()
125
        for _ in range(REPS):
126
            dropped_total += mn.ping(timeout='1')
127
        mn.stop()
128
        self.assertGreater( dropped_total, 0 )
129

    
130
    def testMostOptions( self ):
131
        "Verify topology creation with most link options and CPU limits."
132
        lopts = { 'bw': 10, 'delay': '5ms', 'use_htb': True }
133
        hopts = { 'cpu': 0.5 / N }
134
        self.runOptionsTopoTest( N, hopts=hopts, lopts=lopts )
135

    
136
# pylint: enable=E1101
137

    
138
class testOptionsTopoOVSKernel( testOptionsTopoCommon, unittest.TestCase ):
139
    """Verify ability to create networks with host and link options
140
       (OVS kernel switch)."""
141
    switchClass = OVSSwitch
142

    
143
@unittest.skip( 'Skipping OVS user switch test for now' )
144
class testOptionsTopoOVSUser( testOptionsTopoCommon, unittest.TestCase ):
145
    """Verify ability to create networks with host and link options
146
       (OVS user switch)."""
147
    switchClass = partial( OVSSwitch, datapath='user' )
148

    
149
@unittest.skipUnless( quietRun( 'which ivs-ctl' ), 'IVS is not installed' )
150
class testOptionsTopoIVS( testOptionsTopoCommon, unittest.TestCase ):
151
    "Verify ability to create networks with host and link options (IVS)."
152
    switchClass = IVSSwitch
153

    
154
@unittest.skipUnless( quietRun( 'which ofprotocol' ),
155
                     'Reference user switch is not installed' )
156
class testOptionsTopoUserspace( testOptionsTopoCommon, unittest.TestCase ):
157
    "Verify ability to create networks with host and link options (UserSwitch)."
158
    switchClass = UserSwitch
159

    
160
if __name__ == '__main__':
161
    setLogLevel( 'warning' )
162
    unittest.main()