{ "info": { "author": "Emmanuel Bretelle", "author_email": "chantra@fb.com", "bugtrack_url": null, "classifiers": [ "Programming Language :: Python" ], "description": "# ATCD\n\n## Introduction\n\nATCD is the `Augmented Traffic Control` (ATC) Daemon which is reponsible for\nhandling traffic shaping request for the devices.\n\n`atcd` is written in python and provide a [Thrift](https://thrift.apache.org/) interface to interact with it.\n\n## Requirements\n\nIn order to be able to shape traffic, `atcd` must be running on a router that forwards the packets of your devices.\n\n`atcd` works at Layer 3 so it does shape traffic on a per IP basis, as such, the\n`atcd` gateway **must** see the real IP of the devices. In other words, if you are using\nNATting, all the devices behind the NAT will get shaped using the same shaping rules.\n\n`atcd` depends on the following packages:\n\n* python 2.7\n* pyroute2==0.3.3\n* pyotp==1.4.1\n* sparts==0.7.1\n* atc_thrift==0.1.6\n\n## Installation\n\nThe easiest way to install `atcd` is to install it directly from [pip](https://pypi.python.org/pypi).\n\n### From pip\n\n``` bash\npip install atcd\n```\n\n### From source\n\n``` bash\ncd path/to/atcd\npip install .\n```\n\n## Configuration\n\n`atcd` is configured via command line arguments, to get the full list of options\nrun:\n\n```\natcd -h\n```\n\nThe most important options to configure are:\n\n* --atcd-wan: The interface used to connect to internet.\n* --atcd-lan: The interface used to connect to your devices.\n* --sqlite-file: The location where atcd will keep current device settings.\n\n`atcd` init files for debian and rhel based distro can be found in the [chef cookbook](../../chef/atc/files/default/init.d/)\n\n## How atcd works\n\n### Overview\n\nIn order to shape traffic, `atcd` leverages Linux's builtin [Traffic Control subsystem][tchowto]. Communication with the Traffic Control subsystem is done over the netlink API and facilitated by [pyroute2][pyroute2], a pure python netlink library.\n\nPackets that needs to be shaped are expected to be marked. Based on that mark, a classifier will put the packets in the right \"buckets\", which then will throttle the bandwith, add latency, drop packets, corrupt them... depending on the shaping settings.\n\nThe diagram below illustrate the flow an IP packet goes through:\n![ATC Diagram][atc_diagram]\n\n### In more details\n\n#### Marking packets\n\nPackets are marked by using iptables'`MARK` target within the `mangle` table. Marking is done as the packet traverses the router on the `FORWARD` chain, e.g when shaping packets for/to IPs 10.0.2.2, 10.0.2.4 and 10.0.2.5:\n\n```bash\n-A FORWARD -d 10.0.2.2/32 -i eth0 -j MARK --set-xmark 0x2/0xffffffff\n-A FORWARD -s 10.0.2.2/32 -i eth1 -j MARK --set-xmark 0x2/0xffffffff\n-A FORWARD -d 10.0.2.4/32 -i eth0 -j MARK --set-xmark 0x3/0xffffffff\n-A FORWARD -s 10.0.2.4/32 -i eth1 -j MARK --set-xmark 0x3/0xffffffff\n-A FORWARD -d 10.0.2.5/32 -i eth0 -j MARK --set-xmark 0x4/0xffffffff\n-A FORWARD -s 10.0.2.5/32 -i eth1 -j MARK --set-xmark 0x4/0xffffffff\n```\nwhere `eth0` is the network interface that connects to the internet.\n\n#### Shaping packets\n\nThe Traffic Controlling part is more complex. Below is what the shaping on the uplink may look like for 3 devices with IPs 10.0.2.2, 10.0.2.4 and 10.0.2.5:\n```bash\n# tc filter show dev eth0\nfilter parent 1: protocol ip pref 1 fw\nfilter parent 1: protocol ip pref 1 fw handle 0x2 classid 1:2 police 0x1 rate 100000bit burst 12000b mtu 2Kb action drop overhead 0b\nref 1 bind 1\n\nfilter parent 1: protocol ip pref 1 fw handle 0x3 classid 1:3 police 0x3 rate 200000bit burst 12000b mtu 2Kb action drop overhead 0b\nref 1 bind 1\n\nfilter parent 1: protocol ip pref 1 fw handle 0x4 classid 1:4 police 0x5 rate 200000bit burst 12000b mtu 2Kb action drop overhead 0b\nref 1 bind 1\n\n# tc class show dev eth0\nclass htb 1:4 root leaf 8005: prio 0 rate 200000bit ceil 200000bit burst 1600b cburst 1600b\nclass htb 1:2 root leaf 8001: prio 0 rate 100000bit ceil 100000bit burst 1600b cburst 1600b\nclass htb 1:3 root leaf 8003: prio 0 rate 200000bit ceil 200000bit burst 1600b cburst 1600b\n# tc qdisc show dev eth0\nqdisc htb 1: root refcnt 2 r2q 10 default 0 direct_packets_stat 3755 direct_qlen 1000\nqdisc netem 8001: parent 1:2 limit 1000 delay 10.0ms loss 1%\nqdisc netem 8003: parent 1:3 limit 1000 delay 20.0ms loss 2%\nqdisc netem 8005: parent 1:4 limit 1000 delay 20.0ms loss 2%\n```\n\nSo what goes on? When a packets gets in, it goes through the root qdisc (line 4), which is virtually unlimited, filters are checked and if a packet is marked with mark 0x2, it will be passed onto the class with id 1:2 where throttling happens. After that, the packet is passed to its child qdisc that uses netem to provide packet loss, corruption, reordering... and then off it goes on the wire.\n\nThe diagram below represents how the `filter`, `class` and `qdisc` fit together:\n\n```\n root 1:\n _ |_ <-- filter matching\n / | \\\n / | \\\n / | \\\n 1:2 1:3 1:4 <-- bandwidth limits\n | | |\n 8001: 8003: 8005: <-- delay, packet loss, reordering and corruption\n```\n\nWhen requesting `atcd` to shape/unshape traffic for a given device, `atcd` will set/unset the needed `iptables` rules and `filter`, `class` and `qdisc` to control the traffic. Aside from this, it will run some periodic tasks for housekeeping (like expiring shaping settings...).\n\n## Security\n\n`atcd` has currently almost no authentication/authorization mechanism built-in. It is recommended to make `atcd` only listen on `localhost`, and offload the authentication to the API.\n\n[tchowto]: http://www.tldp.org/HOWTO/Traffic-Control-HOWTO/\n[pyroute2]: https://github.com/svinota/pyroute2\n[atc_diagram]: https://facebook.github.io/augmented-traffic-control/images/atc_diagram.png", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/facebook/augmented-traffic-control", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "atcd", "package_url": "https://pypi.org/project/atcd/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/atcd/", "project_urls": { "Homepage": "https://github.com/facebook/augmented-traffic-control" }, "release_url": "https://pypi.org/project/atcd/0.1.6/", "requires_dist": [ "atc-thrift", "pyotp (==1.4.1)", "pyroute2 (==0.3.3)", "sparts (==0.7.1)" ], "requires_python": "", "summary": "ATC Daemon", "version": "0.1.6" }, "last_serial": 2366851, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "795f2d996fedf46bb6a4c2ff3589eb65", "sha256": "80b8b24ea0737b4f3d6800e9ef29779cd5ff55fe0c4c55ed9c86746812c832d9" }, "downloads": -1, "filename": "atcd-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "795f2d996fedf46bb6a4c2ff3589eb65", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 24955, "upload_time": "2015-03-23T08:52:20", "url": "https://files.pythonhosted.org/packages/ef/6f/8947dd314d0989fae3b4201cc7c0a3f937336e39d2cbcb3f1a57c401a368/atcd-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "43e8022288e5f2b6a28813c5869446c4", "sha256": "e7105a6f5ebbd2c87b408f5416794b929dabba756474485e11073397a2ef1844" }, "downloads": -1, "filename": "atcd-0.1.0.tar.gz", "has_sig": false, "md5_digest": "43e8022288e5f2b6a28813c5869446c4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17041, "upload_time": "2015-03-23T08:52:24", "url": "https://files.pythonhosted.org/packages/d8/73/67acbcca74976a2b31b0ca2fdaba1f6f39786091a563d79c21ecf6f5445c/atcd-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "a0d38e5cbe94369d3764fe46e0b44c62", "sha256": "41854e6a7dc6fce140732ff3ea3b3563ce8597682699fc0cbab38e8aa4606012" }, "downloads": -1, "filename": "atcd-0.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a0d38e5cbe94369d3764fe46e0b44c62", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 24967, "upload_time": "2015-03-30T21:07:59", "url": "https://files.pythonhosted.org/packages/51/cc/527fb65475809cbfb416d33dc70143557fdd047d4c495fb19593d66da70c/atcd-0.1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9761a63b59e30b228befcaca8f779fc1", "sha256": "8e76f39aca4af93e08805eeec6326b1e04f0d9f39680708be6ebcae794a4f6cf" }, "downloads": -1, "filename": "atcd-0.1.1.tar.gz", "has_sig": false, "md5_digest": "9761a63b59e30b228befcaca8f779fc1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19949, "upload_time": "2015-03-30T21:08:02", "url": "https://files.pythonhosted.org/packages/17/ea/5776906790009a488290a715fea989e94e4a331ea4fb749043cd54a50095/atcd-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "be205b75a2f9342ebb4230f5947d3128", "sha256": "7ac379ea7fbc6bb0b9fa9a7344eae2f8afdcfccc990f6ac85e3c90696e27cc99" }, "downloads": -1, "filename": "atcd-0.1.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "be205b75a2f9342ebb4230f5947d3128", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 25303, "upload_time": "2015-07-16T22:56:30", "url": "https://files.pythonhosted.org/packages/df/2f/87bbf44026b1afed1cfb52d1afec40b49849446e4856bf70d2d2a00e9a96/atcd-0.1.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "26452c538bbf9c3435141f71abc721df", "sha256": "956dad9802efe8e33b46c905bd27a4121346f200ef48a778fc12643bdaa76ca5" }, "downloads": -1, "filename": "atcd-0.1.2.tar.gz", "has_sig": false, "md5_digest": "26452c538bbf9c3435141f71abc721df", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17935, "upload_time": "2015-07-16T22:56:34", "url": "https://files.pythonhosted.org/packages/6f/bc/dcb914020250953a33c10875e56359b4cc40a3fdd403c550db65b942fe8d/atcd-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "9061b062c347528f8c062a13eec166c7", "sha256": "1f09f83a1d3f1904ec8d60c40e69f6b727cfd06b9e9f86f0718f43d9bd8b4a0d" }, "downloads": -1, "filename": "atcd-0.1.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "9061b062c347528f8c062a13eec166c7", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 25303, "upload_time": "2015-10-15T19:33:42", "url": "https://files.pythonhosted.org/packages/33/42/042ea86b314dc41a2fafae232bc563f353d58ff23369db779e1d34a77dde/atcd-0.1.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "db4b32afe97584db92ea18a342a34f30", "sha256": "35fb50955b44302331644d897e3f55b3d01ff27b331367100a78cad07a3d229b" }, "downloads": -1, "filename": "atcd-0.1.3.tar.gz", "has_sig": false, "md5_digest": "db4b32afe97584db92ea18a342a34f30", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17911, "upload_time": "2015-10-15T19:33:45", "url": "https://files.pythonhosted.org/packages/b4/e8/e854e62e9b2d91c71e050dd2be5438c1eebb7b7d51d2497624150466e4db/atcd-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "e84f09e2030b6936da47978adbc5db95", "sha256": "40bfea2df34e6a89118f702206bf3d0f4ced85d9ed6ccc9ad60e2fb42a50c19b" }, "downloads": -1, "filename": "atcd-0.1.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "e84f09e2030b6936da47978adbc5db95", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 25303, "upload_time": "2016-08-10T19:02:13", "url": "https://files.pythonhosted.org/packages/be/76/c5b9e1b8a523f46153a6e3000791467c2aaa6b13d3e9e19564db69f53d6f/atcd-0.1.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "465b6567e6bfe50e31b7efb3d9206fad", "sha256": "abb9122e998200a232b0ba3155efa4a4298a34316b2f463a751e11751ab72b92" }, "downloads": -1, "filename": "atcd-0.1.4.tar.gz", "has_sig": false, "md5_digest": "465b6567e6bfe50e31b7efb3d9206fad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17927, "upload_time": "2016-08-10T19:02:16", "url": "https://files.pythonhosted.org/packages/e5/f3/82dce5410746e2388bab58613eb3087dccb5b92fa23dabcc27cead8a9cea/atcd-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "bb6dbb67557b0f8c7b58ce8638bc4ff6", "sha256": "78c24f1d2648d80e1462adc95867361e9b90efe63871f36083f6c0f31d65cf6b" }, "downloads": -1, "filename": "atcd-0.1.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "bb6dbb67557b0f8c7b58ce8638bc4ff6", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 25307, "upload_time": "2016-08-18T15:46:47", "url": "https://files.pythonhosted.org/packages/4e/02/7bfe2cebdc43148f6507e12e5a9d4eedc2c453da923fe5dadc36a5750468/atcd-0.1.5-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7a84231ba9d44466b91849a39bccc1d4", "sha256": "9ab5f0da964ea67b29af95ecb56c6481e8c99added687b98cbeb59cbd1d56ae8" }, "downloads": -1, "filename": "atcd-0.1.5.tar.gz", "has_sig": false, "md5_digest": "7a84231ba9d44466b91849a39bccc1d4", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17926, "upload_time": "2016-08-18T15:46:50", "url": "https://files.pythonhosted.org/packages/30/fd/4a9803a83e62df476ff1990e9df192f5c149a5761df1ede18402e2920854/atcd-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "f39ff0c0331f35f49472f8338535dd76", "sha256": "1717a289dc1d9d57457b4d8e345aad2978f051fd7e75bb911b3c38ad1cffdd83" }, "downloads": -1, "filename": "atcd-0.1.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f39ff0c0331f35f49472f8338535dd76", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 25309, "upload_time": "2016-09-27T17:38:48", "url": "https://files.pythonhosted.org/packages/4d/e3/5eeb8d75461fac3f6cdd963e000eb81871be8aa3da7ecc3e5d005ff7b238/atcd-0.1.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ef0eade751c7db77c80d519f7700131f", "sha256": "719923ca77543ce0c9a1ff0b275bc5a72917cc77f97032c78be354c745907fb7" }, "downloads": -1, "filename": "atcd-0.1.6.tar.gz", "has_sig": false, "md5_digest": "ef0eade751c7db77c80d519f7700131f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17917, "upload_time": "2016-09-27T17:38:50", "url": "https://files.pythonhosted.org/packages/cd/ec/473c8b557713d3119fafd30323a9930056d770c44b66c2e8e831eb6c4442/atcd-0.1.6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "f39ff0c0331f35f49472f8338535dd76", "sha256": "1717a289dc1d9d57457b4d8e345aad2978f051fd7e75bb911b3c38ad1cffdd83" }, "downloads": -1, "filename": "atcd-0.1.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f39ff0c0331f35f49472f8338535dd76", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 25309, "upload_time": "2016-09-27T17:38:48", "url": "https://files.pythonhosted.org/packages/4d/e3/5eeb8d75461fac3f6cdd963e000eb81871be8aa3da7ecc3e5d005ff7b238/atcd-0.1.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ef0eade751c7db77c80d519f7700131f", "sha256": "719923ca77543ce0c9a1ff0b275bc5a72917cc77f97032c78be354c745907fb7" }, "downloads": -1, "filename": "atcd-0.1.6.tar.gz", "has_sig": false, "md5_digest": "ef0eade751c7db77c80d519f7700131f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 17917, "upload_time": "2016-09-27T17:38:50", "url": "https://files.pythonhosted.org/packages/cd/ec/473c8b557713d3119fafd30323a9930056d770c44b66c2e8e831eb6c4442/atcd-0.1.6.tar.gz" } ] }