Skip to content

Commit

Permalink
net: sched: wrap doit/dumpit methods
Browse files Browse the repository at this point in the history
In preparation for grabbing netdev instance lock around qdisc
operations, introduce tc_xxx wrappers that lookup netdev
and call respective __tc_xxx helper to do the actual work.
No functional changes.

Cc: Cong Wang <xiyou.wangcong@gmail.com>
Cc: Jiri Pirko <jiri@resnulli.us>
Cc: Saeed Mahameed <saeed@kernel.org>
Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Stanislav Fomichev <sdf@fomichev.me>
Link: https://patch.msgid.link/20250305163732.2766420-4-sdf@fomichev.me
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Stanislav Fomichev authored and Jakub Kicinski committed Mar 6, 2025
1 parent c4f0f30 commit 7c79cff
Showing 1 changed file with 123 additions and 68 deletions.
191 changes: 123 additions & 68 deletions net/sched/sch_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1505,27 +1505,18 @@ const struct nla_policy rtm_tca_policy[TCA_MAX + 1] = {
* Delete/get qdisc.
*/

static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack)
static int __tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack,
struct net_device *dev,
struct nlattr *tca[TCA_MAX + 1],
struct tcmsg *tcm)
{
struct net *net = sock_net(skb->sk);
struct tcmsg *tcm = nlmsg_data(n);
struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
u32 clid;
struct Qdisc *q = NULL;
struct Qdisc *p = NULL;
u32 clid;
int err;

err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
rtm_tca_policy, extack);
if (err < 0)
return err;

dev = __dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return -ENODEV;

clid = tcm->tcm_parent;
if (clid) {
if (clid != TC_H_ROOT) {
Expand Down Expand Up @@ -1582,6 +1573,27 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
return 0;
}

static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack)
{
struct net *net = sock_net(skb->sk);
struct tcmsg *tcm = nlmsg_data(n);
struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
int err;

err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
rtm_tca_policy, extack);
if (err < 0)
return err;

dev = __dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return -ENODEV;

return __tc_get_qdisc(skb, n, extack, dev, tca, tcm);
}

static bool req_create_or_replace(struct nlmsghdr *n)
{
return (n->nlmsg_flags & NLM_F_CREATE &&
Expand All @@ -1601,35 +1613,19 @@ static bool req_change(struct nlmsghdr *n)
!(n->nlmsg_flags & NLM_F_EXCL));
}

/*
* Create/change qdisc.
*/
static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack)
static int __tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack,
struct net_device *dev,
struct nlattr *tca[TCA_MAX + 1],
struct tcmsg *tcm,
bool *replay)
{
struct net *net = sock_net(skb->sk);
struct tcmsg *tcm;
struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
struct Qdisc *q = NULL;
struct Qdisc *p = NULL;
u32 clid;
struct Qdisc *q, *p;
int err;

replay:
/* Reinit, just in case something touches this. */
err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
rtm_tca_policy, extack);
if (err < 0)
return err;

tcm = nlmsg_data(n);
clid = tcm->tcm_parent;
q = p = NULL;

dev = __dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return -ENODEV;


if (clid) {
if (clid != TC_H_ROOT) {
Expand Down Expand Up @@ -1755,7 +1751,7 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
}
err = qdisc_change(q, tca, extack);
if (err == 0)
qdisc_notify(net, skb, n, clid, NULL, q, extack);
qdisc_notify(sock_net(skb->sk), skb, n, clid, NULL, q, extack);
return err;

create_n_graft:
Expand Down Expand Up @@ -1788,8 +1784,10 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
tca, &err, extack);
}
if (q == NULL) {
if (err == -EAGAIN)
goto replay;
if (err == -EAGAIN) {
*replay = true;
return 0;
}
return err;
}

Expand All @@ -1804,6 +1802,39 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
return 0;
}

/*
* Create/change qdisc.
*/
static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack)
{
struct net *net = sock_net(skb->sk);
struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
struct tcmsg *tcm;
bool replay;
int err;

replay:
/* Reinit, just in case something touches this. */
err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
rtm_tca_policy, extack);
if (err < 0)
return err;

tcm = nlmsg_data(n);
dev = __dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return -ENODEV;

replay = false;
err = __tc_modify_qdisc(skb, n, extack, dev, tca, tcm, &replay);
if (replay)
goto replay;

return err;
}

static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
struct netlink_callback *cb,
int *q_idx_p, int s_q_idx, bool recur,
Expand Down Expand Up @@ -2135,31 +2166,22 @@ static void tc_bind_tclass(struct Qdisc *q, u32 portid, u32 clid,

#endif

static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack)
static int __tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack,
struct net_device *dev,
struct nlattr *tca[TCA_MAX + 1],
struct tcmsg *tcm)
{
struct net *net = sock_net(skb->sk);
struct tcmsg *tcm = nlmsg_data(n);
struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
struct Qdisc *q = NULL;
const struct Qdisc_class_ops *cops;
struct Qdisc *q = NULL;
unsigned long cl = 0;
unsigned long new_cl;
u32 portid;
u32 clid;
u32 qid;
int err;

err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
rtm_tca_policy, extack);
if (err < 0)
return err;

dev = __dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return -ENODEV;

/*
parent == TC_H_UNSPEC - unspecified parent.
parent == TC_H_ROOT - class is root, which has no parent.
Expand Down Expand Up @@ -2268,6 +2290,27 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n,
return err;
}

static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n,
struct netlink_ext_ack *extack)
{
struct net *net = sock_net(skb->sk);
struct tcmsg *tcm = nlmsg_data(n);
struct nlattr *tca[TCA_MAX + 1];
struct net_device *dev;
int err;

err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
rtm_tca_policy, extack);
if (err < 0)
return err;

dev = __dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return -ENODEV;

return __tc_ctl_tclass(skb, n, extack, dev, tca, tcm);
}

struct qdisc_dump_args {
struct qdisc_walker w;
struct sk_buff *skb;
Expand Down Expand Up @@ -2344,20 +2387,12 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb,
return 0;
}

static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
static int __tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb,
struct tcmsg *tcm, struct net_device *dev)
{
struct tcmsg *tcm = nlmsg_data(cb->nlh);
struct net *net = sock_net(skb->sk);
struct netdev_queue *dev_queue;
struct net_device *dev;
int t, s_t;

if (nlmsg_len(cb->nlh) < sizeof(*tcm))
return 0;
dev = dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return 0;

s_t = cb->args[0];
t = 0;

Expand All @@ -2374,10 +2409,30 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
done:
cb->args[0] = t;

dev_put(dev);
return skb->len;
}

static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
{
struct tcmsg *tcm = nlmsg_data(cb->nlh);
struct net *net = sock_net(skb->sk);
struct net_device *dev;
int err;

if (nlmsg_len(cb->nlh) < sizeof(*tcm))
return 0;

dev = dev_get_by_index(net, tcm->tcm_ifindex);
if (!dev)
return 0;

err = __tc_dump_tclass(skb, cb, tcm, dev);

dev_put(dev);

return err;
}

#ifdef CONFIG_PROC_FS
static int psched_show(struct seq_file *seq, void *v)
{
Expand Down

0 comments on commit 7c79cff

Please sign in to comment.