# tcconfig wraps tc so you can shape traffic without writing qdisc rules

> tcconfig is a Python wrapper around the Linux tc command that turns bandwidth, latency, loss, corruption, duplication, reordering and packet limits into a single tcset command, and it can target a Docker container instead of a network interface. It is opinionated about syntax and thin about anything tc itself does not do.

**thombashi/tcconfig** — A tc command wrapper. Make it easy to set up traffic control of network bandwidth/latency/packet-loss/packet-corruption/etc. to a network-interface/Docker-container(veth).

- Repository: https://github.com/thombashi/tcconfig
- Website: https://tcconfig.rtfd.io/
- Stars: 854 · Forks: 89
- Language: Python
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/thombashi-tcconfig

## tc exists, tcconfig makes it readable

The Linux tc command is the standard tool for traffic control, and the syntax it exposes has a reputation for being difficult to read. tcconfig is a wrapper around it, written in Python and published on PyPI as tcconfig, whose stated purpose is to make it easy to set up traffic control of network bandwidth, latency, packet loss, packet corruption and similar conditions on a network interface or on a Docker container through its veth.

The value is in the argument names rather than in new capability. A tc qdisc invocation involves choosing a class, a filter and a handle, and the same rule for a different interface means editing several parts of the command. tcconfig turns that into one flag per property, and the flags are the names of the properties.

The three commands are tcset to add a rule, tcshow to display the current configuration, and tcdel to delete rules. The documentation is on Read the Docs at tcconfig.rtfd.io, and the repository carries a CHANGELOG.md, a docs directory and a test directory, along with a tox.ini and a Makefile for the development workflow.

The audience is developers and site reliability engineers who need to reproduce a bad network on purpose, whether that is a slow link, a lossy one or a congested one.

## The properties you can set, and the units they take

The list of parameters is what makes the wrapper useful. A network interface can be given a bandwidth rate in G, M or K bits per second, a latency in microseconds, milliseconds, seconds or minutes, and rates for packet loss, packet corruption, packet duplication and packet reordering, all as percentages, plus a packet limit as a count.

The time units are handled by name, and the documentation lists the accepted specifiers: h, hour and hours for hours; m, min, mins, minute and minutes for minutes; s, sec, secs, second and seconds for seconds; ms, msec, msecs, millisecond and milliseconds for milliseconds; us, usec, usecs, microsecond and microseconds for microseconds.

So a delay of 100 milliseconds, 10 seconds or 0.5 minutes can all be written the way you would say it, rather than converted into a unit tc accepts.

The percentage parameters are also written as percentages, so 0.1 percent loss is 0.1% on the command line. That reads more naturally than the base numbers tc uses, and it is a small thing that adds up when you are writing a test scenario file by hand.

## tcset in practice, one flag per property

The examples in the documentation are the fastest way to understand the syntax. A bandwidth limit on eth0 is set with the rate flag:

```bash
    # tcset eth0 --rate 100Kbps
```

Latency uses the delay flag with a time unit:

```bash
    # tcset eth0 --delay 100ms
```

```bash
    # tcset eth0 --delay 10sec
```

```bash
    # tcset eth0 --delay 0.5min
```

Several properties can be combined in a single command, which is the part that removes the most friction compared with raw tc:

```bash
    # tcset eth0 --rate 100Kbps --delay 100ms --loss 0.1%
```

The rules can also be narrowed to particular traffic. A single address is selected with the network flag, and a network with a port is expressed the same way:

```bash
    # tcset eth0 --delay 100ms --network 192.168.0.10
```

```bash
    # tcset eth0 --delay 100ms --network 192.168.0.0/24 --port 80
```

Direction matters too. The traffic control section lists outgoing and incoming packets as separate targets, along with source and destination IP addresses and networks for both IPv4 and IPv6, and source and destination ports. The direction is selected with a --direction flag whose values include incoming and outgoing.

## Docker containers are a first class target

Traffic shaping a container is the case the wrapper was built around, and there are two distinct routes.

On the Docker host, you run tcset with the --docker option and give it the container name or ID. The source and destination can be picked separately with the --src-container and --dst-container options, which means you can shape the traffic between two specific containers rather than everything on the host.

```bash
    # tcset <container name or ID> --docker ...
```

Inside a container, the container needs the NET_ADMIN capability for tc to work, and the documentation gives the run command:

```bash
    docker run -d --cap-add NET_ADMIN -t <docker image>
```

There is also a container image with tcconfig built in, published at hub.docker.com/r/thombashi/tcconfig/.

The capability requirement is the detail to keep in mind. NET_ADMIN is a broad privilege, and granting it to a container purely to shape its own traffic is a decision to make deliberately rather than by copy and paste. The host side route, where the shaping is applied to the container's veth from the Docker host, avoids putting that capability inside the container at all, and it is the form to prefer when you have the choice.

