Permalink
Browse files

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.
  • Loading branch information...
1 parent 0f9c1b3 commit 8def6752f353f93eb1a4f11e203771cebb0e7c23 @lantz lantz committed Sep 19, 2016
Showing with 57 additions and 10 deletions.
  1. +12 −4 bin/mn
  2. +45 −6 mininet/link.py
View
@@ -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:
View
@@ -313,16 +313,40 @@ def tc( self, cmd, tc='tc' ):
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 @@ def delete( self ):
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 @@ def __init__( self, node1, node2, port1=None, port2=None,
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 )

0 comments on commit 8def675

Please sign in to comment.