net/sched: act_api: conditional notification of events
authorPedro Tammela <pctammela@mojatatu.com>
Fri, 8 Dec 2023 19:28:45 +0000 (16:28 -0300)
committerJakub Kicinski <kuba@kernel.org>
Tue, 12 Dec 2023 02:52:57 +0000 (18:52 -0800)
As of today tc-action events are unconditionally built and sent to
RTNLGRP_TC. As with the introduction of rtnl_notify_needed we can check
before-hand if they are really needed.

Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Link: https://lore.kernel.org/r/20231208192847.714940-6-pctammela@mojatatu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/sched/act_api.c

index 4f295ae4e152e2bb508cfa2fd6306f52739612c5..6611f292b6cb71b3faed87a39f041cd15dc6e166 100644 (file)
@@ -1785,30 +1785,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(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;
+       int ret;
+
+       if (!rtnl_notify_needed(net, 0, RTNLGRP_TC)) {
+               skb = NULL;
+       } else {
+               skb = tcf_reoffload_del_notify_msg(net, action);
+               if (IS_ERR(skb))
+                       return PTR_ERR(skb);
        }
 
        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);
        }
@@ -1874,22 +1889,41 @@ 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(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;
+       int ret;
+
+       if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC)) {
+               skb = NULL;
+       } else {
+               skb = tcf_del_notify_msg(net, n, actions, portid, attr_size,
+                                        extack);
+               if (IS_ERR(skb))
+                       return PTR_ERR(skb);
        }
 
        /* now do the delete */
@@ -1900,9 +1934,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
@@ -1953,25 +1986,44 @@ err:
        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(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 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;
+
+       if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC)) {
+               skb = NULL;
+       } else {
+               skb = tcf_add_notify_msg(net, n, actions, portid, attr_size,
+                                        extack);
+               if (IS_ERR(skb))
+                       return PTR_ERR(skb);
        }
 
-       return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
-                             n->nlmsg_flags & NLM_F_ECHO);
+       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,