Message ID | 20231229132642.1489088-2-pctammela@mojatatu.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 530496985ceae54b78c301baf7819eac0012d0f8 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net-next] net/sched: sch_api: conditional netlink notifications | expand |
On Fri, Dec 29, 2023 at 8:27 AM Pedro Tammela <pctammela@mojatatu.com> wrote: > > 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> cheers, jamal > --- > net/sched/sch_api.c | 79 ++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 68 insertions(+), 11 deletions(-) > > diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c > index 299086bb6205..2a2a48838eb9 100644 > --- a/net/sched/sch_api.c > +++ b/net/sched/sch_api.c > @@ -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; > -- > 2.40.1 >
Hello: This patch was applied to netdev/net-next.git (main) by Jakub Kicinski <kuba@kernel.org>: On Fri, 29 Dec 2023 10:26:42 -0300 you wrote: > 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. > > [...] Here is the summary with links: - [net-next] net/sched: sch_api: conditional netlink notifications https://git.kernel.org/netdev/net-next/c/530496985cea You are awesome, thank you!
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 299086bb6205..2a2a48838eb9 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -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;
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> --- net/sched/sch_api.c | 79 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 11 deletions(-)