Compare commits

...

11 Commits

Author SHA1 Message Date
Bob Lantz e0436642ae 2.3.0d6 2019-07-11 17:16:46 -07:00
lantz c5f626ce27 Merge pull request #891 from benfrankel/master
Use incremental utf-8 decoder for buffered reading
2019-07-11 17:15:37 -07:00
Ben Frankel 10e758e80a Use incremental UTF-8 decoder for buffered reading 2019-07-11 16:57:09 -07:00
lantz de28f67a97 Merge pull request #882 from stephanreiter/master
Don't pass 'loss 0' to tc as it will cause an error on newer versions
2019-06-09 15:52:33 -07:00
Stephan Reiter 46242acdd4 Don't pass 'loss 0' to tc as it will cause an error on newer versions
Observed on Ubuntu 18.04.
2019-06-09 00:24:21 +02:00
lantz e203808a20 Merge pull request #872 from dsaucez/patch-2
change isShellBuiltin
2019-04-25 20:16:31 -07:00
Damien Saucez 7c0d1506e7 change isShellBuiltin
change isShellBuiltin to have each builtin as a different token in a set and lookup cmd to be an element of the set instead of a sequence of characters in a string (tested only on Python 3.6.7). Corrected according to @lantz comments.
2019-04-23 08:42:07 +02:00
lantz c5f23b9f82 Merge pull request #815 from teto/fix_controller
fix "which" calls always returning true
2019-04-16 13:28:47 -07:00
Bob Lantz cfb0a6d3f0 Silence warning for failing to stop ovs-testcontroller 2019-04-09 12:17:35 -07:00
Bob Lantz 664ba39383 NAT warning if IPv4 loopback address in /etc/resolv.conf 2019-04-04 16:40:04 -07:00
Matthieu Coudron a73e776695 fix "which" calls always returning true
The redirection of stderr towards stdout means calls to "which program"
always return something even when "program" is not installed.

This patch checks for the return value instead before returning the
value.

