diff mbox series

[net-next,v2,4/5] net/sched: act_api: conditional notification of events

Message ID 20231204203907.413435-5-pctammela@mojatatu.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series net/sched: conditional notification of events for cls and act | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 1117 this patch: 1117
netdev/cc_maintainers success CCed 7 of 7 maintainers
netdev/build_clang success Errors and warnings before: 1143 this patch: 1143
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 1144 this patch: 1144
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 167 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Pedro Tammela Dec. 4, 2023, 8:39 p.m. UTC
As of today tc-action events are unconditionally built and sent to
RTNLGRP_TC. As with the introduction of tc_should_notify we can check
before-hand if they are really needed.

Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
---
 net/sched/act_api.c | 105 ++++++++++++++++++++++++++++++++------------
 1 file changed, 76 insertions(+), 29 deletions(-)

Comments

Jiri Pirko Dec. 5, 2023, 11:32 a.m. UTC | #1
Mon, Dec 04, 2023 at 09:39:06PM CET, pctammela@mojatatu.com wrote:
>As of today tc-action events are unconditionally built and sent to
>RTNLGRP_TC. As with the introduction of tc_should_notify we can check
>before-hand if they are really needed.
>
>Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
>---
> net/sched/act_api.c | 105 ++++++++++++++++++++++++++++++++------------
> 1 file changed, 76 insertions(+), 29 deletions(-)
>
>diff --git a/net/sched/act_api.c b/net/sched/act_api.c
>index c39252d61ebb..55c62a8e8803 100644
>--- a/net/sched/act_api.c
>+++ b/net/sched/act_api.c
>@@ -1780,31 +1780,45 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[])
> 	return 0;
> }
> 
>-static int
>-tcf_reoffload_del_notify(struct net *net, struct tc_action *action)
>+static struct sk_buff *tcf_reoffload_del_notify_msg(struct net *net,

I wonder, why this new function is needed? If I'm reading things
correctly, tcf_reoffload_del_notify() with added check would be just ok,
woundn't it?

Same for others.

>+						    struct tc_action *action)
> {
> 	size_t attr_size = tcf_action_fill_size(action);
> 	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {
> 		[0] = action,
> 	};
>-	const struct tc_action_ops *ops = action->ops;
> 	struct sk_buff *skb;
>-	int ret;
> 
>-	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
>-			GFP_KERNEL);
>+	skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);

I don't see how this is related to this patch. Can't you do it in separate
patch?

Same for others.

> 	if (!skb)
>-		return -ENOBUFS;
>+		return ERR_PTR(-ENOBUFS);
> 
> 	if (tca_get_fill(skb, actions, 0, 0, 0, RTM_DELACTION, 0, 1, NULL) <= 0) {
> 		kfree_skb(skb);
>-		return -EINVAL;
>+		return ERR_PTR(-EINVAL);
> 	}
> 
>+	return skb;
>+}
>+

[...]
Pedro Tammela Dec. 5, 2023, 2:45 p.m. UTC | #2
On 05/12/2023 08:32, Jiri Pirko wrote:
> Mon, Dec 04, 2023 at 09:39:06PM CET, pctammela@mojatatu.com wrote:
>> As of today tc-action events are unconditionally built and sent to
>> RTNLGRP_TC. As with the introduction of tc_should_notify we can check
>> before-hand if they are really needed.
>>
>> Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
>> ---
>> net/sched/act_api.c | 105 ++++++++++++++++++++++++++++++++------------
>> 1 file changed, 76 insertions(+), 29 deletions(-)
>>
>> diff --git a/net/sched/act_api.c b/net/sched/act_api.c
>> index c39252d61ebb..55c62a8e8803 100644
>> --- a/net/sched/act_api.c
>> +++ b/net/sched/act_api.c
>> @@ -1780,31 +1780,45 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[])
>> 	return 0;
>> }
>>
>> -static int
>> -tcf_reoffload_del_notify(struct net *net, struct tc_action *action)
>> +static struct sk_buff *tcf_reoffload_del_notify_msg(struct net *net,
> 
> I wonder, why this new function is needed? If I'm reading things
> correctly, tcf_reoffload_del_notify() with added check would be just ok,
> woundn't it?
> 
> Same for others.

In V1 we had it like what you are suggesting[1].
Jakub suggested to refactor the functions a bit more. The main argument 
was the code duplication introduced for the delete routines.
Note that for the case that no notification is needed, we still need to 
do the action delete etc...
I agree that code duplication is bad in the long term, so I did the 
changes, but I don't have a strong opinion here (either way is fine for me).
Let's see what he has to say, perhaps I overdid what he was suggesting :)

[1] 
https://lore.kernel.org/all/20231201204314.220543-4-pctammela@mojatatu.com/

> 
>> +						    struct tc_action *action)
>> {
>> 	size_t attr_size = tcf_action_fill_size(action);
>> 	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {
>> 		[0] = action,
>> 	};
>> -	const struct tc_action_ops *ops = action->ops;
>> 	struct sk_buff *skb;
>> -	int ret;
>>
>> -	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
>> -			GFP_KERNEL);
>> +	skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
> 
> I don't see how this is related to this patch. Can't you do it in separate
> patch?
> 
> Same for others.

