Merge pull request #313 from cdburkard/master

ovs port numbering bug fix
This commit is contained in:
Brian O'Connor
2014-06-11 16:17:14 -07:00
4 changed files with 161 additions and 7 deletions
+5
View File
@@ -117,3 +117,8 @@ memory and `sysctl` configuration (see `INSTALL`.)
This example creates a 64-host tree network, and attempts to check full This example creates a 64-host tree network, and attempts to check full
connectivity using `ping`, for different switch/datapath types. connectivity using `ping`, for different switch/datapath types.
#### numberedports.py
This example verifies the mininet ofport numbers match up to the ovs port numbers.
It also verifies that the port numbers match up to the interface numbers
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/python
"""
Create a network with 5 hosts, numbered 1-4 and 9.
Validate that the port numbers match to the interface name,
and that the ovs ports match the mininet ports.
"""
from mininet.net import Mininet
from mininet.node import Controller
from mininet.log import setLogLevel, info, warn
from mininet.node import Node
def validatePort( switch, intf ):
"Validate intf's OF port number"
ofport = int( switch.cmd( 'ovs-vsctl get Interface', intf,
'ofport' ) )
if ofport != switch.ports[ intf ]:
warn( 'WARNING: ofport for', intf, 'is actually', ofport, '\n' )
return 0
else:
return 1
def net():
"Create a network with 5 hosts."
net = Mininet( controller=Controller )
info( '*** Adding controller\n' )
net.addController( 'c0' )
info( '*** Adding hosts\n' )
h1 = net.addHost( 'h1', ip='10.0.0.1' )
h2 = net.addHost( 'h2', ip='10.0.0.2' )
h3 = net.addHost( 'h3', ip='10.0.0.3' )
h4 = net.addHost( 'h4', ip='10.0.0.4' )
h5 = net.addHost( 'h5', ip='10.0.0.5' )
info( '*** Adding switch\n' )
s1 = net.addSwitch( 's1' )
info( '*** Creating links\n' )
# host 1-4 connect to ports 1-4 on the switch
net.addLink( h1, s1 )
net.addLink( h2, s1 )
net.addLink( h3, s1 )
net.addLink( h4, s1 )
net.addLink( h5, s1, port1 = 1, port2 = 9 ) # specify a different port to connect host 5 to on the switch.
root = Node( 'root', inNamespace=False )
info( '*** Starting network\n' )
net.start()
# print the interfaces and their port numbers
info( '\n*** printing and validating the ports running on each interface\n' )
for intfs in s1.intfList():
if not intfs.name == "lo":
info( intfs, ': ', s1.ports[intfs],
'\n' )
info ( 'Validating that', intfs, 'is actually on port', s1.ports[intfs], '... ' )
if validatePort( s1, intfs ):
info( 'Validated.\n' )
print '\n'
# test the network with pingall
net.pingAll()
print '\n'
info( '*** Stopping network' )
net.stop()
if __name__ == '__main__':
setLogLevel( 'info' )
net()
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env python
"""
Test for numberedports.py
"""
import unittest
import pexpect
from collections import defaultdict
from mininet.node import OVSSwitch
class testNumberedports( unittest.TestCase ):
@unittest.skipIf( OVSSwitch.setup() or OVSSwitch.isOldOVS(), "old version of OVS" )
def testConsistency( self ):
"""verify consistency between mininet and ovs ports"""
p = pexpect.spawn( 'python -m mininet.examples.numberedports' )
opts = [ 'Validating that s1-eth\d is actually on port \d ... Validated.',
'Validating that s1-eth\d is actually on port \d ... WARNING',
pexpect.EOF ]
correct_ports = True
count = 0
while True:
index = p.expect( opts )
if index == 0:
count += 1
elif index == 1:
correct_ports = False
elif index == 2:
self.assertNotEqual( 0, count )
break
self.assertTrue( correct_ports )
def testNumbering( self ):
"""verify that all of the port numbers are printed correctly and consistent with their interface"""
p = pexpect.spawn( 'python -m mininet.examples.numberedports' )
opts = [ 's1-eth(\d+) : (\d+)',
pexpect.EOF ]
count_intfs = 0
while True:
index = p.expect( opts )
if index == 0:
count_intfs += 1
intfport = p.match.group( 1 )
ofport = p.match.group( 2 )
self.assertEqual( intfport, ofport )
elif index == 1:
break
self.assertNotEqual( 0, count_intfs )
if __name__ == '__main__':
unittest.main()
+28 -7
View File
@@ -57,6 +57,8 @@ from mininet.util import ( quietRun, errRun, errFail, moveIntf, isShellBuiltin,
numCores, retry, mountCgroups ) numCores, retry, mountCgroups )
from mininet.moduledeps import moduleDeps, pathCheck, OVS_KMOD, OF_KMOD, TUN from mininet.moduledeps import moduleDeps, pathCheck, OVS_KMOD, OF_KMOD, TUN
from mininet.link import Link, Intf, TCIntf from mininet.link import Link, Intf, TCIntf
from re import findall
from distutils.version import StrictVersion
class Node( object ): class Node( object ):
"""A virtual network node is simply a shell in a network namespace. """A virtual network node is simply a shell in a network namespace.
@@ -987,6 +989,13 @@ class OVSSwitch( Switch ):
'You may wish to try ' 'You may wish to try '
'"service openvswitch-switch start".\n' ) '"service openvswitch-switch start".\n' )
exit( 1 ) exit( 1 )
info = quietRun( 'ovs-vsctl --version' )
cls.OVSVersion = findall( '\d+\.\d+', info )[ 0 ]
@classmethod
def isOldOVS( cls ):
return ( StrictVersion( cls.OVSVersion ) <
StrictVersion( '1.10' ) )
@classmethod @classmethod
def batchShutdown( cls, switches ): def batchShutdown( cls, switches ):
@@ -1046,19 +1055,32 @@ class OVSSwitch( Switch ):
self.cmd( 'ovs-vsctl del-br', self ) self.cmd( 'ovs-vsctl del-br', self )
int( self.dpid, 16 ) # DPID must be a hex string int( self.dpid, 16 ) # DPID must be a hex string
# Interfaces and controllers # Interfaces and controllers
intfs = ' '.join( '-- add-port %s %s ' % ( self, intf ) intfs = ' '.join( '-- add-port %s %s ' % ( self, intf ) +
'-- set Interface %s ' % intf +
'ofport_request=%s ' % self.ports[ intf ]
for intf in self.intfList() if not intf.IP() ) for intf in self.intfList() if not intf.IP() )
clist = ' '.join( '%s:%s:%d' % ( c.protocol, c.IP(), c.port ) clist = ' '.join( '%s:%s:%d' % ( c.protocol, c.IP(), c.port )
for c in controllers ) for c in controllers )
if self.listenPort: if self.listenPort:
clist += ' ptcp:%s' % self.listenPort clist += ' ptcp:%s' % self.listenPort
# Construct big ovs-vsctl command # Construct big ovs-vsctl command for new versions of OVS
cmd = ( 'ovs-vsctl add-br %s ' % self + if not self.isOldOVS():
'-- set Bridge %s ' % self + cmd = ( 'ovs-vsctl add-br %s ' % self +
'-- set Bridge %s ' % self +
'other_config:datapath-id=%s ' % self.dpid +
'-- set-fail-mode %s %s ' % ( self, self.failMode ) +
intfs +
'-- set-controller %s %s ' % ( self, clist ) )
# Construct ovs-vsctl commands for old versions of OVS
else:
self.cmd( 'ovs-vsctl add-br', self )
for intf in self.intfList():
if not intf.IP():
self.cmd('ovs-vsctl add-port', self, intf )
cmd = ('ovs-vsctl set Bridge %s ' % self +
'other_config:datapath-id=%s ' % self.dpid + 'other_config:datapath-id=%s ' % self.dpid +
'-- set-fail-mode %s %s ' % ( self, self.failMode ) + '-- set-fail-mode %s %s ' % ( self, self.failMode ) +
intfs + '-- set-controller %s %s ' % ( self, clist ) )
'-- set-controller %s %s ' % (self, clist ) )
if not self.inband: if not self.inband:
cmd += ( '-- set bridge %s ' cmd += ( '-- set bridge %s '
'other-config:disable-in-band=true ' % self ) 'other-config:disable-in-band=true ' % self )
@@ -1282,4 +1304,3 @@ class RemoteController( Controller ):
if 'Connected' not in listening: if 'Connected' not in listening:
warn( "Unable to contact the remote controller" warn( "Unable to contact the remote controller"
" at %s:%d\n" % ( self.ip, self.port ) ) " at %s:%d\n" % ( self.ip, self.port ) )