Add TCULink and make it the default for --switch user
For some time, UserSwitch has suffered from abysmal performance due to rx and tx offload settings. In the latest Ubuntu 16.04/Linux 4.4 kernel, it simply doesn't work with the default settings, since packets with bad TCP checksums are generated at one end, passed through the user switch, and dropped at the other. It doesn't seem to be something we can fix in UserSwitch itself although it may be possible to do something in the C code of the Stanford reference switch and CPqD switch.
This commit is contained in:
@@ -30,7 +30,7 @@ from mininet.node import ( Host, CPULimitedHost, Controller, OVSController,
|
||||
UserSwitch, OVSSwitch, OVSBridge,
|
||||
IVSSwitch )
|
||||
from mininet.nodelib import LinuxBridge
|
||||
from mininet.link import Link, TCLink, OVSLink
|
||||
from mininet.link import Link, TCLink, TCULink, OVSLink
|
||||
from mininet.topo import ( SingleSwitchTopo, LinearTopo,
|
||||
SingleSwitchReversedTopo, MinimalTopo )
|
||||
from mininet.topolib import TreeTopo, TorusTopo
|
||||
@@ -73,18 +73,18 @@ HOSTS = { 'proc': Host,
|
||||
'cfs': specialClass( CPULimitedHost, defaults=dict( sched='cfs' ) ) }
|
||||
|
||||
CONTROLLERDEF = 'default'
|
||||
|
||||
CONTROLLERS = { 'ref': Controller,
|
||||
'ovsc': OVSController,
|
||||
'nox': NOX,
|
||||
'remote': RemoteController,
|
||||
'ryu': Ryu,
|
||||
'default': DefaultController, # Note: replaced below
|
||||
'default': DefaultController, # Note: overridden below
|
||||
'none': NullController }
|
||||
|
||||
LINKDEF = 'default'
|
||||
LINKS = { 'default': Link,
|
||||
LINKS = { 'default': Link, # Note: overridden below
|
||||
'tc': TCLink,
|
||||
'tcu': TCULink,
|
||||
'ovs': OVSLink }
|
||||
|
||||
# TESTS dict can contain functions and/or Mininet() method names
|
||||
@@ -341,11 +341,19 @@ class MininetRunner( object ):
|
||||
"for switch %s" %
|
||||
opts.switch )
|
||||
|
||||
|
||||
|
||||
topo = buildTopo( TOPOS, opts.topo )
|
||||
switch = customClass( SWITCHES, opts.switch )
|
||||
host = customClass( HOSTS, opts.host )
|
||||
controller = [ customClass( CONTROLLERS, c )
|
||||
for c in opts.controller ]
|
||||
|
||||
if opts.switch == 'user' and opts.link == 'default':
|
||||
debug( '*** Using TCULink with UserSwitch\n' )
|
||||
# Use link configured correctly for UserSwitch
|
||||
opts.link = 'tcu'
|
||||
|
||||
link = customClass( LINKS, opts.link )
|
||||
|
||||
if self.validate:
|
||||
|
||||
+45
-6
@@ -313,16 +313,40 @@ class TCIntf( Intf ):
|
||||
return self.cmd( c )
|
||||
|
||||
def config( self, bw=None, delay=None, jitter=None, loss=None,
|
||||
disable_gro=True, speedup=0, use_hfsc=False, use_tbf=False,
|
||||
gro=False, txo=True, rxo=True,
|
||||
speedup=0, use_hfsc=False, use_tbf=False,
|
||||
latency_ms=None, enable_ecn=False, enable_red=False,
|
||||
max_queue_size=None, **params ):
|
||||
"Configure the port and set its properties."
|
||||
"""Configure the port and set its properties.
|
||||
bw: bandwidth in b/s (e.g. '10m')
|
||||
delay: transmit delay (e.g. '1ms' )
|
||||
jitter: jitter (e.g. '1ms')
|
||||
loss: loss (e.g. '1%' )
|
||||
gro: enable GRO (False)
|
||||
txo: enable transmit checksum offload (True)
|
||||
rxo: enable receive checksum offload (True)
|
||||
speedup: experimental switch-side bw option
|
||||
use_hfsc: use HFSC scheduling
|
||||
use_tbf: use TBF scheduling
|
||||
latency_ms: TBF latency parameter
|
||||
enable_ecn: enable ECN (False)
|
||||
enable_red: enable RED (False)
|
||||
max_queue_size: queue limit parameter for netem"""
|
||||
|
||||
# Support old names for parameters
|
||||
gro = not params.pop( 'disable_gro', not gro )
|
||||
|
||||
result = Intf.config( self, **params)
|
||||
|
||||
# Disable GRO
|
||||
if disable_gro:
|
||||
self.cmd( 'ethtool -K %s gro off' % self )
|
||||
def on( isOn ):
|
||||
"Helper method: bool -> 'on'/'off'"
|
||||
return 'on' if isOn else 'off'
|
||||
|
||||
# Set offload parameters with ethool
|
||||
self.cmd( 'ethtool -K', self,
|
||||
'gro', on( gro ),
|
||||
'tx', on( txo ),
|
||||
'rx', on( rxo ) )
|
||||
|
||||
# Optimization: return if nothing else to configure
|
||||
# Question: what happens if we want to reset things?
|
||||
@@ -476,7 +500,7 @@ class Link( object ):
|
||||
self.intf1 = None
|
||||
self.intf2.delete()
|
||||
self.intf2 = None
|
||||
|
||||
|
||||
def stop( self ):
|
||||
"Override to stop and clean up link as needed"
|
||||
self.delete()
|
||||
@@ -535,3 +559,18 @@ class TCLink( Link ):
|
||||
addr1=addr1, addr2=addr2,
|
||||
params1=params,
|
||||
params2=params )
|
||||
|
||||
|
||||
class TCULink( TCLink ):
|
||||
"""TCLink with default settings optimized for UserSwitch
|
||||
(txo=rxo=0/False). Unfortunately with recent Linux kernels,
|
||||
enabling TX and RX checksum offload on veth pairs doesn't work
|
||||
well with UserSwitch: either it gets terrible performance or
|
||||
TCP packets with bad checksums are generated, forwarded, and
|
||||
*dropped* due to having bad checksums! OVS and LinuxBridge seem
|
||||
to cope with this somehow, but it is likely to be an issue with
|
||||
many software Ethernet bridges."""
|
||||
|
||||
def __init__( self, *args, **kwargs ):
|
||||
kwargs.update( txo=False, rxo=False )
|
||||
TCLink.__init__( self, *args, **kwargs )
|
||||
|
||||
Reference in New Issue
Block a user