Add helpers for Linux Traffic Control (TC) filter#209
Add helpers for Linux Traffic Control (TC) filter#209peilin-ye wants to merge 6 commits intoosandov:mainfrom
Conversation
Add a helper, for_each_tcf_chain(), to iterate over all TC filter chains
on a block (struct tcf_block *). As an example:
>>> eth0 = netdev_get_by_name(prog, "eth0")
>>> htb = qdisc_lookup(eth0, 0x1)
>>> block = Object(prog, "struct htb_sched *", htb.privdata.address_).block
>>> for chain in for_each_tcf_chain(block):
... print(chain.index)
...
0
1
2
This is only supported since Linux kernel commit 2190d1d0944f ("net:
sched: introduce helpers to work with filter chains") in v4.13.
Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
Add a helper, get_tcf_chain_by_index(), to get a TC filter chain from a
block given the chain index number. As an example:
>>> eth0 = netdev_get_by_name(prog, "eth0")
>>> htb = qdisc_lookup(eth0, 0x1)
>>> block = Object(prog, "struct htb_sched *", htb.privdata.address_).block
>>> chain = get_tcf_chain_by_index(block, 0)
>>> chain.filter_chain.ops.kind
b'u32'
This is only supported since Linux kernel commit 5bc1701881e3 ("net:
sched: introduce multichain support for filters") in v4.13.
Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
Add a helper, for_each_tcf_proto(), to iterate over all TC filters
(struct tcf_proto *) on a filter chain. As an example:
>>> eth0 = netdev_get_by_name(prog, "eth0")
>>> htb = qdisc_lookup(eth0, 0x1)
>>> block = Object(prog, "struct htb_sched *", htb.privdata.address_).block
>>> chain = get_tcf_chain_by_index(block, 0)
>>> for filter in for for_each_tcf_proto(chain):
... print(filter.ops.kind)
b'u32'
b'matchall'
b'flower'
This is only supported since Linux kernel commit 2190d1d0944f ("net:
sched: introduce helpers to work with filter chains") in v4.13.
Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
Add a helper, get_tcf_proto_by_prio(), to get a TC filter (struct
tcf_proto *) from a chain given the priority (preference) number. As an
example:
>>> eth0 = netdev_get_by_name(prog, "eth0")
>>> htb = qdisc_lookup(eth0, 0x1)
>>> block = Object(prog, "struct htb_sched *", htb.privdata.address_).block
>>> chain = get_tcf_chain_by_index(block, 0)
>>> u32 = get_tcf_proto_by_prio(chain, 10)
>>> u32.ops.kind
b'u32'
This is only supported since Linux kernel commit 2190d1d0944f ("net:
sched: introduce helpers to work with filter chains") in v4.13.
Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
Since we are planning to add more TestTc() tests, factor out common code and shared variables (e.g. drgn Object for network namespace). Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
Add a TestTc() test, test_tcf_chain_and_tcf_proto(), for the following
helpers:
for_each_tcf_chain()
for_each_tcf_proto()
get_tcf_chain_by_index()
get_tcf_proto_by_prio()
It depends on Linux kernel CONFIG_NET_SCH_HTB and CONFIG_NET_CLS_U32
configs, and is skipped if kernel is older than v4.13 (commit 5bc1701881e3
("net: sched: introduce multichain support for filters")).
It depends on the TCA_CHAIN netlink message attribute, which pyroute2
does not support yet. Use a customized class tcmsg for now.
Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
2f4d457 to
43c214f
Compare
|
Fixed a |
osandov
left a comment
There was a problem hiding this comment.
I only gave this a quick look and had some questions about the kernel versions involved. I'll give it a more thorough review once that's cleared up. Thank you!
| # Before Linux kernel commit 5bc1701881e3 ("net: sched: introduce | ||
| # multichain support for filters") (in v4.13), each block contained only | ||
| # one chain. | ||
| try: | ||
| chain_list = block.chain_list.address_of_() | ||
| except AttributeError: | ||
| # Before Linux kernel commit 2190d1d0944f ("net: sched: introduce | ||
| # helpers to work with filter chains") (in v4.13), struct tcf_chain | ||
| # didn't exist. | ||
| return block.chain |
There was a problem hiding this comment.
It looks like both of these commits went in during v4.13-rc1. I wouldn't bother checking for the intermediate state between those two commits; let's just assume that the kernel is an official tagged release, which I think will simplify this.
| """ | ||
| Iterate over all TC filter chains on a block. | ||
|
|
||
| This is only supported since Linux v4.13. |
There was a problem hiding this comment.
I'm not familiar with TC at all, but looking at the commits you reference here, it looks like TC filter chains didn't exist at all before 4.13, is that correct? Maybe we can say something like "This is only supported since Linux v4.13, before which TC filter chains didn't exist.".
| for chain in list_for_each_entry("struct tcf_chain", chain_list, "list"): | ||
| yield chain |
There was a problem hiding this comment.
I think you can simplify this to:
| for chain in list_for_each_entry("struct tcf_chain", chain_list, "list"): | |
| yield chain | |
| return list_for_each_entry("struct tcf_chain", chain_list, "list") |
Hi all,
These are helpers for Linux TC filter (
struct tcf_proto) and filter chain (struct tcf_chain) that I found useful when debugging TC issues. They are only supported since Linux v4.13 because several related data structures didn't exist before that.The test is skipped if kernel is older than v4.13 commit 5bc1701881e3 ("net: sched: introduce multichain support for filters"), and depends on config
CONFIG_NET_SCH_HTBandCONFIG_NET_CLS_U32. It uses theTCA_CHAINNetlink message attribute, which pyroute2 doesn't fully support yet, which is why the test may look a bit over-complicated. I will addTCA_CHAINsupport to pyroute2 and clean it up.Thanks,
Peilin Ye