Sure, will split it out.

> 
>> 	if (!skb)
>> -		return -ENOBUFS;
>> +		return ERR_PTR(-ENOBUFS);
>>
>> 	if (tca_get_fill(skb, actions, 0, 0, 0, RTM_DELACTION, 0, 1, NULL) <= 0) {
>> 		kfree_skb(skb);
>> -		return -EINVAL;
>> +		return ERR_PTR(-EINVAL);
>> 	}
>>
>> +	return skb;
>> +}
>> +
> 
> [...]
Jiri Pirko Dec. 6, 2023, 7:53 a.m. UTC | #3
Tue, Dec 05, 2023 at 03:45:52PM CET, pctammela@mojatatu.com wrote:
>On 05/12/2023 08:32, Jiri Pirko wrote:
>> Mon, Dec 04, 2023 at 09:39:06PM CET, pctammela@mojatatu.com wrote:
>> > As of today tc-action events are unconditionally built and sent to
>> > RTNLGRP_TC. As with the introduction of tc_should_notify we can check
>> > before-hand if they are really needed.
>> > 
>> > Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
>> > ---
>> > net/sched/act_api.c | 105 ++++++++++++++++++++++++++++++++------------
>> > 1 file changed, 76 insertions(+), 29 deletions(-)
>> > 
>> > diff --git a/net/sched/act_api.c b/net/sched/act_api.c
>> > index c39252d61ebb..55c62a8e8803 100644
>> > --- a/net/sched/act_api.c
>> > +++ b/net/sched/act_api.c
>> > @@ -1780,31 +1780,45 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[])
>> > 	return 0;
>> > }
>> > 
>> > -static int
>> > -tcf_reoffload_del_notify(struct net *net, struct tc_action *action)
>> > +static struct sk_buff *tcf_reoffload_del_notify_msg(struct net *net,
>> 
>> I wonder, why this new function is needed? If I'm reading things
>> correctly, tcf_reoffload_del_notify() with added check would be just ok,
>> woundn't it?
>> 
>> Same for others.
>
>In V1 we had it like what you are suggesting[1].
>Jakub suggested to refactor the functions a bit more. The main argument was
>the code duplication introduced for the delete routines.

Okay.

>Note that for the case that no notification is needed, we still need to do
>the action delete etc...
>I agree that code duplication is bad in the long term, so I did the changes,
>but I don't have a strong opinion here (either way is fine for me).
>Let's see what he has to say, perhaps I overdid what he was suggesting :)
>
>[1]
>https://lore.kernel.org/all/20231201204314.220543-4-pctammela@mojatatu.com/
>
>> 
>> > +						    struct tc_action *action)
>> > {
>> > 	size_t attr_size = tcf_action_fill_size(action);
>> > 	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {
>> > 		[0] = action,
>> > 	};
>> > -	const struct tc_action_ops *ops = action->ops;
>> > 	struct sk_buff *skb;
>> > -	int ret;
>> > 
>> > -	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
>> > -			GFP_KERNEL);
>> > +	skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
>> 
>> I don't see how this is related to this patch. Can't you do it in separate
>> patch?
>> 
>> Same for others.
>
>Sure, will split it out.
>
>> 
>> > 	if (!skb)
>> > -		return -ENOBUFS;
>> > +		return ERR_PTR(-ENOBUFS);
>> > 
>> > 	if (tca_get_fill(skb, actions, 0, 0, 0, RTM_DELACTION, 0, 1, NULL) <= 0) {
>> > 		kfree_skb(skb);
>> > -		return -EINVAL;
>> > +		return ERR_PTR(-EINVAL);
>> > 	}
>> > 
>> > +	return skb;
>> > +}
>> > +
>> 
>> [...]
>
diff mbox series

Patch

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index c39252d61ebb..55c62a8e8803 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -1780,31 +1780,45 @@  static int tcf_action_delete(struct net *net, struct tc_action *actions[])
 	return 0;
 }
 
-static int
-tcf_reoffload_del_notify(struct net *net, struct tc_action *action)
+static struct sk_buff *tcf_reoffload_del_notify_msg(struct net *net,
+						    struct tc_action *action)
 {
 	size_t attr_size = tcf_action_fill_size(action);
 	struct tc_action *actions[TCA_ACT_MAX_PRIO] = {
 		[0] = action,
 	};
-	const struct tc_action_ops *ops = action->ops;
 	struct sk_buff *skb;
-	int ret;
 
-	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
-			GFP_KERNEL);
+	skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
 	if (!skb)
-		return -ENOBUFS;
+		return ERR_PTR(-ENOBUFS);
 
 	if (tca_get_fill(skb, actions, 0, 0, 0, RTM_DELACTION, 0, 1, NULL) <= 0) {
 		kfree_skb(skb);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
+	return skb;
+}
+
+static int tcf_reoffload_del_notify(struct net *net, struct tc_action *action)
+{
+	const struct tc_action_ops *ops = action->ops;
+	struct sk_buff *skb = NULL;
+	int ret;
+
+	if (!rtnl_notify_needed(net, 0, RTNLGRP_TC))
+		goto skip_msg;
+
+	skb = tcf_reoffload_del_notify_msg(net, action);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+skip_msg:
 	ret = tcf_idr_release_unsafe(action);
 	if (ret == ACT_P_DELETED) {
 		module_put(ops->owner);
-		ret = rtnetlink_send(skb, net, 0, RTNLGRP_TC, 0);
+		ret = rtnetlink_maybe_send(skb, net, 0, RTNLGRP_TC, 0);
 	} else {
 		kfree_skb(skb);
 	}
@@ -1870,25 +1884,42 @@  int tcf_action_reoffload_cb(flow_indr_block_bind_cb_t *cb,
 	return 0;
 }
 
-static int
-tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
-	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
+static struct sk_buff *tcf_del_notify_msg(struct net *net, struct nlmsghdr *n,
+					  struct tc_action *actions[],
+					  u32 portid, size_t attr_size,
+					  struct netlink_ext_ack *extack)
 {
-	int ret;
 	struct sk_buff *skb;
 
-	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
-			GFP_KERNEL);
+	skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
 	if (!skb)
-		return -ENOBUFS;
+		return ERR_PTR(-ENOBUFS);
 
 	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
 			 0, 2, extack) <= 0) {
 		NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes");
 		kfree_skb(skb);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
+	return skb;
+}
+
+static int tcf_del_notify(struct net *net, struct nlmsghdr *n,
+			  struct tc_action *actions[], u32 portid,
+			  size_t attr_size, struct netlink_ext_ack *extack)
+{
+	struct sk_buff *skb = NULL;
+	int ret;
+
+	if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC))
+		goto skip_msg;
+
+	skb = tcf_del_notify_msg(net, n, actions, portid, attr_size, extack);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+skip_msg:
 	/* now do the delete */
 	ret = tcf_action_delete(net, actions);
 	if (ret < 0) {
@@ -1897,9 +1928,8 @@  tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
 		return ret;
 	}
 
-	ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
-			     n->nlmsg_flags & NLM_F_ECHO);
-	return ret;
+	return rtnetlink_maybe_send(skb, net, portid, RTNLGRP_TC,
+				    n->nlmsg_flags & NLM_F_ECHO);
 }
 
 static int
@@ -1950,26 +1980,43 @@  tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
 	return ret;
 }
 
-static int
-tcf_add_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
-	       u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
+static struct sk_buff *tcf_add_notify_msg(struct net *net, struct nlmsghdr *n,
+					  struct tc_action *actions[],
+					  u32 portid, size_t attr_size,
+					  struct netlink_ext_ack *extack)
 {
 	struct sk_buff *skb;
 
-	skb = alloc_skb(attr_size <= NLMSG_GOODSIZE ? NLMSG_GOODSIZE : attr_size,
-			GFP_KERNEL);
+	skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
 	if (!skb)
-		return -ENOBUFS;
+		return ERR_PTR(-ENOBUFS);
 
 	if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
 			 RTM_NEWACTION, 0, 0, extack) <= 0) {
 		NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
 		kfree_skb(skb);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 
-	return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
-			      n->nlmsg_flags & NLM_F_ECHO);
+	return skb;
+}
+
+static int tcf_add_notify(struct net *net, struct nlmsghdr *n,
+			  struct tc_action *actions[], u32 portid,
+			  size_t attr_size, struct netlink_ext_ack *extack)
+{
+	struct sk_buff *skb = NULL;
+
+	if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC))
+		goto skip_msg;
+
+	skb = tcf_add_notify_msg(net, n, actions, portid, attr_size, extack);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+skip_msg:
+	return rtnetlink_maybe_send(skb, net, portid, RTNLGRP_TC,
+				    n->nlmsg_flags & NLM_F_ECHO);
 }
 
 static int tcf_action_add(struct net *net, struct nlattr *nla,