-
Notifications
You must be signed in to change notification settings - Fork 50
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
tc actions support #122
tc actions support #122
Conversation
522f60e
to
4dfa69e
Compare
I'm moving this out of draft state now because I think it can now be meaningfully reviewed. I will work on squashing the remaining tiny TODO involving documentation, making sure all the doc links work correctly, and the other notes I left for myself. I will be very surprised if addressing any of those significantly change the code. As things stand I
in addition to what is described in the issue.
|
4e99be4
to
902ac77
Compare
I also made a slight amendment to the testing pattern by
I am happy to adapt that back into the existing testing pattern with hard coded |
134c77f
to
524578e
Compare
3c5c87d
to
fb346b9
Compare
# Summary of feature This is easiest to explain by way of iproute2. `tc` allows actions to be created independently of filters. Once created, these actions may then 1. be associated with _zero or more_ filters, 2. live updated (and updates will be seen by all filters using that action), 3. be deleted (only after all filters using that action have been deleted). For example, consider the following : ```bash for i in x y z; do ip link add dev "$i" type dummy tc qdisc add dev "$i" clsact done tc actions add action mirred egress redirect dev y tc actions add action gact drop ``` At this point, we could 1. list the `mirred` actions ```bash $ tc actions list action mirred total acts 1 action order 0: mirred (Egress Redirect to device y) stolen index 1 ref 1 bind 0 not_in_hw used_hw_stats disabled ``` 2. list the `gact` actions ```bash $ tc actions list action gact total acts 1 action order 0: gact action drop random type none pass val 0 index 1 ref 1 bind 0 not_in_hw used_hw_stats disabled ``` 3. create any number of filters using either or both of these actions by index ```bash tc filter add dev x ingress pref 1000 proto ip flower dst_ip 8.8.8.8 action mirred index 1 tc filter add dev z ingress pref 1000 proto ip flower dst_ip 8.8.8.8 action mirred index 1 action gact index 1 ``` 4. display those filters as normal (with per-action statistics) ```bash $ tc -s filter show dev z ingress filter protocol ip pref 1000 flower chain 0 filter protocol ip pref 1000 flower chain 0 handle 0x1 eth_type ipv4 dst_ip 8.8.8.8 not_in_hw action order 1: mirred (Egress Redirect to device y) stolen index 1 ref 3 bind 2 installed 599 sec used 599 sec Action statistics: Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 action order 2: gact action drop random type none pass val 0 index 1 ref 2 bind 1 installed 599 sec used 599 sec Action statistics: Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 ``` 5. centrally update those actions (e.g., change `drop` to `pass`) ```bash $ tc actions change action gact pass index 1 $ tc -s filter show dev z ingress filter protocol ip pref 1000 flower chain 0 filter protocol ip pref 1000 flower chain 0 handle 0x1 eth_type ipv4 dst_ip 8.8.8.8 not_in_hw action order 1: mirred (Egress Redirect to device y) stolen index 1 ref 3 bind 2 installed 838 sec used 838 sec Action statistics: Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 action order 2: gact action pass random type none pass val 0 index 1 ref 2 bind 1 installed 838 sec used 838 sec Action statistics: Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) backlog 0b 0p requeues 0 ``` 6. attempts to delete those actions while in use will be rejected (albeit with a buggy error message from `iproute2`/`tc`) ```bash $ tc actions delete action gact index 1 Error: Failed to delete TC action. We have an error talking to the kernel Command "action" is unknown, try "tc actions help" ``` 7. Removing all filters that use an action will allow the action to be deleted ```bash $ tc filter del dev z ingress pref 1000 $ tc actions delete action gact index 1 $ tc filter del dev x ingress pref 1000 $ tc actions delete action mirred index 1 ```
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.
Thanks for your documentation.
The unit tests is nice too.
&TcActionMessageBuffer::new_checked(&buf.inner()) | ||
.context(err)?, | ||
) | ||
.context(err)?; |
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.
Is context
required, if only return errors to caller. Or write some context message?
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.
good catch. No idea how that got there. Will fix
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.
It looks like I was just following an existing pattern when I did this?
If we change this pattern here we should likely change this pattern for all the other arms to remain consistent.
Thoughts?
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.
It's ok to keep origin pattern.
But the context
is used to trace error path. I haven't tried what context(err)
behaves like.
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.
Ok. Then I suggest we leave it as is for now.
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.
The use of anyhow need to be debated in another PR or issue. I don't like anyhow, but let's follow the precedent
Thank you for the review 😄 I will write fixups based on your comments. If you think that flavor of unit tests is helpful (as I do, see #121) then we may also consider something like proptest or bolero to really expand on that "parse-back" strategy. It may also be worth looking at the rather unfortunate state of the higher level API this PR results in (see rust-netlink/rtnetlink#64) before we agree to merge this. This segment of test code is especially unfortunate This segment of test code is almost as sad I have thoughts about what can be done to fix this. Thanks again 🎉 |
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.
Besides the lints I mentioned, all looks good to me.
We have document in README.md for capture netlink data and convert it into Vec, which could be better than decode a long string.
src/tc/actions/action.rs
Outdated
// This is heuristically trying to match the kernel's behavior | ||
// but may not be correct. | ||
if opts.len() == 1 { | ||
TCA_ACT_OPTIONS | NLA_F_NESTED |
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.
In kernel we have
static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = {
[TCA_ACT_KIND] = { .type = NLA_STRING },
[TCA_ACT_INDEX] = { .type = NLA_U32 },
[TCA_ACT_COOKIE] = { .type = NLA_BINARY,
.len = TC_COOKIE_MAX_SIZE },
[TCA_ACT_OPTIONS] = { .type = NLA_NESTED },
And nest = nla_nest_start_noflag(skb, TCA_ACT_OPTIONS);
.
So it should always carry with NLA_F_NESTED
.
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.
Ah, it must be iproute2 just being wrong sometimes. I will change our code to always set NLA_F_NESTED
src/tc/actions/message.rs
Outdated
/// All dump responses will contain the number of actions being dumped | ||
/// stored in for user app's consumption in TCA_ROOT_COUNT | ||
/// | ||
/// [`rtnetlink.h`]: https://github.com/iproute2/iproute2/blob/89210b9ec1c445ae963d181b5816d12a0cdafbb6/include/uapi/linux/rtnetlink.h#L803-L806 |
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.
Those link might not accessible in the future. No need to mention it.
iproute2 might be the de-factor netlink client, but I prefer explains stuff using kernel codes or function name.
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.
Ok. Will fix.
@@ -1,164 +0,0 @@ | |||
// SPDX-License-Identifier: MIT |
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.
Why this file is removed instead of amended?
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.
Hmm, I thought I moved the contents of this file into the same file as the other nat tests.
Likely that change was messed up in a rebase. Will fix.
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.
The test in this file has been moved now. It lives with the rest of the NAT tests
If you find it hard to capture netlink package as Vec, please let me know, I am happy to amend(and also validate) your test codes. |
I can capture as a |
Feedback responses posted. Summary of changes:
Will mark as ready for next review. I left the review response fixups as the last commit in this series to make review easier. I'm happy to squash that commit into the prior one before merge if you wish to keep the commit history clean |
Summary of changes: 1. adjust use of `NLA_F_NESTED` flag in both tests and emitted messages to reflect the kernel's stated usage (i.e. that `NLA_F_NESTED` be set for the tc-actions options). This required adjusting the tests which seem to have captured iproute2's incorrectly formed messages (iproute2 does not always set the `NLA_F_NESTED` flag) 2. Remove the use of hex as a dev dependency and use a const slice of `u8` instead as per @cathay4t request 3. remove links to iproute2's github as per @cathay4t request 4. trivial documentation cleanup 5. restore previously deleted test
Any update on this? |
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.
Nicely done!
Support for tc-actions
Add the building blocks for tc-actions support.
This PR is in the same spirit as my (in progress) work on florianl/go-tc#145
I broke out this functionality from my other PR #111 based on conversation and feedback from @cathay4t.
Summary of feature
This is easiest to explain by way of iproute2.
tc
allows actions to be created independently of filters.Once created, these actions may then
For example, consider the following :
At this point, we could
list the
mirred
actions$ tc actions list action mirred total acts 1 action order 0: mirred (Egress Redirect to device y) stolen index 1 ref 1 bind 0 not_in_hw used_hw_stats disabled
list the
gact
actionscreate any number of filters using either or both of these actions by index
display those filters as normal (with per-action statistics)
centrally update those actions (e.g., change
drop
topass
)attempts to delete those actions while in use will be rejected (albeit with a buggy error message from
iproute2
/tc
)Removing all filters that use an action will allow the action to be deleted