net/sched: sch_api: conditional netlink notifications
Implement conditional netlink notifications for Qdiscs and classes, which were missing in the initial patches that targeted tc filters and actions. Notifications will only be built after passing a check for 'rtnl_notify_needed()'. For both Qdiscs and classes 'get' operations now call a dedicated notification function as it was not possible to distinguish between 'create' and 'get' before. This distinction is necessary because 'get' always send a notification. Signed-off-by: Pedro Tammela <pctammela@mojatatu.com> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Link: https://lore.kernel.org/r/20231229132642.1489088-2-pctammela@mojatatu.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
c2a67de9bb
commit
530496985c
@ -1003,6 +1003,32 @@ static bool tc_qdisc_dump_ignore(struct Qdisc *q, bool dump_invisible)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int qdisc_get_notify(struct net *net, struct sk_buff *oskb,
|
||||
struct nlmsghdr *n, u32 clid, struct Qdisc *q,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
|
||||
|
||||
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (!tc_qdisc_dump_ignore(q, false)) {
|
||||
if (tc_fill_qdisc(skb, q, clid, portid, n->nlmsg_seq, 0,
|
||||
RTM_NEWQDISC, extack) < 0)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (skb->len)
|
||||
return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
|
||||
n->nlmsg_flags & NLM_F_ECHO);
|
||||
|
||||
err_out:
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int qdisc_notify(struct net *net, struct sk_buff *oskb,
|
||||
struct nlmsghdr *n, u32 clid,
|
||||
struct Qdisc *old, struct Qdisc *new,
|
||||
@ -1011,6 +1037,9 @@ static int qdisc_notify(struct net *net, struct sk_buff *oskb,
|
||||
struct sk_buff *skb;
|
||||
u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
|
||||
|
||||
if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC))
|
||||
return 0;
|
||||
|
||||
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOBUFS;
|
||||
@ -1583,7 +1612,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
|
||||
if (err != 0)
|
||||
return err;
|
||||
} else {
|
||||
qdisc_notify(net, skb, n, clid, NULL, q, NULL);
|
||||
qdisc_get_notify(net, skb, n, clid, q, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1977,6 +2006,9 @@ static int tclass_notify(struct net *net, struct sk_buff *oskb,
|
||||
struct sk_buff *skb;
|
||||
u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
|
||||
|
||||
if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC))
|
||||
return 0;
|
||||
|
||||
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOBUFS;
|
||||
@ -1990,6 +2022,27 @@ static int tclass_notify(struct net *net, struct sk_buff *oskb,
|
||||
n->nlmsg_flags & NLM_F_ECHO);
|
||||
}
|
||||
|
||||
static int tclass_get_notify(struct net *net, struct sk_buff *oskb,
|
||||
struct nlmsghdr *n, struct Qdisc *q,
|
||||
unsigned long cl, struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
u32 portid = oskb ? NETLINK_CB(oskb).portid : 0;
|
||||
|
||||
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (tc_fill_tclass(skb, q, cl, portid, n->nlmsg_seq, 0, RTM_NEWTCLASS,
|
||||
extack) < 0) {
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rtnetlink_send(skb, net, portid, RTNLGRP_TC,
|
||||
n->nlmsg_flags & NLM_F_ECHO);
|
||||
}
|
||||
|
||||
static int tclass_del_notify(struct net *net,
|
||||
const struct Qdisc_class_ops *cops,
|
||||
struct sk_buff *oskb, struct nlmsghdr *n,
|
||||
@ -2003,14 +2056,18 @@ static int tclass_del_notify(struct net *net,
|
||||
if (!cops->delete)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOBUFS;
|
||||
if (rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC)) {
|
||||
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (tc_fill_tclass(skb, q, cl, portid, n->nlmsg_seq, 0,
|
||||
RTM_DELTCLASS, extack) < 0) {
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
if (tc_fill_tclass(skb, q, cl, portid, n->nlmsg_seq, 0,
|
||||
RTM_DELTCLASS, extack) < 0) {
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
skb = NULL;
|
||||
}
|
||||
|
||||
err = cops->delete(q, cl, extack);
|
||||
@ -2019,8 +2076,8 @@ static int tclass_del_notify(struct net *net,
|
||||
return err;
|
||||
}
|
||||
|
||||
err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
|
||||
n->nlmsg_flags & NLM_F_ECHO);
|
||||
err = rtnetlink_maybe_send(skb, net, portid, RTNLGRP_TC,
|
||||
n->nlmsg_flags & NLM_F_ECHO);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -2215,7 +2272,7 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n,
|
||||
tc_bind_tclass(q, portid, clid, 0);
|
||||
goto out;
|
||||
case RTM_GETTCLASS:
|
||||
err = tclass_notify(net, skb, n, q, cl, RTM_NEWTCLASS, extack);
|
||||
err = tclass_get_notify(net, skb, n, q, cl, extack);
|
||||
goto out;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user