## tcshow prints the rules back as JSON

Reading the current state is where a JSON output earns its keep. tcshow displays the traffic control settings for network interfaces, and the documented example shows the shape of the output, with the interface as the top level key and outgoing and incoming sections underneath, each holding the filters and the values that were set:

```bash
    # tcshow eth0
```

The example output is a JSON object keyed by the interface, where each direction maps to a dictionary of filters, each filter holding a filter_id and the delay, delay-distro, loss and rate values that were applied. Filters are described by the traffic they match, such as a destination network and port with the protocol.

That structure means the state of a host can be checked from a script without parsing human formatted tc output. It is also how you confirm what a previous run actually did, which matters when a test environment has been reshaped by several different commands and you need to know what is still in place.

Removing rules is the third operation, and tcdel takes the same interface argument plus an --all option to clear every shaping rule for that device.

## What tcconfig does not add to tc

The honest framing is that tcconfig is a front end, not an extension of the kernel queuing system. Every property it sets maps to something tc already does, and the underlying scheduling, classification and queuing behaviour is entirely tc's.

The practical limits follow from that. There is no new scheduler, no queue discipline of its own, and no way to express a rule that tc could not. If you need a specific qdisc configuration, a netem combination tcconfig does not wrap, or a filter match on something other than the documented dimensions, you will be back in tc by hand.

The command names also give the tool away. There is a tcconfig command that installs tcset, tcshow and tcdel, and a separate tcconfig invocation with the --docker option to work with containers, and the examples show tcset used as a standalone command. That vocabulary is a deliberate choice to look like tc, which is a plus if you already know tc and a mild cost if you do not, since you then have to learn which of tc's abilities are exposed.

The project description calls it a tc command wrapper, and reading the code as a wrapper rather than as a new tool is the right expectation to set.

## Packaging details and the release history

The package is a conventional Python project with a modern build setup. pyproject.toml uses the setuptools build backend with setuptools_scm, so the version is derived from the repository tags rather than written by hand, and the version scheme is guess-next-dev with no local version segment. The tool configuration is equally explicit: black and ruff both use a line length of 100, isort is configured with two lines after imports, and pytest is pointed at the test directory with markdown reporting enabled.

The setup.py reads the version from the package's __version__.py, takes the long description from README.rst and the summary from a text file under docs, and splits the requirements into separate files for runtime, test and docs dependencies, which is what lets tox run the different environments.

The release history is the part to note. Version 0.30.1 was tagged on 2025-05-08 and v0.30.0 on 2025-05-05, with v0.29.1 before that on 2024-07-28. The repository is not archived and the last push was on 2026-04-13, so work continues on the master branch, but the newest published release is from 2025. The version remains below 1.0, and the project ships an MIT licence, which keeps the legal side simple for most uses.

## Conclusion

tcconfig suits anyone who needs repeatable network conditions on a Linux host or inside a container, since the tcset, tcshow and tcdel commands take readable arguments and tcshow prints the resulting configuration as JSON. It is not a replacement for tc, because everything it does maps onto tc rules and it adds no scheduler or queuing logic of its own. Before adopting it, check that the tc binary and the iproute2 tools are present on the target host, decide whether you need the --docker or --src-container form, and remember that the newest release is v0.30.1 from 2025-05-08 with the last push on 2026-04-13, so read the changelog before pinning a version in a test pipeline.

## FAQ

### How do I set a bandwidth limit with tcconfig?

Use the tcset command with the rate flag, for example tcset eth0 --rate 100Kbps. Rates accept G, M and K bits per second, and other properties such as delay and loss can be combined in the same command.

### How do I apply traffic shaping to a Docker container with tcconfig?

On the Docker host, run tcset with the --docker option and the container name or ID, using --src-container or --dst-container to pick the source or destination. To shape traffic inside the container instead, run the container with the NET_ADMIN capability, for example docker run -d --cap-add NET_ADMIN -t <docker image>.

### How do I check and remove traffic control rules with tcconfig?

tcshow displays the current traffic control settings for a network interface, and its output is JSON keyed by interface and direction with the filter values nested inside. tcdel removes rules, and the --all option clears every shaping rule for the interface.

## Sources

- [License: MIT](https://github.com/thombashi/tcconfig/blob/master/LICENSE)
- [Project website](https://tcconfig.rtfd.io/)
- [README](https://github.com/thombashi/tcconfig/blob/master/README.md)
- [Releases](https://github.com/thombashi/tcconfig/releases)
- [thombashi/tcconfig on GitHub](https://github.com/thombashi/tcconfig)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/thombashi-tcconfig
