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:
parent
f5d934dfd8
commit
29c5a2335c
@ -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):
|
@ -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())
|
@ -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()
|
Loading…
x
Reference in New Issue
Block a user