Merge pull request #313 from cdburkard/master
ovs port numbering bug fix
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Executable
+76
@@ -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()
|
||||||
|
|
||||||
Executable
+52
@@ -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
@@ -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 ) )
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user