Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: tools/network_emulator/emulate.py

Issue 2584433002: Create top-level dir tools-webrtc and start moving things into it. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/network_emulator/config.py ('k') | tools/network_emulator/network_emulator.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 #
4 # Use of this source code is governed by a BSD-style license
5 # that can be found in the LICENSE file in the root of the source
6 # tree. An additional intellectual property rights grant can be found
7 # in the file PATENTS. All contributing project authors may
8 # be found in the AUTHORS file in the root of the source tree.
9
10 """Script for constraining traffic on the local machine."""
11
12
13 import logging
14 import optparse
15 import socket
16 import sys
17
18 import config
19 import network_emulator
20
21
22 _DEFAULT_LOG_LEVEL = logging.INFO
23
24 # Default port range to apply network constraints on.
25 _DEFAULT_PORT_RANGE = (32768, 65535)
26
27 # The numbers below are gathered from Google stats from the presets of the Apple
28 # developer tool called Network Link Conditioner.
29 _PRESETS = [
30 config.ConnectionConfig(1, 'Generic, Bad', 95, 95, 250, 2, 100),
31 config.ConnectionConfig(2, 'Generic, Average', 375, 375, 145, 0.1, 100),
32 config.ConnectionConfig(3, 'Generic, Good', 1000, 1000, 35, 0, 100),
33 config.ConnectionConfig(4, '3G, Average Case', 780, 330, 100, 0, 100),
34 config.ConnectionConfig(5, '3G, Good', 850, 420, 90, 0, 100),
35 config.ConnectionConfig(6, '3G, Lossy Network', 780, 330, 100, 1, 100),
36 config.ConnectionConfig(7, 'Cable Modem', 6000, 1000, 2, 0, 10),
37 config.ConnectionConfig(8, 'DSL', 2000, 256, 5, 0, 10),
38 config.ConnectionConfig(9, 'Edge, Average Case', 240, 200, 400, 0, 100),
39 config.ConnectionConfig(10, 'Edge, Good', 250, 200, 350, 0, 100),
40 config.ConnectionConfig(11, 'Edge, Lossy Network', 240, 200, 400, 1, 100),
41 config.ConnectionConfig(12, 'Wifi, Average Case', 40000, 33000, 1, 0, 100),
42 config.ConnectionConfig(13, 'Wifi, Good', 45000, 40000, 1, 0, 100),
43 config.ConnectionConfig(14, 'Wifi, Lossy', 40000, 33000, 1, 0, 100),
44 ]
45 _PRESETS_DICT = dict((p.num, p) for p in _PRESETS)
46
47 _DEFAULT_PRESET_ID = 2
48 _DEFAULT_PRESET = _PRESETS_DICT[_DEFAULT_PRESET_ID]
49
50
51 class NonStrippingEpilogOptionParser(optparse.OptionParser):
52 """Custom parser to let us show the epilog without weird line breaking."""
53
54 def format_epilog(self, formatter):
55 return self.epilog
56
57
58 def _get_external_ip():
59 """Finds out the machine's external IP by connecting to google.com."""
60 external_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
61 external_socket.connect(('google.com', 80))
62 return external_socket.getsockname()[0]
63
64
65 def _parse_args():
66 """Define and parse the command-line arguments."""
67 presets_string = '\n'.join(str(p) for p in _PRESETS)
68 parser = NonStrippingEpilogOptionParser(epilog=(
69 '\nAvailable presets:\n'
70 ' Bandwidth (kbps) Packet\n'
71 'ID Name Receive Send Queue Delay loss \n'
72 '-- ---- --------- -------- ----- ------- ------\n'
73 '%s\n' % presets_string))
74 parser.add_option('-p', '--preset', type='int', default=_DEFAULT_PRESET_ID,
75 help=('ConnectionConfig configuration, specified by ID. '
76 'Default: %default'))
77 parser.add_option('-r', '--receive-bw', type='int',
78 default=_DEFAULT_PRESET.receive_bw_kbps,
79 help=('Receive bandwidth in kilobit/s. Default: %default'))
80 parser.add_option('-s', '--send-bw', type='int',
81 default=_DEFAULT_PRESET.send_bw_kbps,
82 help=('Send bandwidth in kilobit/s. Default: %default'))
83 parser.add_option('-d', '--delay', type='int',
84 default=_DEFAULT_PRESET.delay_ms,
85 help=('Delay in ms. Default: %default'))
86 parser.add_option('-l', '--packet-loss', type='float',
87 default=_DEFAULT_PRESET.packet_loss_percent,
88 help=('Packet loss in %. Default: %default'))
89 parser.add_option('-q', '--queue', type='int',
90 default=_DEFAULT_PRESET.queue_slots,
91 help=('Queue size as number of slots. Default: %default'))
92 parser.add_option('--port-range', default='%s,%s' % _DEFAULT_PORT_RANGE,
93 help=('Range of ports for constrained network. Specify as '
94 'two comma separated integers. Default: %default'))
95 parser.add_option('--target-ip', default=None,
96 help=('The interface IP address to apply the rules for. '
97 'Default: the external facing interface IP address.'))
98 parser.add_option('-v', '--verbose', action='store_true', default=False,
99 help=('Turn on verbose output. Will print all \'ipfw\' '
100 'commands that are executed.'))
101
102 options = parser.parse_args()[0]
103
104 # Find preset by ID, if specified.
105 if options.preset and not _PRESETS_DICT.has_key(options.preset):
106 parser.error('Invalid preset: %s' % options.preset)
107
108 # Simple validation of the IP address, if supplied.
109 if options.target_ip:
110 try:
111 socket.inet_aton(options.target_ip)
112 except socket.error:
113 parser.error('Invalid IP address specified: %s' % options.target_ip)
114
115 # Convert port range into the desired tuple format.
116 try:
117 if isinstance(options.port_range, str):
118 options.port_range = tuple(int(port) for port in
119 options.port_range.split(','))
120 if len(options.port_range) != 2:
121 parser.error('Invalid port range specified, please specify two '
122 'integers separated by a comma.')
123 except ValueError:
124 parser.error('Invalid port range specified.')
125
126 _set_logger(options.verbose)
127 return options
128
129
130 def _set_logger(verbose):
131 """Setup logging."""
132 log_level = _DEFAULT_LOG_LEVEL
133 if verbose:
134 log_level = logging.DEBUG
135 logging.basicConfig(level=log_level, format='%(message)s')
136
137
138 def _main():
139 options = _parse_args()
140
141 # Build a configuration object. Override any preset configuration settings if
142 # a value of a setting was also given as a flag.
143 connection_config = _PRESETS_DICT[options.preset]
144 if options.receive_bw is not _DEFAULT_PRESET.receive_bw_kbps:
145 connection_config.receive_bw_kbps = options.receive_bw
146 if options.send_bw is not _DEFAULT_PRESET.send_bw_kbps:
147 connection_config.send_bw_kbps = options.send_bw
148 if options.delay is not _DEFAULT_PRESET.delay_ms:
149 connection_config.delay_ms = options.delay
150 if options.packet_loss is not _DEFAULT_PRESET.packet_loss_percent:
151 connection_config.packet_loss_percent = options.packet_loss
152 if options.queue is not _DEFAULT_PRESET.queue_slots:
153 connection_config.queue_slots = options.queue
154 emulator = network_emulator.NetworkEmulator(connection_config,
155 options.port_range)
156 try:
157 emulator.check_permissions()
158 except network_emulator.NetworkEmulatorError as e:
159 logging.error('Error: %s\n\nCause: %s', e.fail_msg, e.error)
160 return -1
161
162 if not options.target_ip:
163 external_ip = _get_external_ip()
164 else:
165 external_ip = options.target_ip
166
167 logging.info('Constraining traffic to/from IP: %s', external_ip)
168 try:
169 emulator.emulate(external_ip)
170 logging.info('Started network emulation with the following configuration:\n'
171 ' Receive bandwidth: %s kbps (%s kB/s)\n'
172 ' Send bandwidth : %s kbps (%s kB/s)\n'
173 ' Delay : %s ms\n'
174 ' Packet loss : %s %%\n'
175 ' Queue slots : %s',
176 connection_config.receive_bw_kbps,
177 connection_config.receive_bw_kbps/8,
178 connection_config.send_bw_kbps,
179 connection_config.send_bw_kbps/8,
180 connection_config.delay_ms,
181 connection_config.packet_loss_percent,
182 connection_config.queue_slots)
183 logging.info('Affected traffic: IP traffic on ports %s-%s',
184 options.port_range[0], options.port_range[1])
185 raw_input('Press Enter to abort Network Emulation...')
186 logging.info('Flushing all Dummynet rules...')
187 network_emulator.cleanup()
188 logging.info('Completed Network Emulation.')
189 return 0
190 except network_emulator.NetworkEmulatorError as e:
191 logging.error('Error: %s\n\nCause: %s', e.fail_msg, e.error)
192 return -2
193
194 if __name__ == '__main__':
195 sys.exit(_main())
OLDNEW
« no previous file with comments | « tools/network_emulator/config.py ('k') | tools/network_emulator/network_emulator.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698