mirror of
https://github.com/torvalds/linux.git
synced 2026-09-11 20:13:02 +02:00
Merge branch 'net-sched-fix-remaining-actions-notification-accounting-issues'
Victor Nogueira says:
====================
net/sched: Fix remaining actions notification accounting issues
Commit 8e2efb3f45 ("net/sched: add get_fill_size callbacks for actions
missing them") fixed the reported echo/notify skb overrun and noted that
the pre-existing issues Sashiko pointed out [1] would be fixed separately.
This is that series.
Patch 1 makes tcf_action_shared_attrs_size() a real upper bound again.
TCA_ACT_IN_HW_COUNT and TCA_STATS_BASIC_HW are emitted on every action
dump and were never budgeted; TCA_STATS_PKT64 was budgeted once but can be
emitted twice; TCA_ACT_USED_HW_STATS and the rate estimator attributes are
conditional and also unaccounted.
Patch 2 makes the RTM_GETACTION path use the attr_size that tca_action_gd()
already computes and then throws away, so that "tc actions get" can read
back an action whose dump is larger than NLMSG_GOODSIZE.
Patch 3 wraps the reoffload delete notification in
tcf_action_full_attrs_size() like every other notification path, and stops
leaving a skip_sw action installed when that notification cannot be built.
[1] https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260810164357.1653956-1-victor%40mojatatu.com
====================
Link: https://patch.msgid.link/20260824153903.4143642-1-victor@mojatatu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
7e1d6caa9c
|
|
@ -443,12 +443,21 @@ static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
|
|||
+ nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */
|
||||
+ cookie_len /* TCA_ACT_COOKIE */
|
||||
+ nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_HW_STATS */
|
||||
/* TCA_ACT_USED_HW_STATS */
|
||||
+ nla_total_size(sizeof(struct nla_bitfield32))
|
||||
+ nla_total_size(sizeof(u32)) /* TCA_ACT_IN_HW_COUNT */
|
||||
+ nla_total_size(0) /* TCA_ACT_STATS nested */
|
||||
+ nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_FLAGS */
|
||||
/* TCA_STATS_BASIC */
|
||||
+ nla_total_size_64bit(sizeof(struct gnet_stats_basic))
|
||||
/* TCA_STATS_PKT64 */
|
||||
+ nla_total_size_64bit(sizeof(u64))
|
||||
/* TCA_STATS_BASIC_HW */
|
||||
+ nla_total_size_64bit(sizeof(struct gnet_stats_basic))
|
||||
/* TCA_STATS_PKT64, emitted by both of the basic copies above */
|
||||
+ 2 * nla_total_size_64bit(sizeof(u64))
|
||||
/* TCA_STATS_RATE_EST */
|
||||
+ nla_total_size_64bit(sizeof(struct gnet_stats_rate_est))
|
||||
/* TCA_STATS_RATE_EST64 */
|
||||
+ nla_total_size_64bit(sizeof(struct gnet_stats_rate_est64))
|
||||
/* TCA_STATS_QUEUE */
|
||||
+ nla_total_size_64bit(sizeof(struct gnet_stats_queue))
|
||||
+ nla_total_size(0) /* TCA_ACT_OPTIONS nested */
|
||||
|
|
@ -1688,12 +1697,12 @@ static int tca_get_fill(struct sk_buff *skb, struct tc_action *actions[],
|
|||
|
||||
static int
|
||||
tcf_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
|
||||
struct tc_action *actions[], int event,
|
||||
struct tc_action *actions[], size_t attr_size, int event,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
||||
skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOBUFS;
|
||||
if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event,
|
||||
|
|
@ -1858,11 +1867,13 @@ static int tcf_action_delete(struct net *net, struct tc_action *actions[])
|
|||
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;
|
||||
size_t attr_size;
|
||||
|
||||
attr_size = tcf_action_full_attrs_size(tcf_action_fill_size(action));
|
||||
|
||||
skb = alloc_skb(max(attr_size, NLMSG_GOODSIZE), GFP_KERNEL);
|
||||
if (!skb)
|
||||
|
|
@ -1879,15 +1890,18 @@ static struct sk_buff *tcf_reoffload_del_notify_msg(struct net *net,
|
|||
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;
|
||||
struct sk_buff *skb = NULL;
|
||||
int ret;
|
||||
|
||||
if (!rtnl_notify_needed(net, 0, RTNLGRP_TC)) {
|
||||
skb = NULL;
|
||||
} else {
|
||||
if (rtnl_notify_needed(net, 0, RTNLGRP_TC)) {
|
||||
skb = tcf_reoffload_del_notify_msg(net, action);
|
||||
/* The action has already lost its hardware instance and is
|
||||
* skip_sw, so it must be released whether or not the
|
||||
* notification can be built. Drop the notification rather
|
||||
* than leave an action behind that processes no packets.
|
||||
*/
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
skb = NULL;
|
||||
}
|
||||
|
||||
ret = tcf_idr_release_unsafe(action);
|
||||
|
|
@ -2044,7 +2058,8 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
|
|||
attr_size = tcf_action_full_attrs_size(attr_size);
|
||||
|
||||
if (event == RTM_GETACTION)
|
||||
ret = tcf_get_notify(net, portid, n, actions, event, extack);
|
||||
ret = tcf_get_notify(net, portid, n, actions, attr_size, event,
|
||||
extack);
|
||||
else { /* delete */
|
||||
ret = tcf_del_notify(net, n, actions, portid, attr_size, extack);
|
||||
if (ret)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user