mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 13:41:51 +00:00
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: 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>
This commit is contained in:
parent
c73724bfde
commit
8d4390f519
@ -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,
|
||||
};
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOBUFS);
|
||||
|
||||
if (tca_get_fill(skb, actions, 0, 0, 0, RTM_DELACTION, 0, 1, NULL) <= 0) {
|
||||
kfree_skb(skb);
|
||||
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;
|
||||
|
||||
skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (tca_get_fill(skb, actions, 0, 0, 0, RTM_DELACTION, 0, 1, NULL) <= 0) {
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
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 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;
|
||||
|
||||
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_maybe_send(skb, net, portid, RTNLGRP_TC,
|
||||
n->nlmsg_flags & NLM_F_ECHO);
|
||||
}
|
||||
|
||||
static int tcf_action_add(struct net *net, struct nlattr *nla,
|
||||
|
Loading…
Reference in New Issue
Block a user