diff --git a/bin/mn b/bin/mn index aef64fe..d5cc0f1 100755 --- a/bin/mn +++ b/bin/mn @@ -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: diff --git a/mininet/link.py b/mininet/link.py index 81b12e4..eff9c97 100644 --- a/mininet/link.py +++ b/mininet/link.py @@ -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 )