- Checks the OS and runs the appropriate commands for Dummynet (ipfw)

- Added pipe rule flush handling
- Also fixed a bug preventing any rule settings other than default from being 
  used no matter what preset was chosen
- Fixed some comments.

BUGS=none
TEST= Windows and linux
Review URL: https://webrtc-codereview.appspot.com/1158006

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3639 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
jansson@webrtc.org
2013-03-08 10:50:14 +00:00
parent 971278a962
commit 755e19adfc
2 changed files with 53 additions and 47 deletions

View File

@@ -9,6 +9,7 @@
"""Script for constraining traffic on the local machine."""
import ctypes
import logging
import os
import subprocess
@@ -88,21 +89,26 @@ class NetworkEmulator(object):
NetworkEmulatorError: If permissions to run Dummynet commands are not
available.
"""
if os.geteuid() != 0:
_run_shell_command(
['sudo', '-n', 'ipfw', '-h'],
msg=('Cannot run \'ipfw\' command. This script must be run as '
'root or have password-less sudo access to this command.'))
try:
if os.getuid() != 0:
raise NetworkEmulatorError('You must run this script with sudo.')
except AttributeError:
@staticmethod
def cleanup():
# AttributeError will be raised on Windows.
if ctypes.windll.shell32.IsUserAnAdmin() == 0:
raise NetworkEmulatorError('You must run this script with administrator'
'privileges.')
def cleanup(self):
"""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 emulation.
"""
_run_shell_command(['sudo', 'ipfw', '-f', 'flush'],
'Failed to flush Dummynet rules!')
self._run_ipfw_command(['-f', 'flush'],
'Failed to flush Dummynet rules!')
self._run_ipfw_command(['-f', 'pipe', 'flush'],
'Failed to flush Dummynet pipes!')
def _create_dummynet_rule(self, pipe_id, from_address, to_address,
port_range):
@@ -121,12 +127,12 @@ class NetworkEmulator(object):
each rule being added.
"""
self._rule_counter += 100
add_part = ['sudo', 'ipfw', 'add', self._rule_counter, 'pipe', pipe_id,
add_part = ['add', self._rule_counter, 'pipe', pipe_id,
'ip', 'from', from_address, 'to', to_address]
_run_shell_command(add_part + ['src-port', '%s-%s' % port_range],
'Failed to add Dummynet src-port rule.')
_run_shell_command(add_part + ['dst-port', '%s-%s' % port_range],
'Failed to add Dummynet dst-port rule.')
self._run_ipfw_command(add_part + ['src-port', '%s-%s' % port_range],
'Failed to add Dummynet src-port rule.')
self._run_ipfw_command(add_part + ['dst-port', '%s-%s' % port_range],
'Failed to add Dummynet dst-port rule.')
return self._rule_counter
def _create_dummynet_pipe(self, bandwidth_kbps, delay_ms, packet_loss_percent,
@@ -142,7 +148,7 @@ class NetworkEmulator(object):
The ID of the pipe, starting at 1.
"""
self._pipe_counter += 1
cmd = ['sudo', 'ipfw', 'pipe', self._pipe_counter, 'config',
cmd = ['pipe', self._pipe_counter, 'config',
'bw', str(bandwidth_kbps/8) + 'KByte/s',
'delay', '%sms' % delay_ms,
'plr', (packet_loss_percent/100.0),
@@ -150,10 +156,13 @@ class NetworkEmulator(object):
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)')
_run_shell_command(cmd, error_message)
'your kernel (sudo insmod /path/to/ipfw_mod.ko).')
self._run_ipfw_command(cmd, error_message)
return self._pipe_counter
def _run_ipfw_command(self, command, msg=None):
"""Executes a command and it prefixes the appropriate command for
Windows or Linux/UNIX.
def _run_shell_command(command, msg=None):
"""Executes a command.
@@ -162,20 +171,22 @@ def _run_shell_command(command, msg=None):
command: Command list to execute.
msg: Message describing the error in case the command fails.
Returns:
The standard output from running the command.
Raises:
NetworkEmulatorError: If command fails. Message is set by the msg
Raises:
NetworkEmulatorError: If command fails. Message is set by the msg
parameter.
"""
cmd_list = [str(x) for x in command]
cmd = ' '.join(cmd_list)
logging.debug('Running command: %s', cmd)
"""
if sys.platform == 'win32':
ipfw_command = ['ipfw.exe']
else:
ipfw_command = ['sudo', '-n', 'ipfw']
process = subprocess.Popen(cmd_list, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, error = process.communicate()
if process.returncode != 0:
raise NetworkEmulatorError(msg, cmd, process.returncode, output, error)
return output.strip()
cmd_list = ipfw_command[:] + [str(x) for x in command]
cmd_string = ' '.join(cmd_list)
logging.debug('Running command: %s', cmd_string)
process = subprocess.Popen(cmd_list, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, error = process.communicate()
if process.returncode != 0:
raise NetworkEmulatorError(msg, cmd_string, process.returncode, output,
error)
return output.strip()