Renamed to Network Emulator and improved error handling.

Changed default start port of the port-range to 32768.

BUG=None
TEST=Tested locally.

Review URL: https://webrtc-codereview.appspot.com/627004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2338 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
kjellander@webrtc.org 2012-06-01 08:42:17 +00:00
parent f5d934dfd8
commit 29c5a2335c
3 changed files with 54 additions and 45 deletions

View File

@ -7,7 +7,7 @@
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
"""Configuration class for network simulation."""
"""Configuration class for network emulation."""
class ConnectionConfig(object):

View File

@ -16,12 +16,12 @@ import socket
import sys
import config
import network_simulator
import network_emulator
_DEFAULT_LOG_LEVEL = logging.INFO
# Default port range to apply network constraints on.
_DEFAULT_PORT_RANGE = (30000, 65535)
_DEFAULT_PORT_RANGE = (32768, 65535)
_PRESETS = [
config.ConnectionConfig(1, 'Generic, Bad', 95, 95, 250, 2, 100),
@ -133,7 +133,7 @@ def _set_logger(verbose):
def _main():
"""Checks arguments, permissions and runs a network simulation."""
"""Checks arguments, permissions and runs a network emulation."""
if os.name != 'posix':
print >> sys.stderr, 'This script is only supported on Linux and Mac.'
return 1
@ -154,11 +154,11 @@ def _main():
if options.queue:
connection_config.queue_slots = options.queue
simulator = network_simulator.NetworkSimulator(connection_config,
options.port_range)
emulator = network_emulator.NetworkEmulator(connection_config,
options.port_range)
try:
simulator.check_permissions()
except network_simulator.NetworkSimulatorError as e:
emulator.check_permissions()
except network_emulator.NetworkEmulatorError as e:
logging.error('Error: %s\n\nCause: %s', e.msg, e.error)
return -1
@ -167,28 +167,32 @@ def _main():
else:
external_ip = options.target_ip
logging.info('Simulating traffic to/from IP: %s', external_ip)
simulator.simulate(external_ip)
logging.info('Started network simulation with the following configuration:\n'
' Receive bandwidth: %s kbps (%s kB/s)\n'
' Send bandwidth : %s kbps (%s kB/s)\n'
' Delay : %s ms\n'
' Packet loss : %s %%\n'
' Queue slots : %s',
connection_config.receive_bw_kbps,
connection_config.receive_bw_kbps/8,
connection_config.send_bw_kbps,
connection_config.send_bw_kbps/8,
connection_config.delay_ms,
connection_config.packet_loss_percent,
connection_config.queue_slots)
logging.info('Affected traffic: IP traffic on ports %s-%s',
options.port_range[0], options.port_range[1])
raw_input('Press Enter to abort Network simulation...')
logging.info('Flushing all Dummynet rules...')
simulator.cleanup()
logging.info('Completed Network Simulation.')
return 0
logging.info('Constraining traffic to/from IP: %s', external_ip)
try:
emulator.emulate(external_ip)
logging.info('Started network emulation with the following configuration:\n'
' Receive bandwidth: %s kbps (%s kB/s)\n'
' Send bandwidth : %s kbps (%s kB/s)\n'
' Delay : %s ms\n'
' Packet loss : %s %%\n'
' Queue slots : %s',
connection_config.receive_bw_kbps,
connection_config.receive_bw_kbps/8,
connection_config.send_bw_kbps,
connection_config.send_bw_kbps/8,
connection_config.delay_ms,
connection_config.packet_loss_percent,
connection_config.queue_slots)
logging.info('Affected traffic: IP traffic on ports %s-%s',
options.port_range[0], options.port_range[1])
raw_input('Press Enter to abort Network Emulation...')
logging.info('Flushing all Dummynet rules...')
emulator.cleanup()
logging.info('Completed Network Emulation.')
return 0
except network_emulator.NetworkEmulatorError as e:
logging.error('Error: %s\n\nCause: %s', e.msg, e.error)
return -2
if __name__ == '__main__':
sys.exit(_main())

View File

@ -12,10 +12,11 @@
import logging
import os
import subprocess
import sys
class NetworkSimulatorError(BaseException):
"""Exception raised for errors in the network simulator.
class NetworkEmulatorError(BaseException):
"""Exception raised for errors in the network emulator.
Attributes:
msg: User defined error message.
@ -35,15 +36,15 @@ class NetworkSimulatorError(BaseException):
self.error = error
class NetworkSimulator(object):
"""A network simulator that can constrain the network using Dummynet."""
class NetworkEmulator(object):
"""A network emulator that can constrain the network using Dummynet."""
def __init__(self, connection_config, port_range):
"""Constructor.
Args:
connection_config: A config.ConnectionConfig object containing the
characteristics for the connection to be simulated.
characteristics for the connection to be emulation.
port_range: Tuple containing two integers defining the port range.
"""
self._pipe_counter = 0
@ -51,8 +52,8 @@ class NetworkSimulator(object):
self._port_range = port_range
self._connection_config = connection_config
def simulate(self, target_ip):
"""Starts a network simulation by setting up Dummynet rules.
def emulate(self, target_ip):
"""Starts a network emulation by setting up Dummynet rules.
Args:
target_ip: The IP address of the interface that shall be that have the
@ -71,7 +72,7 @@ class NetworkSimulator(object):
self._connection_config.queue_slots)
logging.debug('Created send pipe: %s', send_pipe_id)
# Adding the rules will start the simulation.
# Adding the rules will start the emulation.
incoming_rule_id = self._create_dummynet_rule(receive_pipe_id, 'any',
target_ip, self._port_range)
logging.debug('Created incoming rule: %s', incoming_rule_id)
@ -83,7 +84,7 @@ class NetworkSimulator(object):
"""Checks if permissions are available to run Dummynet commands.
Raises:
NetworkSimulatorError: If permissions to run Dummynet commands are not
NetworkEmulatorError: If permissions to run Dummynet commands are not
available.
"""
if os.geteuid() != 0:
@ -93,17 +94,17 @@ class NetworkSimulator(object):
'root or have password-less sudo access to this command.'))
def cleanup(self):
"""Stops the network simulation by flushing all Dummynet rules.
"""Stops the network emulation by flushing all Dummynet rules.
Notice that this will flush any rules that may have been created previously
before starting the simulation.
before starting the emulation.
"""
self._run_shell_command(['sudo', 'ipfw', '-f', 'flush'],
'Failed to flush Dummynet rules!')
def _create_dummynet_rule(self, pipe_id, from_address, to_address,
port_range):
"""Creates a network simulation rule and returns its ID.
"""Creates a network emulation rule and returns its ID.
Args:
pipe_id: integer ID of the pipe.
@ -144,7 +145,11 @@ class NetworkSimulator(object):
'delay', '%sms' % delay_ms,
'plr', (packet_loss_percent/100.0),
'queue', queue_slots]
self._run_shell_command(cmd, 'Failed to create Dummynet pipe')
error_message = 'Failed to create Dummynet pipe. '
if sys.platform.startswith('linux'):
error_message += ('Make sure you have loaded the ipfw_mod.ko module to '
'your kernel (sudo insmod /path/to/ipfw_mod.ko)')
self._run_shell_command(cmd, error_message)
return self._pipe_counter
def _run_shell_command(self, command, msg=None):
@ -158,7 +163,7 @@ class NetworkSimulator(object):
The standard output from running the command.
Raises:
NetworkSimulatorError: If command fails. Message is set by the msg
NetworkEmulatorError: If command fails. Message is set by the msg
parameter.
"""
cmd_list = [str(x) for x in command]
@ -169,5 +174,5 @@ class NetworkSimulator(object):
stderr=subprocess.PIPE)
output, error = process.communicate()
if process.returncode != 0:
raise NetworkSimulatorError(msg, cmd, process.returncode, output, error)
raise NetworkEmulatorError(msg, cmd, process.returncode, output, error)
return output.strip()