Skip to content

Commit

Permalink
Merge pull request #1 from thombashi/develop
Browse files Browse the repository at this point in the history
initial commit
  • Loading branch information
thombashi committed Jan 18, 2016
2 parents d157e37 + 2988130 commit d3f0ed6
Show file tree
Hide file tree
Showing 10 changed files with 383 additions and 0 deletions.
60 changes: 60 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover

# Translations
*.mo
*.pot

# Django stuff:
*.log

# Sphinx documentation
docs/_build/

# PyBuilder
target/
/.idea
convert_readme.sh
desktop.ini
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include LICENSE
include README.rst
include setup.cfg
include requirements.txt
recursive-include test *
74 changes: 74 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
tcconfig

About
=====

tcconfig is a simple tc (traffic control) command wrapper.

Installation
============

.. code:: console
pip install tcconfig
Usage
=====

Set traffic control
-------------------

Help
~~~~

.. code:: console
usage: tcset [-h] [--version] [--time-measure] [--logging] [--stacktrace]
[--debug | --quiet] --device DEVICE [--rate RATE] [--delay DELAY]
[--loss LOSS] [--overwrite]
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
--debug for debug print.
--quiet suppress output of execution log message.
Miscellaneous:
--time-measure measuring execution time.
--logging suppress output of execution log files.
--stacktrace display stack trace when an error occurred.
Traffic Control:
--device DEVICE network device name
--rate RATE network bandwidth [K|M|G bps]
--delay DELAY round trip network delay [ms] (default=0)
--loss LOSS round trip packet loss rate [%] (default=0)
--overwrite overwrite existing setting
e.g. Set a limit on bandwidth up to 100Kbps
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: console
# tcset --device eth0 --rate 100k
e.g. Set 100ms network delay
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: console
# tcset --device eth0 --delay 100
e.g. Set 0.1% packet loss
~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: console
# tcset --device eth0 --loss 0.1
Delete traffic control
----------------------

.. code:: console
# tcdel --device eth0
29 changes: 29 additions & 0 deletions common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

def set_tc(sys_wrapper, device, rate_mbps, delay_ms, loss_percent):
import delete_tc

delete_tc.delete_tc(sys_wrapper, device)

command = "tc qdisc add dev %s root handle 1: htb default 0" % (device)
if sys_wrapper.run(command) != 0:
return

if thutils.common.is_float(rate_mbps):
command = "tc class add dev %s parent 1:0 classid 1:0 htb rate %dmbit" % (
device, rate_mbps)
sys_wrapper.run(command)

if thutils.common.is_float(loss_percent) and thutils.common.is_float(delay_ms):
one_way_loss = loss_percent
one_way_delay = delay_ms
command = "tc qdisc add dev %s root netem loss %s%% delay %dms limit 100000000000000" % (
device, str(one_way_loss), one_way_delay)
sys_wrapper.run(command)


def delete_tc(sys_wrapper, device):
command = "tc qdisc del dev %s root" % (device)
sys_wrapper.run(command)

command = "tc qdisc del dev %s root" % (device)
sys_wrapper.run(command)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
thutils
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[wheel]
universal = 1
51 changes: 51 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from __future__ import with_statement
import sys
import setuptools
from setuptools.command.test import test as TestCommand

import tcconfig


with open("README.rst") as fp:
long_description = fp.read()

with open("requirements.txt", "r") as fp:
requirements = fp.read().splitlines()

major, minor = sys.version_info[:2]

if major == 2 and minor <= 5:
requirements.extend([
"argparse",
])

setuptools.setup(
name="tcconfig",
version=tcconfig.VERSION,
author="Tsuyoshi Hombashi",
author_email="[email protected]",
url="https://github.com/thombashi/tcconfig",
description="Simple tc (traffic control) command wrapper",
long_description=long_description,
license="GNU General Public License v3 (LGPLv3)",
include_package_data=True,
packages=setuptools.find_packages(exclude=['test*']),
install_requires=requirements,
classifiers=[
"Development Status :: 3 - Alpha",
"Environment :: Console",
"Intended Audience :: System Administrators",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Operating System :: POSIX",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 3",
"Topic :: System :: Networking",
],
entry_points={
"console_scripts": [
"tcset=tcconfig.tcset:main",
"tcdel=tcconfig.tcdel:main",
],
}
)
61 changes: 61 additions & 0 deletions tcconfig/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import thutils


