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__':