Commit 8d4390f5 authored by Pedro Tammela's avatar Pedro Tammela Committed by Jakub Kicinski

net/sched: act_api: conditional notification of events

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: default avatarPedro Tammela <pctammela@mojatatu.com>
Reviewed-by: default avatarJiri Pirko <jiri@nvidia.com>
Link: https://lore.kernel.org/r/20231208192847.714940-6-pctammela@mojatatu.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent c73724bf
...@@ -1785,30 +1785,45 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[]) ...@@ -1785,30 +1785,45 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[])
return 0; return 0;
} }
static int static struct sk_buff *tcf_reoffload_del_notify_msg(struct net *net,
tcf_reoffload_del_notify(struct net *net, struct tc_action *action) struct tc_action *action)
{ {
size_t attr_size = tcf_action_fill_size(action); size_t attr_size = tcf_action_fill_size(action);
struct tc_action *actions[TCA_ACT_MAX_PRIO] = { struct tc_action *actions[TCA_ACT_MAX_PRIO] = {
[0] = action, [0] = action,
}; };
const struct tc_action_ops *ops = action->ops;
struct sk_buff *skb; struct sk_buff *skb;
int ret;
skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL); skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
if (!skb) if (!skb)
return -ENOBUFS; return ERR_PTR(-ENOBUFS);
if (tca_get_fill(skb, actions, 0, 0, 0, RTM_DELACTION, 0, 1, NULL) <= 0) { if (tca_get_fill(skb, actions, 0, 0, 0, RTM_DELACTION, 0, 1, NULL) <= 0) {
kfree_skb(skb); 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); ret = tcf_idr_release_unsafe(action);
if (ret == ACT_P_DELETED) { if (ret == ACT_P_DELETED) {
module_put(ops->owner); module_put(ops->owner);
ret = rtnetlink_send(skb, net, 0, RTNLGRP_TC, 0); ret = rtnetlink_maybe_send(skb, net, 0, RTNLGRP_TC, 0);
} else { } else {
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -1874,22 +1889,41 @@ int tcf_action_reoffload_cb(flow_indr_block_bind_cb_t *cb, ...@@ -1874,22 +1889,41 @@ int tcf_action_reoffload_cb(flow_indr_block_bind_cb_t *cb,
return 0; return 0;
} }
static int static struct sk_buff *tcf_del_notify_msg(struct net *net, struct nlmsghdr *n,
tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[], struct tc_action *actions[],
u32 portid, size_t attr_size, struct netlink_ext_ack *extack) u32 portid, size_t attr_size,
struct netlink_ext_ack *extack)
{ {
int ret;
struct sk_buff *skb; struct sk_buff *skb;
skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL); skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
if (!skb) if (!skb)
return -ENOBUFS; return ERR_PTR(-ENOBUFS);
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION, if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION,
0, 2, extack) <= 0) { 0, 2, extack) <= 0) {
NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes"); NL_SET_ERR_MSG(extack, "Failed to fill netlink TC action attributes");
kfree_skb(skb); 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 */ /* now do the delete */
...@@ -1900,9 +1934,8 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[], ...@@ -1900,9 +1934,8 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
return ret; return ret;
} }
ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC, return rtnetlink_maybe_send(skb, net, portid, RTNLGRP_TC,
n->nlmsg_flags & NLM_F_ECHO); n->nlmsg_flags & NLM_F_ECHO);
return ret;
} }
static int static int
...@@ -1953,25 +1986,44 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n, ...@@ -1953,25 +1986,44 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
return ret; return ret;
} }
static int static struct sk_buff *tcf_add_notify_msg(struct net *net, struct nlmsghdr *n,
tcf_add_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[], struct tc_action *actions[],
u32 portid, size_t attr_size, struct netlink_ext_ack *extack) u32 portid, size_t attr_size,
struct netlink_ext_ack *extack)
{ {
struct sk_buff *skb; struct sk_buff *skb;
skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL); skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
if (!skb) if (!skb)
return -ENOBUFS; return ERR_PTR(-ENOBUFS);
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags, if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags,
RTM_NEWACTION, 0, 0, extack) <= 0) { RTM_NEWACTION, 0, 0, extack) <= 0) {
NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action"); NL_SET_ERR_MSG(extack, "Failed to fill netlink attributes while adding TC action");
kfree_skb(skb); 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, return rtnetlink_maybe_send(skb, net, portid, RTNLGRP_TC,
n->nlmsg_flags & NLM_F_ECHO); n->nlmsg_flags & NLM_F_ECHO);
} }
static int tcf_action_add(struct net *net, struct nlattr *nla, static int tcf_action_add(struct net *net, struct nlattr *nla,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment