2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """A script for configuring constraint networks.
8 Sets up a constrained network configuration on a specific port. Traffic on this
9 port will be redirected to another local server port.
11 The configuration includes bandwidth, latency, and packet loss.
17 import traffic_control
19 # Default logging is ERROR. Use --verbose to enable DEBUG logging.
20 _DEFAULT_LOG_LEVEL = logging.ERROR
22 Dispatcher = collections.namedtuple('Dispatcher', ['dispatch', 'requires_ports',
25 # Map of command names to traffic_control functions.
27 # Adds a new constrained network configuration.
28 'add': Dispatcher(traffic_control.CreateConstrainedPort,
29 requires_ports=True, desc='Add a new constrained port.'),
31 # Deletes an existing constrained network configuration.
32 'del': Dispatcher(traffic_control.DeleteConstrainedPort,
33 requires_ports=True, desc='Delete a constrained port.'),
35 # Deletes all constrained network configurations.
36 'teardown': Dispatcher(traffic_control.TearDown,
38 desc='Teardown all constrained ports.')
43 """Define and parse command-line arguments.
46 tuple as (command, configuration):
47 command: one of the possible commands to setup, delete or teardown the
49 configuration: a map of constrained network properties to their values.
51 parser = optparse.OptionParser()
53 indent_first = parser.formatter.indent_increment
54 opt_width = parser.formatter.help_position - indent_first
58 cmd_usage.append('%*s%-*s%s' %
59 (indent_first, '', opt_width, s, COMMANDS[s].desc))
61 parser.usage = ('usage: %%prog {%s} [options]\n\n%s' %
62 ('|'.join(COMMANDS.keys()), '\n'.join(cmd_usage)))
64 parser.add_option('--port', type='int',
65 help='The port to apply traffic control constraints to.')
66 parser.add_option('--server-port', type='int',
67 help='Port to forward traffic on --port to.')
68 parser.add_option('--bandwidth', type='int',
69 help='Bandwidth of the network in kbit/s.')
70 parser.add_option('--latency', type='int',
71 help=('Latency (delay) added to each outgoing packet in '
73 parser.add_option('--loss', type='int',
74 help='Packet-loss percentage on outgoing packets. ')
75 parser.add_option('--interface', type='string',
76 help=('Interface to setup constraints on. Use "lo" for a '
78 parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
79 default=False, help='Turn on verbose output.')
80 options, args = parser.parse_args()
82 _SetLogger(options.verbose)
84 # Check a valid command was entered
85 if not args or args[0].lower() not in COMMANDS:
86 parser.error('Please specify a command {%s}.' % '|'.join(COMMANDS.keys()))
87 user_cmd = args[0].lower()
89 # Check if required options are available
90 if COMMANDS[user_cmd].requires_ports:
91 if not (options.port and options.server_port):
92 parser.error('Please provide port and server-port values.')
96 'server_port': options.server_port,
97 'interface': options.interface,
98 'latency': options.latency,
99 'bandwidth': options.bandwidth,
102 return user_cmd, config
105 def _SetLogger(verbose):
106 log_level = _DEFAULT_LOG_LEVEL
108 log_level = logging.DEBUG
109 logging.basicConfig(level=log_level, format='%(message)s')
113 """Get the command and configuration of the network to set up."""
114 user_cmd, config = _ParseArgs()
117 COMMANDS[user_cmd].dispatch(config)
118 except traffic_control.TrafficControlError as e:
119 logging.error('Error: %s\n\nOutput: %s', e.msg, e.error)
122 if __name__ == '__main__':