Skip to content

Commit

Permalink
Merge pull request #19 from thombashi/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
thombashi committed Mar 13, 2016
2 parents 95c045a + 052821e commit 92c504e
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 62 deletions.
124 changes: 107 additions & 17 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,35 +53,39 @@ manager).
Usage
=====

Set traffic control (tcset)
---------------------------
Set traffic control (``tcset`` command)
---------------------------------------

``tcset`` is a command to impose traffic control to a network interface
(device).

tcset help
~~~~~~~~~~
``tcset`` help
~~~~~~~~~~~~~~

.. code:: console
usage: tcset [-h] [--version] [--logging] [--stacktrace] [--debug | --quiet]
--device DEVICE [--overwrite] [--direction {outgoing,incoming}]
[--rate BANDWIDTH_RATE] [--delay NETWORK_LATENCY]
[--delay-distro LATENCY_DISTRO_MS] [--loss PACKET_LOSS_RATE]
[--corrupt CORRUPTION_RATE] [--network NETWORK] [--port PORT]
(--device DEVICE | -f CONFIG_FILE) [--overwrite]
[--direction {outgoing,incoming}] [--rate BANDWIDTH_RATE]
[--delay NETWORK_LATENCY] [--delay-distro LATENCY_DISTRO_MS]
[--loss PACKET_LOSS_RATE] [--corrupt CORRUPTION_RATE]
[--network NETWORK] [--port PORT]
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.
--device DEVICE network device name (e.g. eth0)
-f CONFIG_FILE, --config-file CONFIG_FILE
setting traffic controls from configuration file.
output file of the tcshow.
Miscellaneous:
--logging output execution log to a file (tcset.log).
--stacktrace display stack trace when an error occurred.
Network Interface:
--device DEVICE network device name (e.g. eth0)
--overwrite overwrite existing settings
Traffic Control:
Expand Down Expand Up @@ -189,14 +193,14 @@ e.g. Set 100ms +- 20ms network latency with normal distribution
# tcset --device eth0 --delay 100 --delay-distro 20
Delete traffic control (tcdel)
------------------------------
Delete traffic control (``tcdel`` command)
------------------------------------------

``tcdel`` is a command to delete traffic control from a network
interface (device).

tcdel help
~~~~~~~~~~
``tcdel`` help
~~~~~~~~~~~~~~

.. code:: console
Expand All @@ -223,8 +227,8 @@ e.g. Delete traffic control of eth0
# tcdel --device eth0
Display traffic control configurations (tcshow)
-----------------------------------------------
Display traffic control configurations (``tcshow`` command)
-----------------------------------------------------------

``tcshow`` is a command to display traffic control to network
interface(s).
Expand All @@ -233,8 +237,8 @@ Note: scope of ``tcshow`` command is limited to parameters that can be
set with tcset (``tcshow`` is not a general purpose tool to display all
of the parameters of the tc command).

tcshow help
~~~~~~~~~~~
``tcshow`` help
~~~~~~~~~~~~~~~

.. code:: console
Expand Down Expand Up @@ -283,6 +287,92 @@ Example
}
}
Backup and restore traffic control configurations
-------------------------------------------------

Backup configurations
~~~~~~~~~~~~~~~~~~~~~

.. code:: console
# tcset --device eth0 --delay 10 --delay-distro 2 --loss 0.01 --rate 0.25M --network 192.168.0.10 --port 8080
# tcset --device eth0 --delay 1 --loss 0.02 --rate 500K --direction incoming
# tcset --device eth1 --delay 2.5 --delay-distro 1.2 --loss 0.01 --rate 0.25M --port 80
# tcset --device eth1 --corrupt 0.02 --rate 1.5M --direction incoming --network 192.168.10.0/24
.. code:: console
# tcshow --device eth0 --device eth1 > tcconfig.json
Restore configurations
~~~~~~~~~~~~~~~~~~~~~~

Before restore

.. code:: console
# tcshow --device eth0 --device eth1
{
"eth1": {
"outgoing": {},
"incoming": {}
},
"eth0": {
"outgoing": {},
"incoming": {}
}
}
Restore from a configuration file.

.. code:: console
# tcset -f tcconfig.json
After restore

.. code:: console
# tcshow --device eth0 --device eth1
{
"eth1": {
"outgoing": {
"port=80": {
"delay": "2.5",
"loss": "0.01",
"rate": "250K",
"delay-distro": "1.2"
},
"network=0.0.0.0/0": {}
},
"incoming": {
"network=192.168.10.0/24": {
"corrupt": "0.02",
"rate": "1500K"
},
"network=0.0.0.0/0": {}
}
},
"eth0": {
"outgoing": {
"network=192.168.0.10/32, port=8080": {
"delay": "10.0",
"loss": "0.01",
"rate": "250K",
"delay-distro": "2.0"
},
"network=0.0.0.0/0": {}
},
"incoming": {
"network=0.0.0.0/0": {
"delay": "1.0",
"loss": "0.02",
"rate": "500K"
}
}
}
}
Dependencies
============