See #814.
2018-09-25 22:29:30 +09:00
9 changed files with 88 additions and 45 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
Mininet Installation/Configuration Notes
----------------------------------------
Mininet 2.3.0d5
Mininet 2.3.0d6
---
The supported installation methods for Mininet are 1) using a
+1 -1
View File
@@ -1,4 +1,4 @@
Mininet 2.3.0d5 License
Mininet 2.3.0d6 License
Copyright (c) 2013-2019 Open Networking Laboratory
Copyright (c) 2009-2012 Bob Lantz and The Board of Trustees of
+1 -1
View File
@@ -2,7 +2,7 @@ Mininet: Rapid Prototyping for Software Defined Networks
========================================================
*The best way to emulate almost any network on your laptop!*
Mininet 2.3.0d5
Mininet 2.3.0d6
[![Build Status][1]](https://travis-ci.org/mininet/mininet)
+4
View File
@@ -388,6 +388,10 @@ class MininetRunner( object ):
listenPort=opts.listenport )
if opts.ensure_value( 'nat', False ):
with open( '/etc/resolv.conf' ) as f:
if 'nameserver 127.' in f.read():
warn( '*** Warning: loopback address in /etc/resolv.conf '
'may break host DNS over NAT\n')
mn.addNAT( *opts.nat_args, **opts.nat_kwargs ).configDefault()
# --custom files can set CLI or change mininet.cli.CLI
+1 -1
View File
@@ -295,7 +295,7 @@ class TCIntf( Intf ):
netemargs = '%s%s%s%s' % (
'delay %s ' % delay if delay is not None else '',
'%s ' % jitter if jitter is not None else '',
'loss %.5f ' % loss if loss is not None else '',
'loss %.5f ' % loss if (loss is not None and loss > 0) else '',
'limit %d' % max_queue_size if max_queue_size is not None
else '' )
if netemargs:
+1 -1
View File
@@ -108,7 +108,7 @@ from mininet.util import ( quietRun, fixLimits, numCores, ensureRoot,
from mininet.term import cleanUpScreens, makeTerms
# Mininet version: should be consistent with README and LICENSE
VERSION = "2.3.0d5"
VERSION = "2.3.0d6"
class Mininet( object ):
"Network emulation with hosts spawned in network namespaces."
+16 -13
View File
@@ -63,7 +63,7 @@ from time import sleep
from mininet.log import info, error, warn, debug
from mininet.util import ( quietRun, errRun, errFail, moveIntf, isShellBuiltin,
numCores, retry, mountCgroups, BaseString, decode,
encode, Python3 )
encode, getincrementaldecoder, Python3, which )
from mininet.moduledeps import moduleDeps, pathCheck, TUN
from mininet.link import Link, Intf, TCIntf, OVSIntf
from re import findall
@@ -106,6 +106,9 @@ class Node( object ):
self.waiting = False
self.readbuf = ''
# Incremental decoder for buffered reading
self.decoder = getincrementaldecoder()
# Start command interpreter shell
self.master, self.slave = None, None # pylint
self.startShell()
@@ -229,19 +232,19 @@ class Node( object ):
# Subshell I/O, commands and control
def read( self, maxbytes=1024 ):
def read( self, size=1024 ):
"""Buffered read from node, potentially blocking.
maxbytes: maximum number of bytes to return"""
size: maximum number of characters to return"""
count = len( self.readbuf )
if count < maxbytes:
data = decode( os.read( self.stdout.fileno(), maxbytes - count ) )
self.readbuf += data
if maxbytes >= len( self.readbuf ):
if count < size:
data = os.read( self.stdout.fileno(), size - count )
self.readbuf += self.decoder.decode( data )
if size >= len( self.readbuf ):
result = self.readbuf
self.readbuf = ''
else:
result = self.readbuf[ :maxbytes ]
self.readbuf = self.readbuf[ maxbytes: ]
result = self.readbuf[ :size ]
self.readbuf = self.readbuf[ size: ]
return result
def readline( self ):
@@ -1447,7 +1450,7 @@ class Controller( Node ):
@classmethod
def isAvailable( cls ):
"Is controller available?"
return quietRun( 'which controller' )
return which( 'controller' )
class OVSController( Controller ):
@@ -1459,9 +1462,9 @@ class OVSController( Controller ):
@classmethod
def isAvailable( cls ):
return ( quietRun( 'which ovs-controller' ) or
quietRun( 'which test-controller' ) or
quietRun( 'which ovs-testcontroller' ) ).strip()
return (which( 'ovs-controller' ) or
which( 'test-controller' ) or
which( 'ovs-testcontroller' ))
class NOX( Controller ):
"Controller to run a NOX application."
+62 -26
View File
@@ -13,23 +13,48 @@ from os import O_NONBLOCK
import os
from functools import partial
import sys
import codecs
# Python 2/3 compatibility
Python3 = sys.version_info[0] == 3
BaseString = str if Python3 else getattr( str, '__base__' )
Encoding = 'utf-8' if Python3 else None
def decode( s ):
"Decode a byte string if needed for Python 3"
return s.decode( Encoding ) if Python3 else s
def encode( s ):
"Encode a byte string if needed for Python 3"
return s.encode( Encoding ) if Python3 else s
class NullCodec( object ):
"Null codec for Python 2"
@staticmethod
def decode( buf ):
"Null decode"
return buf
@staticmethod
def encode( buf ):
"Null encode"
return buf
if Python3:
def decode( buf ):
"Decode buffer for Python 3"
return buf.decode( Encoding )
def encode( buf ):
"Encode buffer for Python 3"
return buf.encode( Encoding )
getincrementaldecoder = codecs.getincrementaldecoder( Encoding )
else:
decode, encode = NullCodec.decode, NullCodec.encode
def getincrementaldecoder():
"Return null codec for Python 2"
return NullCodec
try:
# pylint: disable=import-error
oldpexpect = None
import pexpect as oldpexpect
# pylint: enable=import-error
# pylint: enable=import-error
class Pexpect( object ):
"Custom pexpect that is compatible with str"
@staticmethod
@@ -119,20 +144,21 @@ def errRun( *cmd, **kwargs ):
out, err = '', ''
poller = poll()
poller.register( popen.stdout, POLLIN )
fdtofile = { popen.stdout.fileno(): popen.stdout }
fdToFile = { popen.stdout.fileno(): popen.stdout }
fdToDecoder = { popen.stdout.fileno(): getincrementaldecoder() }
outDone, errDone = False, True
if popen.stderr:
fdtofile[ popen.stderr.fileno() ] = popen.stderr
fdToFile[ popen.stderr.fileno() ] = popen.stderr
fdToDecoder[ popen.stderr.fileno() ] = getincrementaldecoder()
poller.register( popen.stderr, POLLIN )
errDone = False
while not outDone or not errDone:
readable = poller.poll()
for fd, event in readable:
f = fdtofile[ fd ]
f = fdToFile[ fd ]
decoder = fdToDecoder[ fd ]
if event & POLLIN:
data = f.read( 1024 )
if Python3:
data = data.decode( Encoding )
data = decoder.decode( f.read( 1024 ) )
if echo:
output( data )
if f == popen.stdout:
@@ -171,19 +197,26 @@ def quietRun( cmd, **kwargs ):
"Run a command and return merged stdout and stderr"
return errRun( cmd, stderr=STDOUT, **kwargs )[ 0 ]
def which(cmd, **kwargs ):
"Run a command and return merged stdout and stderr"
out, _, ret = errRun( ["which", cmd], stderr=STDOUT, **kwargs )
return out.rstrip() if ret == 0 else None
# pylint: enable=maybe-no-member
def isShellBuiltin( cmd ):
"Return True if cmd is a bash builtin."
if isShellBuiltin.builtIns is None:
isShellBuiltin.builtIns = quietRun( 'bash -c enable' )
isShellBuiltin.builtIns = set(quietRun( 'bash -c enable' ).split())
space = cmd.find( ' ' )
if space > 0:
cmd = cmd[ :space]
return cmd in isShellBuiltin.builtIns
isShellBuiltin.builtIns = None
# Interface management
#
# Interfaces are managed as strings which are simply the
@@ -370,7 +403,7 @@ def netParse( ipstr ):
if '/' in ipstr:
ip, pf = ipstr.split( '/' )
prefixLen = int( pf )
#if no prefix is specified, set the prefix to 24
# if no prefix is specified, set the prefix to 24
else:
ip = ipstr
prefixLen = 24
@@ -413,9 +446,11 @@ def pmonitor(popens, timeoutms=500, readline=True,
terminates: when all EOFs received"""
poller = poll()
fdToHost = {}
fdToDecoder = {}
for host, popen in popens.items():
fd = popen.stdout.fileno()
fdToHost[ fd ] = host
fdToDecoder[ fd ] = getincrementaldecoder()
poller.register( fd, POLLIN | POLLHUP )
flags = fcntl( fd, F_GETFL )
fcntl( fd, F_SETFL, flags | O_NONBLOCK )
@@ -424,13 +459,14 @@ def pmonitor(popens, timeoutms=500, readline=True,
if fds:
for fd, event in fds:
host = fdToHost[ fd ]
decoder = fdToDecoder[ fd ]
popen = popens[ host ]
if event & POLLIN or event & POLLHUP:
while True:
try:
f = popen.stdout
line = decode( f.readline() if readline
else f.read( readmax ) )
line = decoder.decode( f.readline() if readline
else f.read( readmax ) )
except IOError:
line = ''
if line == '':
@@ -445,19 +481,19 @@ def pmonitor(popens, timeoutms=500, readline=True,
# Other stuff we use
def sysctlTestAndSet( name, limit ):
"Helper function to set sysctl limits"
#convert non-directory names into directory names
# convert non-directory names into directory names
if '/' not in name:
name = '/proc/sys/' + name.replace( '.', '/' )
#read limit
# read limit
with open( name, 'r' ) as readFile:
oldLimit = readFile.readline()
if isinstance( limit, int ):
#compare integer limits before overriding
# compare integer limits before overriding
if int( oldLimit ) < limit:
with open( name, 'w' ) as writeFile:
writeFile.write( "%d" % limit )
else:
#overwrite non-integer limits
# overwrite non-integer limits
with open( name, 'w' ) as writeFile:
writeFile.write( limit )
@@ -474,21 +510,21 @@ def fixLimits():
try:
rlimitTestAndSet( RLIMIT_NPROC, 8192 )
rlimitTestAndSet( RLIMIT_NOFILE, 16384 )
#Increase open file limit
# Increase open file limit
sysctlTestAndSet( 'fs.file-max', 10000 )
#Increase network buffer space
# Increase network buffer space
sysctlTestAndSet( 'net.core.wmem_max', 16777216 )
sysctlTestAndSet( 'net.core.rmem_max', 16777216 )
sysctlTestAndSet( 'net.ipv4.tcp_rmem', '10240 87380 16777216' )
sysctlTestAndSet( 'net.ipv4.tcp_wmem', '10240 87380 16777216' )
sysctlTestAndSet( 'net.core.netdev_max_backlog', 5000 )
#Increase arp cache size
# Increase arp cache size
sysctlTestAndSet( 'net.ipv4.neigh.default.gc_thresh1', 4096 )
sysctlTestAndSet( 'net.ipv4.neigh.default.gc_thresh2', 8192 )
sysctlTestAndSet( 'net.ipv4.neigh.default.gc_thresh3', 16384 )
#Increase routing table size
# Increase routing table size
sysctlTestAndSet( 'net.ipv4.route.max_size', 32768 )
#Increase number of PTYs for nodes
# Increase number of PTYs for nodes
sysctlTestAndSet( 'kernel.pty.max', 20000 )
# pylint: disable=broad-except
except Exception:
+1 -1
View File
@@ -409,7 +409,7 @@ function ovs {
# Switch can run on its own, but
# Mininet should control the controller
# This appears to only be an issue on Ubuntu/Debian
if sudo service $OVSC stop; then
if sudo service $OVSC stop 2>/dev/null; then
echo "Stopped running controller"
fi
if [ -e /etc/init.d/$OVSC ]; then