Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2010 Google Inc. All Rights Reserved. | 2 # Copyright 2010 Google Inc. All Rights Reserved. |
| 3 # | 3 # |
| 4 # Licensed under the Apache License, Version 2.0 (the "License"); | 4 # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 # you may not use this file except in compliance with the License. | 5 # you may not use this file except in compliance with the License. |
| 6 # You may obtain a copy of the License at | 6 # You may obtain a copy of the License at |
| 7 # | 7 # |
| 8 # http://www.apache.org/licenses/LICENSE-2.0 | 8 # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 # | 9 # |
| 10 # Unless required by applicable law or agreed to in writing, software | 10 # Unless required by applicable law or agreed to in writing, software |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 _DOWNLOAD_PIPE = '11' # Enforces overall download bandwidth. | 46 _DOWNLOAD_PIPE = '11' # Enforces overall download bandwidth. |
| 47 _DOWNLOAD_QUEUE = '11' # Shares download bandwidth among destination ports. | 47 _DOWNLOAD_QUEUE = '11' # Shares download bandwidth among destination ports. |
| 48 _DOWNLOAD_RULE = '5100' # Specifies when the download queue is used. | 48 _DOWNLOAD_RULE = '5100' # Specifies when the download queue is used. |
| 49 _QUEUE_SLOTS = 100 # Number of packets to queue. | 49 _QUEUE_SLOTS = 100 # Number of packets to queue. |
| 50 | 50 |
| 51 _BANDWIDTH_RE = re.compile(BANDWIDTH_PATTERN) | 51 _BANDWIDTH_RE = re.compile(BANDWIDTH_PATTERN) |
| 52 | 52 |
| 53 def __init__(self, | 53 def __init__(self, |
| 54 dont_use=None, | 54 dont_use=None, |
| 55 host='127.0.0.1', | 55 host='127.0.0.1', |
| 56 port='80', | 56 ports=None, |
|
slamm
2014/02/04 17:36:02
Nice simplification.
| |
| 57 ssl_port='443', | |
| 58 dns_port='53', | |
| 59 up_bandwidth='0', | 57 up_bandwidth='0', |
| 60 down_bandwidth='0', | 58 down_bandwidth='0', |
| 61 delay_ms='0', | 59 delay_ms='0', |
| 62 packet_loss_rate='0', | 60 packet_loss_rate='0', |
| 63 init_cwnd='0', | 61 init_cwnd='0', |
| 64 use_loopback=True): | 62 use_loopback=True): |
| 65 """Start shaping traffic. | 63 """Start shaping traffic. |
| 66 | 64 |
| 67 Args: | 65 Args: |
| 68 host: a host string (name or IP) for the web proxy. | 66 host: a host string (name or IP) for the web proxy. |
| 69 port: a port string (e.g. '80') for the web proxy. | 67 ports: a list of ports to shape traffic on. |
| 70 ssl_port: a port string (e.g. '443') for the SSL web proxy. | |
| 71 dns_port: a port string for the dns proxy (for unit testing). | |
| 72 up_bandwidth: Upload bandwidth | 68 up_bandwidth: Upload bandwidth |
| 73 down_bandwidth: Download bandwidth | 69 down_bandwidth: Download bandwidth |
| 74 Bandwidths measured in [K|M]{bit/s|Byte/s}. '0' means unlimited. | 70 Bandwidths measured in [K|M]{bit/s|Byte/s}. '0' means unlimited. |
| 75 delay_ms: Propagation delay in milliseconds. '0' means no delay. | 71 delay_ms: Propagation delay in milliseconds. '0' means no delay. |
| 76 packet_loss_rate: Packet loss rate in range [0..1]. '0' means no loss. | 72 packet_loss_rate: Packet loss rate in range [0..1]. '0' means no loss. |
| 77 init_cwnd: the initial cwnd setting. '0' means no change. | 73 init_cwnd: the initial cwnd setting. '0' means no change. |
| 78 use_loopback: True iff shaping is done on the loopback (or equiv) adapter. | 74 use_loopback: True iff shaping is done on the loopback (or equiv) adapter. |
| 79 """ | 75 """ |
| 80 assert dont_use is None # Force args to be named. | 76 assert dont_use is None # Force args to be named. |
| 81 self.host = host | 77 self.host = host |
| 82 self.port = port | 78 self.ports = ports |
| 83 self.ssl_port = ssl_port | |
| 84 self.dns_port = dns_port | |
| 85 self.up_bandwidth = up_bandwidth | 79 self.up_bandwidth = up_bandwidth |
| 86 self.down_bandwidth = down_bandwidth | 80 self.down_bandwidth = down_bandwidth |
| 87 self.delay_ms = delay_ms | 81 self.delay_ms = delay_ms |
| 88 self.packet_loss_rate = packet_loss_rate | 82 self.packet_loss_rate = packet_loss_rate |
| 89 self.init_cwnd = init_cwnd | 83 self.init_cwnd = init_cwnd |
| 90 self.use_loopback = use_loopback | 84 self.use_loopback = use_loopback |
| 91 if not self._BANDWIDTH_RE.match(self.up_bandwidth): | 85 if not self._BANDWIDTH_RE.match(self.up_bandwidth): |
| 92 raise BandwidthValueError(self.up_bandwidth) | 86 raise BandwidthValueError(self.up_bandwidth) |
| 93 if not self._BANDWIDTH_RE.match(self.down_bandwidth): | 87 if not self._BANDWIDTH_RE.match(self.down_bandwidth): |
| 94 raise BandwidthValueError(self.down_bandwidth) | 88 raise BandwidthValueError(self.down_bandwidth) |
| 95 self.is_shaping = False | 89 self.is_shaping = False |
| 96 | 90 |
| 97 def __enter__(self): | 91 def __enter__(self): |
| 98 if self.use_loopback: | 92 if self.use_loopback: |
| 99 platformsettings.setup_temporary_loopback_config() | 93 platformsettings.setup_temporary_loopback_config() |
| 100 if self.init_cwnd != '0': | 94 if self.init_cwnd != '0': |
| 101 platformsettings.set_temporary_tcp_init_cwnd(self.init_cwnd) | 95 platformsettings.set_temporary_tcp_init_cwnd(self.init_cwnd) |
| 102 try: | 96 try: |
| 103 ipfw_list = platformsettings.ipfw('list') | 97 ipfw_list = platformsettings.ipfw('list') |
| 104 if not ipfw_list.startswith('65535 '): | 98 if not ipfw_list.startswith('65535 '): |
| 105 logging.warn('ipfw has existing rules:\n%s', ipfw_list) | 99 logging.warn('ipfw has existing rules:\n%s', ipfw_list) |
| 106 self._delete_rules(ipfw_list) | 100 self._delete_rules(ipfw_list) |
| 107 except: | 101 except: |
| 108 pass | 102 pass |
| 109 if (self.up_bandwidth == '0' and self.down_bandwidth == '0' and | 103 if (self.up_bandwidth == '0' and self.down_bandwidth == '0' and |
| 110 self.delay_ms == '0' and self.packet_loss_rate == '0'): | 104 self.delay_ms == '0' and self.packet_loss_rate == '0'): |
| 111 logging.info('Skipped shaping traffic.') | 105 logging.info('Skipped shaping traffic.') |
| 112 return | 106 return |
| 113 if not self.dns_port and not self.port: | 107 if not self.ports: |
| 114 raise TrafficShaperException('No ports on which to shape traffic.') | 108 raise TrafficShaperException('No ports on which to shape traffic.') |
| 115 | 109 |
| 116 ports = ','.join( | 110 ports = ','.join([str(p) for p in self.ports]) |
|
slamm
2014/02/04 17:36:02
A generator works just as well here:
ports =
| |
| 117 str(p) for p in (self.port, self.ssl_port, self.dns_port) if p) | |
| 118 half_delay_ms = int(self.delay_ms) / 2 # split over up/down links | 111 half_delay_ms = int(self.delay_ms) / 2 # split over up/down links |
| 119 | 112 |
| 120 try: | 113 try: |
| 121 # Configure upload shaping. | 114 # Configure upload shaping. |
| 122 platformsettings.ipfw( | 115 platformsettings.ipfw( |
| 123 'pipe', self._UPLOAD_PIPE, | 116 'pipe', self._UPLOAD_PIPE, |
| 124 'config', | 117 'config', |
| 125 'bw', self.up_bandwidth, | 118 'bw', self.up_bandwidth, |
| 126 'delay', half_delay_ms, | 119 'delay', half_delay_ms, |
| 127 ) | 120 ) |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 | 177 |
| 185 def _delete_rules(self, ipfw_list=None): | 178 def _delete_rules(self, ipfw_list=None): |
| 186 if ipfw_list is None: | 179 if ipfw_list is None: |
| 187 ipfw_list = platformsettings.ipfw('list') | 180 ipfw_list = platformsettings.ipfw('list') |
| 188 existing_rules = set( | 181 existing_rules = set( |
| 189 r.split()[0].lstrip('0') for r in ipfw_list.splitlines()) | 182 r.split()[0].lstrip('0') for r in ipfw_list.splitlines()) |
| 190 delete_rules = [r for r in (self._DOWNLOAD_RULE, self._UPLOAD_RULE) | 183 delete_rules = [r for r in (self._DOWNLOAD_RULE, self._UPLOAD_RULE) |
| 191 if r in existing_rules] | 184 if r in existing_rules] |
| 192 if delete_rules: | 185 if delete_rules: |
| 193 platformsettings.ipfw('delete', *delete_rules) | 186 platformsettings.ipfw('delete', *delete_rules) |
| OLD | NEW |