Expand Down
2 changes: 1 addition & 1 deletion tcconfig/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
@author: Tsuyoshi Hombashi
'''

VERSION = "0.5.0"
VERSION = "0.6.0"


def verify_network_interface(device):
Expand Down
14 changes: 7 additions & 7 deletions tcconfig/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class FilterMatchId:
__FILTER_PATTERN = (
pp.Literal("filter parent") +
pp.SkipTo("flowid", include=True) +
pp.Word(pp.nums + ":")
pp.Word(pp.alphanums + ":")
)
__FILTER_MATCH_PATTERN = (
pp.Literal("match") +
Expand Down Expand Up @@ -140,12 +140,12 @@ def parse(self, text):
continue

if re.search("qdisc netem", line) is not None:
self.__parse_netem_param(line, "parent")
self.__parse_netem_param(line, "parent", pp.alphanums + ":")

self.__parse_netem_param(line, "delay")
self.__parse_netem_param(line, "delay", pp.nums + ".")
self.__parse_netem_delay_distro(line)
self.__parse_netem_param(line, "loss")
self.__parse_netem_param(line, "corrupt")
self.__parse_netem_param(line, "loss", pp.nums + ".")
self.__parse_netem_param(line, "corrupt", pp.nums + ".")
self.__parse_tbf_rate(line)

return self.__parsed_param
Expand All @@ -164,10 +164,10 @@ def __parse_netem_delay_distro(self, line):
except pp.ParseException:
pass

def __parse_netem_param(self, line, parse_param_name):
def __parse_netem_param(self, line, parse_param_name, word_pattern):
pattern = (
pp.SkipTo(parse_param_name, include=True) +
pp.Word(pp.nums + "." + ":"))
pp.Word(word_pattern))

try:
result = pattern.parseString(line)[-1]
Expand Down
96 changes: 94 additions & 2 deletions tcconfig/tcset.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
from __future__ import with_statement
import sys

import dataproperty
import pyparsing as pp
import six
import thutils

import tcconfig
import tcconfig.traffic_control

Expand All @@ -18,10 +22,16 @@ def parse_option():
parser = thutils.option.ArgumentParserObject()
parser.make(version=tcconfig.VERSION)

group = parser.add_argument_group("Network Interface")
group = parser.parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"--device", required=True,
"--device",
help="network device name (e.g. eth0)")
group.add_argument(
"-f", "--config-file",
help="""setting traffic controls from configuration file.
output file of the tcshow.""")

group = parser.add_argument_group("Network Interface")
group.add_argument(
"--overwrite", action="store_true", default=False,
help="overwrite existing settings")
Expand Down Expand Up @@ -68,6 +78,77 @@ def parse_option():
return parser.parse_args()


def _parse_tc_filter_network(text):
network_pattern = (
pp.SkipTo("network=", include=True) +
pp.Word(pp.alphanums + "." + "/"))

return network_pattern.parseString(text)[-1]


def _parse_tc_filter_port(text):
port_pattern = (
pp.SkipTo("port=", include=True) +
pp.Word(pp.nums))

return port_pattern.parseString(text)[-1]


def load_tcconfig(config_file):
from voluptuous import Schema, Required, Any, ALLOW_EXTRA

schema = Schema({
Required(six.text_type): {
Any("outgoing", "incoming"): {
six.text_type: {
six.text_type: six.text_type,
},
}
},
}, extra=ALLOW_EXTRA)

return thutils.loader.JsonLoader.load(
config_file, schema)


def get_tcconfig_command_list(config_table, is_overwrite):
command_list = []

for device, device_table in six.iteritems(config_table):
if is_overwrite:
command_list.append("tcdel --device " + device)

for direction, direction_table in six.iteritems(device_table):
for tc_filter, filter_table in six.iteritems(direction_table):
if filter_table == {}:
continue

option_list = [
"--device=" + device,
"--direction=" + direction,
] + [
"--%s=%s" % (k, v)
for k, v in six.iteritems(filter_table)
]

try:
network = _parse_tc_filter_network(tc_filter)
if network != "0.0.0.0/0":
option_list.append("--network=" + network)
except pp.ParseException:
pass

try:
port = _parse_tc_filter_port(tc_filter)
option_list.append("--port=" + port)
except pp.ParseException:
pass

command_list.append(" ".join(["tcset"] + option_list))

return command_list


@thutils.main.Main
def main():
options = parse_option()
Expand All @@ -76,6 +157,17 @@ def main():
thutils.common.verify_install_command(["tc"])

subproc_wrapper = thutils.subprocwrapper.SubprocessWrapper()

if dataproperty.is_not_empty_string(options.config_file):
return_code = 0

for tcconfig_command in get_tcconfig_command_list(
load_tcconfig(options.config_file), options.overwrite):
# print tcconfig_command
return_code |= subproc_wrapper.run(tcconfig_command)

return return_code

tc = tcconfig.traffic_control.TrafficControl(
subproc_wrapper, options.device)
tc.direction = options.direction
Expand Down
Loading

0 comments on commit 92c504e

Please sign in to comment.