-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add helpers for Linux Traffic Control (TC) filter #209
base: main
Are you sure you want to change the base?
Changes from all commits
7e4f037
5972eed
7778cf1
63dd48d
6665dcf
43c214f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -10,11 +10,102 @@ | |||||||
""" | ||||||||
|
||||||||
import operator | ||||||||
from typing import Iterator | ||||||||
|
||||||||
from drgn import NULL, IntegerLike, Object | ||||||||
from drgn.helpers.linux.list import hlist_for_each_entry, list_for_each_entry | ||||||||
|
||||||||
__all__ = ("qdisc_lookup",) | ||||||||
__all__ = ( | ||||||||
"for_each_tcf_chain", | ||||||||
"for_each_tcf_proto", | ||||||||
"get_tcf_chain_by_index", | ||||||||
"get_tcf_proto_by_prio", | ||||||||
"qdisc_lookup", | ||||||||
) | ||||||||
|
||||||||
|
||||||||
def for_each_tcf_chain(block: Object) -> Iterator[Object]: | ||||||||
""" | ||||||||
Iterate over all TC filter chains on a block. | ||||||||
|
||||||||
This is only supported since Linux v4.13. | ||||||||
|
||||||||
:param block: ``struct tcf_block *`` | ||||||||
:return: Iterator of ``struct tcf_chain *`` objects. | ||||||||
""" | ||||||||
# 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 | ||||||||
Comment on lines
+36
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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. |
||||||||
|
||||||||
for chain in list_for_each_entry("struct tcf_chain", chain_list, "list"): | ||||||||
yield chain | ||||||||
Comment on lines
+47
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can simplify this to:
Suggested change
|
||||||||
|
||||||||
|
||||||||
def for_each_tcf_proto(chain: Object) -> Iterator[Object]: | ||||||||
""" | ||||||||
Iterate over all TC filters on a chain. | ||||||||
|
||||||||
This is only supported since Linux v4.13. | ||||||||
|
||||||||
:param chain: ``struct tcf_chain *`` | ||||||||
:return: Iterator of ``struct tcf_proto *`` objects. | ||||||||
""" | ||||||||
# Before Linux kernel commit 2190d1d0944f ("net: sched: introduce helpers | ||||||||
# to work with filter chains") (in v4.13), struct tcf_chain::filter_chain | ||||||||
# didn't exist. | ||||||||
proto = chain.filter_chain | ||||||||
|
||||||||
while proto: | ||||||||
yield proto | ||||||||
proto = proto.next | ||||||||
|
||||||||
|
||||||||
def get_tcf_chain_by_index(block: Object, index: IntegerLike) -> Object: | ||||||||
""" | ||||||||
Get the TC filter chain with the given index number from a block. | ||||||||
|
||||||||
This is only supported since Linux v4.13. | ||||||||
|
||||||||
:param block: ``struct tcf_block *`` | ||||||||
:param index: TC filter chain index number | ||||||||
:return: ``struct tcf_chain *`` (``NULL`` if not found) | ||||||||
""" | ||||||||
index = operator.index(index) | ||||||||
|
||||||||
for chain in for_each_tcf_chain(block): | ||||||||
# Before Linux kernel commit 5bc1701881e3 ("net: sched: introduce | ||||||||
# multichain support for filters") (in v4.13), struct tcf_chain::index | ||||||||
# didn't exist. | ||||||||
if chain.index == index: | ||||||||
return chain | ||||||||
|
||||||||
return NULL(block.prog_, "struct tcf_chain *") | ||||||||
|
||||||||
|
||||||||
def get_tcf_proto_by_prio(chain: Object, prio: IntegerLike) -> Object: | ||||||||
""" | ||||||||
Get the TC filter with the given priority from a chain. | ||||||||
|
||||||||
This is only supported since Linux v4.13. | ||||||||
|
||||||||
:param chain: ``struct tcf_chain *`` | ||||||||
:param prio: TC filter priority (preference) number | ||||||||
:return: ``struct tcf_proto *`` (``NULL`` if not found) | ||||||||
""" | ||||||||
prio = operator.index(prio) << 16 | ||||||||
|
||||||||
for proto in for_each_tcf_proto(chain): | ||||||||
if proto.prio == prio: | ||||||||
return proto | ||||||||
|
||||||||
return NULL(chain.prog_, "struct tcf_proto *") | ||||||||
|
||||||||
|
||||||||
def qdisc_lookup(dev: Object, major: IntegerLike) -> Object: | ||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.".