#!/usr/bin/env python """Package: mininet Test creation and pings for topologies with link and/or CPU options.""" import unittest from mininet.net import Mininet from mininet.node import OVSKernelSwitch from mininet.node import CPULimitedHost from mininet.link import TCLink from mininet.topo import Topo from mininet.log import setLogLevel SWITCH = OVSKernelSwitch # Number of hosts for each test N = 2 class SingleSwitchOptionsTopo(Topo): "Single switch connected to n hosts." def __init__(self, n=2, hopts=None, lopts=None): if not hopts: hopts = {} if not lopts: lopts = {} Topo.__init__(self, hopts=hopts, lopts=lopts) switch = self.addSwitch('s1') for h in range(n): host = self.addHost('h%s' % (h + 1)) self.addLink(host, switch) class testOptionsTopo( unittest.TestCase ): "Verify ability to create networks with host and link options." def runOptionsTopoTest( self, n, hopts=None, lopts=None ): "Generic topology-with-options test runner." mn = Mininet( topo=SingleSwitchOptionsTopo( n=n, hopts=hopts, lopts=lopts ), host=CPULimitedHost, link=TCLink ) dropped = mn.run( mn.ping ) self.assertEqual( dropped, 0 ) def assertWithinTolerance(self, measured, expected, tolerance_frac): """Check that a given value is within a tolerance of expected tolerance_frac: less-than-1.0 value; 0.8 would yield 20% tolerance. """ self.assertTrue( float(measured) >= float(expected) * tolerance_frac ) self.assertTrue( float(measured) >= float(expected) * tolerance_frac ) def testCPULimits( self ): "Verify topology creation with CPU limits set for both schedulers." CPU_FRACTION = 0.1 CPU_TOLERANCE = 0.8 # CPU fraction below which test should fail hopts = { 'cpu': CPU_FRACTION } #self.runOptionsTopoTest( N, hopts=hopts ) mn = Mininet( SingleSwitchOptionsTopo( n=N, hopts=hopts ), host=CPULimitedHost ) mn.start() results = mn.runCpuLimitTest( cpu=CPU_FRACTION ) mn.stop() for cpu in results: self.assertWithinTolerance( cpu, CPU_FRACTION, CPU_TOLERANCE ) def testLinkBandwidth( self ): "Verify that link bandwidths are accurate within a bound." BW = 5 # Mbps BW_TOLERANCE = 0.8 # BW fraction below which test should fail # Verify ability to create limited-link topo first; lopts = { 'bw': BW, 'use_htb': True } # Also verify correctness of limit limitng within a bound. mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ), link=TCLink ) bw_strs = mn.run( mn.iperf ) for bw_str in bw_strs: bw = float( bw_str.split(' ')[0] ) self.assertWithinTolerance( bw, BW, BW_TOLERANCE ) def testLinkDelay( self ): "Verify that link delays are accurate within a bound." DELAY_MS = 15 DELAY_TOLERANCE = 0.8 # Delay fraction below which test should fail lopts = { 'delay': '%sms' % DELAY_MS, 'use_htb': True } mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ), link=TCLink ) ping_delays = mn.run( mn.pingFull ) test_outputs = ping_delays[0] # Ignore unused variables below # pylint: disable-msg=W0612 node, dest, ping_outputs = test_outputs sent, received, rttmin, rttavg, rttmax, rttdev = ping_outputs self.assertEqual( sent, received ) # pylint: enable-msg=W0612 for rttval in [rttmin, rttavg, rttmax]: # Multiply delay by 4 to cover there & back on two links self.assertWithinTolerance( rttval, DELAY_MS * 4.0, DELAY_TOLERANCE) def testLinkLoss( self ): "Verify that we see packet drops with a high configured loss rate." LOSS_PERCENT = 99 REPS = 1 lopts = { 'loss': LOSS_PERCENT, 'use_htb': True } mn = Mininet( topo=SingleSwitchOptionsTopo( n=N, lopts=lopts ), host=CPULimitedHost, link=TCLink ) # Drops are probabilistic, but the chance of no dropped packets is # 1 in 100 million with 4 hops for a link w/99% loss. dropped_total = 0 mn.start() for _ in range(REPS): dropped_total += mn.ping(timeout='1') mn.stop() self.assertTrue(dropped_total > 0) def testMostOptions( self ): "Verify topology creation with most link options and CPU limits." lopts = { 'bw': 10, 'delay': '5ms', 'use_htb': True } hopts = { 'cpu': 0.5 / N } self.runOptionsTopoTest( N, hopts=hopts, lopts=lopts ) if __name__ == '__main__': setLogLevel( 'warning' ) unittest.main()