VERSION = "0.1.0"

_MAX_LOSS_RATE = 99
_MAX_DELAY_MS = 10000
_MIN_BUFFER_BYTE = 1600


def _set_delay_and_loss(sys_wrapper, device, delay_ms, loss_percent):
if loss_percent > _MAX_LOSS_RATE:
raise ValueError("packet loss rate is too high")

if delay_ms > _MAX_DELAY_MS:
raise ValueError("delay time is too high")

command_list = [
"tc qdisc add",
"dev %s" % (device),
"root handle 1:0 netem",
]
if loss_percent > 0:
command_list.append("loss %s%%" % (loss_percent))
if delay_ms > 0:
command_list.append("delay %dms" % (delay_ms))

return sys_wrapper.run(" ".join(command_list))


def _set_rate(sys_wrapper, device, rate):
if thutils.common.isEmptyString(rate):
return 0

rate_kbps = thutils.common.humanreadable_to_byte(
rate, kilo_size=1000) / 1000.0
if rate_kbps <= 0:
raise ValueError("rate must be greater than zero")

command_list = [
"tc qdisc add",
"dev %s" % (device),
"parent 1:1",
"handle 10:",
"tbf",
"rate %dkbit" % (rate_kbps),
"buffer %d" % (max(rate_kbps, _MIN_BUFFER_BYTE)), # [byte]
"limit 10000",
]

return sys_wrapper.run(" ".join(command_list))


def set_tc(sys_wrapper, device, rate, delay_ms, loss_percent):
_set_delay_and_loss(sys_wrapper, device, delay_ms, loss_percent)
_set_rate(sys_wrapper, device, rate)


def delete_tc(sys_wrapper, device):
command = "tc qdisc del dev %s root" % (device)
return sys_wrapper.run(command)
42 changes: 42 additions & 0 deletions tcconfig/tcdel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/usr/bin/env python
# encoding: utf-8

'''
@author: Tsuyoshi Hombashi
'''

from __future__ import with_statement
import sys

import thutils
import tcconfig


def parse_option():
parser = thutils.option.ArgumentParserObject()
parser.make(version=tcconfig.VERSION)

group = parser.add_argument_group("Traffic Control")
group.add_argument(
"--device", required=True,
help="network device name")

return parser.parse_args()


@thutils.main.Main
def main():
options = parse_option()

thutils.initialize_library(__file__, options)

thutils.common.verify_install_command(["tc"])

sys_wrapper = thutils.syswrapper.SystemWrapper()
tcconfig.delete_tc(sys_wrapper, options.device)

return 0


if __name__ == '__main__':
sys.exit(main())
58 changes: 58 additions & 0 deletions tcconfig/tcset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env python
# encoding: utf-8

'''
@author: Tsuyoshi Hombashi
'''

from __future__ import with_statement
import sys

import thutils
import tcconfig


def parse_option():
parser = thutils.option.ArgumentParserObject()
parser.make(version=tcconfig.VERSION)

group = parser.add_argument_group("Traffic Control")
group.add_argument(
"--device", required=True,
help="network device name")
group.add_argument(
"--rate",
help="network bandwidth [K|M|G bps]")
group.add_argument(
"--delay", type=float, default=0,
help="round trip network delay [ms] (default=%(default)s)")
group.add_argument(
"--loss", type=float, default=0,
help="round trip packet loss rate [%%] (default=%(default)s)")
group.add_argument(
"--overwrite", action="store_true", default=False,
help="overwrite existing setting")

return parser.parse_args()


@thutils.main.Main
def main():
options = parse_option()

thutils.initialize_library(__file__, options)
thutils.common.verify_install_command(["tc"])

sys_wrapper = thutils.syswrapper.SystemWrapper()

if options.overwrite:
tcconfig.delete_tc(sys_wrapper, options.device)

tcconfig.set_tc(sys_wrapper, options.device,
options.rate, options.delay, options.loss)

return 0


if __name__ == '__main__':
sys.exit(main())

0 comments on commit d3f0ed6

Please sign in to comment.