Merge branch 'notify-user-space-if-any-actions-were-flushed-before-error'

Victor Nogueira says:

====================
Notify user space if any actions were flushed before error

This patch series fixes the behaviour of actions flush so that the
kernel always notifies user space whenever it deletes actions during a
flush operation, even if it didn't flush all the actions. This series
also introduces tdc tests to verify this new behaviour.
====================

Link: https://lore.kernel.org/r/20220623140742.684043-1-victor@mojatatu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2022-06-27 21:51:29 -07:00
commit cce13b82cf
2 changed files with 91 additions and 8 deletions
net/sched
tools/testing/selftests/tc-testing/tc-tests/actions

View File

@ -588,7 +588,8 @@ static int tcf_idr_release_unsafe(struct tc_action *p)
} }
static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
const struct tc_action_ops *ops) const struct tc_action_ops *ops,
struct netlink_ext_ack *extack)
{ {
struct nlattr *nest; struct nlattr *nest;
int n_i = 0; int n_i = 0;
@ -604,20 +605,25 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
if (nla_put_string(skb, TCA_KIND, ops->kind)) if (nla_put_string(skb, TCA_KIND, ops->kind))
goto nla_put_failure; goto nla_put_failure;
ret = 0;
mutex_lock(&idrinfo->lock); mutex_lock(&idrinfo->lock);
idr_for_each_entry_ul(idr, p, tmp, id) { idr_for_each_entry_ul(idr, p, tmp, id) {
if (IS_ERR(p)) if (IS_ERR(p))
continue; continue;
ret = tcf_idr_release_unsafe(p); ret = tcf_idr_release_unsafe(p);
if (ret == ACT_P_DELETED) { if (ret == ACT_P_DELETED)
module_put(ops->owner); module_put(ops->owner);
n_i++; else if (ret < 0)
} else if (ret < 0) { break;
mutex_unlock(&idrinfo->lock); n_i++;
goto nla_put_failure;
}
} }
mutex_unlock(&idrinfo->lock); mutex_unlock(&idrinfo->lock);
if (ret < 0) {
if (n_i)
NL_SET_ERR_MSG(extack, "Unable to flush all TC actions");
else
goto nla_put_failure;
}
ret = nla_put_u32(skb, TCA_FCNT, n_i); ret = nla_put_u32(skb, TCA_FCNT, n_i);
if (ret) if (ret)
@ -638,7 +644,7 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct tcf_idrinfo *idrinfo = tn->idrinfo; struct tcf_idrinfo *idrinfo = tn->idrinfo;
if (type == RTM_DELACTION) { if (type == RTM_DELACTION) {
return tcf_del_walker(idrinfo, skb, ops); return tcf_del_walker(idrinfo, skb, ops, extack);
} else if (type == RTM_GETACTION) { } else if (type == RTM_GETACTION) {
return tcf_dump_walker(idrinfo, skb, cb); return tcf_dump_walker(idrinfo, skb, cb);
} else { } else {

View File

@ -609,5 +609,82 @@
"teardown": [ "teardown": [
"$TC actions flush action gact" "$TC actions flush action gact"
] ]
},
{
"id": "7f52",
"name": "Try to flush action which is referenced by filter",
"category": [
"actions",
"gact"
],
"plugins": {
"requires": "nsPlugin"
},
"setup": [
[
"$TC actions flush action gact",
0,
1,
255
],
"$TC qdisc add dev $DEV1 ingress",
"$TC actions add action pass index 1",
"$TC filter add dev $DEV1 protocol all ingress prio 1 handle 0x1234 matchall action gact index 1"
],
"cmdUnderTest": "$TC actions flush action gact",
"expExitCode": "1",
"verifyCmd": "$TC actions ls action gact",
"matchPattern": "total acts 1.*action order [0-9]*: gact action pass.*index 1 ref 2 bind 1",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DEV1 ingress",
[
"sleep 1; $TC actions flush action gact",
0,
1
]
]
},
{
"id": "ae1e",
"name": "Try to flush actions when last one is referenced by filter",
"category": [
"actions",
"gact"
],
"plugins": {
"requires": "nsPlugin"
},
"setup": [
[
"$TC actions flush action gact",
0,
1,
255
],
"$TC qdisc add dev $DEV1 ingress",
[
"$TC actions add action pass index 1",
0,
1,
255
],
"$TC actions add action reclassify index 2",
"$TC actions add action drop index 3",
"$TC filter add dev $DEV1 protocol all ingress prio 1 handle 0x1234 matchall action gact index 3"
],
"cmdUnderTest": "$TC actions flush action gact",
"expExitCode": "0",
"verifyCmd": "$TC actions ls action gact",
"matchPattern": "total acts 1.*action order [0-9]*: gact action drop.*index 3 ref 2 bind 1",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DEV1 ingress",
[
"sleep 1; $TC actions flush action gact",
0,
1
]
]
} }
] ]