Merge branch 'sched-tp_q-remove'

Jiri Pirko <jiri@mellanox.com>

====================
net: sched: remove some tp->q usage

In order to prepare for block sharing, tcf_proto instances need to be
independent on particular qdisc instances. This patchset takes care of
removal of couple occurrences of tp->q usage.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2017-10-16 21:00:41 +01:00
commit 745482e0c0
23 changed files with 127 additions and 69 deletions

View File

@ -22,15 +22,26 @@ struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
bool create);
void tcf_chain_put(struct tcf_chain *chain);
int tcf_block_get(struct tcf_block **p_block,
struct tcf_proto __rcu **p_filter_chain);
struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q);
void tcf_block_put(struct tcf_block *block);
static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
{
return block->q;
}
static inline struct net_device *tcf_block_dev(struct tcf_block *block)
{
return tcf_block_q(block)->dev_queue->dev;
}
int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res, bool compat_mode);
#else
static inline
int tcf_block_get(struct tcf_block **p_block,
struct tcf_proto __rcu **p_filter_chain)
struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q)
{
return 0;
}
@ -39,6 +50,16 @@ static inline void tcf_block_put(struct tcf_block *block)
{
}
static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
{
return NULL;
}
static inline struct net_device *tcf_block_dev(struct tcf_block *block)
{
return NULL;
}
static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res, bool compat_mode)
{
@ -53,36 +74,43 @@ __cls_set_class(unsigned long *clp, unsigned long cl)
}
static inline unsigned long
cls_set_class(struct tcf_proto *tp, unsigned long *clp,
unsigned long cl)
cls_set_class(struct Qdisc *q, unsigned long *clp, unsigned long cl)
{
unsigned long old_cl;
tcf_tree_lock(tp);
sch_tree_lock(q);
old_cl = __cls_set_class(clp, cl);
tcf_tree_unlock(tp);
sch_tree_unlock(q);
return old_cl;
}
static inline void
tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base)
{
struct Qdisc *q = tp->chain->block->q;
unsigned long cl;
cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, r->classid);
cl = cls_set_class(tp, &r->class, cl);
/* Check q as it is not set for shared blocks. In that case,
* setting class is not supported.
*/
if (!q)
return;
cl = q->ops->cl_ops->bind_tcf(q, base, r->classid);
cl = cls_set_class(q, &r->class, cl);
if (cl)
tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
q->ops->cl_ops->unbind_tcf(q, cl);
}
static inline void
tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
{
struct Qdisc *q = tp->chain->block->q;
unsigned long cl;
if (!q)
return;
if ((cl = __cls_set_class(&r->class, 0)) != 0)
tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
q->ops->cl_ops->unbind_tcf(q, cl);
}
struct tcf_exts {

View File

@ -4,7 +4,9 @@
#include <linux/jiffies.h>
#include <linux/ktime.h>
#include <linux/if_vlan.h>
#include <linux/netdevice.h>
#include <net/sch_generic.h>
#include <net/net_namespace.h>
#include <uapi/linux/pkt_sched.h>
#define DEFAULT_TX_QUEUE_LEN 1000
@ -146,4 +148,9 @@ static inline bool is_classid_clsact_egress(u32 classid)
TC_H_MIN(classid) == TC_H_MIN(TC_H_MIN_EGRESS);
}
static inline struct net *qdisc_net(struct Qdisc *q)
{
return dev_net(q->dev_queue->dev);
}
#endif

View File

@ -270,6 +270,8 @@ struct tcf_chain {
struct tcf_block {
struct list_head chain_list;
struct net *net;
struct Qdisc *q;
};
static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
@ -357,9 +359,6 @@ static inline void sch_tree_unlock(const struct Qdisc *q)
spin_unlock_bh(qdisc_root_sleeping_lock(q));
}
#define tcf_tree_lock(tp) sch_tree_lock((tp)->q)
#define tcf_tree_unlock(tp) sch_tree_unlock((tp)->q)
extern struct Qdisc noop_qdisc;
extern struct Qdisc_ops noop_qdisc_ops;
extern struct Qdisc_ops pfifo_fast_ops;

View File

@ -241,7 +241,7 @@ tcf_chain_filter_chain_ptr_set(struct tcf_chain *chain,
}
int tcf_block_get(struct tcf_block **p_block,
struct tcf_proto __rcu **p_filter_chain)
struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q)
{
struct tcf_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
struct tcf_chain *chain;
@ -257,6 +257,8 @@ int tcf_block_get(struct tcf_block **p_block,
goto err_chain_create;
}
tcf_chain_filter_chain_ptr_set(chain, p_filter_chain);
block->net = qdisc_net(q);
block->q = q;
*p_block = block;
return 0;
@ -418,8 +420,8 @@ static struct tcf_proto *tcf_chain_tp_find(struct tcf_chain *chain,
}
static int tcf_fill_node(struct net *net, struct sk_buff *skb,
struct tcf_proto *tp, void *fh, u32 portid,
u32 seq, u16 flags, int event)
struct tcf_proto *tp, struct Qdisc *q, u32 parent,
void *fh, u32 portid, u32 seq, u16 flags, int event)
{
struct tcmsg *tcm;
struct nlmsghdr *nlh;
@ -432,8 +434,8 @@ static int tcf_fill_node(struct net *net, struct sk_buff *skb,
tcm->tcm_family = AF_UNSPEC;
tcm->tcm__pad1 = 0;
tcm->tcm__pad2 = 0;
tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex;
tcm->tcm_parent = tp->classid;
tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
tcm->tcm_parent = parent;
tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
if (nla_put_string(skb, TCA_KIND, tp->ops->kind))
goto nla_put_failure;
@ -456,6 +458,7 @@ nla_put_failure:
static int tfilter_notify(struct net *net, struct sk_buff *oskb,
struct nlmsghdr *n, struct tcf_proto *tp,
struct Qdisc *q, u32 parent,
void *fh, int event, bool unicast)
{
struct sk_buff *skb;
@ -465,7 +468,7 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb,
if (!skb)
return -ENOBUFS;
if (tcf_fill_node(net, skb, tp, fh, portid, n->nlmsg_seq,
if (tcf_fill_node(net, skb, tp, q, parent, fh, portid, n->nlmsg_seq,
n->nlmsg_flags, event) <= 0) {
kfree_skb(skb);
return -EINVAL;
@ -480,6 +483,7 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb,
static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
struct nlmsghdr *n, struct tcf_proto *tp,
struct Qdisc *q, u32 parent,
void *fh, bool unicast, bool *last)
{
struct sk_buff *skb;
@ -490,7 +494,7 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
if (!skb)
return -ENOBUFS;
if (tcf_fill_node(net, skb, tp, fh, portid, n->nlmsg_seq,
if (tcf_fill_node(net, skb, tp, q, parent, fh, portid, n->nlmsg_seq,
n->nlmsg_flags, RTM_DELTFILTER) <= 0) {
kfree_skb(skb);
return -EINVAL;
@ -510,6 +514,7 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
}
static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
struct Qdisc *q, u32 parent,
struct nlmsghdr *n,
struct tcf_chain *chain, int event)
{
@ -517,7 +522,7 @@ static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
for (tp = rtnl_dereference(chain->filter_chain);
tp; tp = rtnl_dereference(tp->next))
tfilter_notify(net, oskb, n, tp, 0, event, false);
tfilter_notify(net, oskb, n, tp, q, parent, 0, event, false);
}
/* Add/change/delete/get a filter node */
@ -636,7 +641,8 @@ replay:
}
if (n->nlmsg_type == RTM_DELTFILTER && prio == 0) {
tfilter_notify_chain(net, skb, n, chain, RTM_DELTFILTER);
tfilter_notify_chain(net, skb, q, parent, n,
chain, RTM_DELTFILTER);
tcf_chain_flush(chain);
err = 0;
goto errout;
@ -683,7 +689,7 @@ replay:
if (!fh) {
if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
tcf_chain_tp_remove(chain, &chain_info, tp);
tfilter_notify(net, skb, n, tp, fh,
tfilter_notify(net, skb, n, tp, q, parent, fh,
RTM_DELTFILTER, false);
tcf_proto_destroy(tp);
err = 0;
@ -708,8 +714,8 @@ replay:
}
break;
case RTM_DELTFILTER:
err = tfilter_del_notify(net, skb, n, tp, fh, false,
&last);
err = tfilter_del_notify(net, skb, n, tp, q, parent,
fh, false, &last);
if (err)
goto errout;
if (last) {
@ -718,7 +724,7 @@ replay:
}
goto errout;
case RTM_GETTFILTER:
err = tfilter_notify(net, skb, n, tp, fh,
err = tfilter_notify(net, skb, n, tp, q, parent, fh,
RTM_NEWTFILTER, true);
goto errout;
default:
@ -732,7 +738,8 @@ replay:
if (err == 0) {
if (tp_created)
tcf_chain_tp_insert(chain, &chain_info, tp);
tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER, false);
tfilter_notify(net, skb, n, tp, q, parent, fh,
RTM_NEWTFILTER, false);
} else {
if (tp_created)
tcf_proto_destroy(tp);
@ -751,6 +758,8 @@ struct tcf_dump_args {
struct tcf_walker w;
struct sk_buff *skb;
struct netlink_callback *cb;
struct Qdisc *q;
u32 parent;
};
static int tcf_node_dump(struct tcf_proto *tp, void *n, struct tcf_walker *arg)
@ -758,13 +767,14 @@ static int tcf_node_dump(struct tcf_proto *tp, void *n, struct tcf_walker *arg)
struct tcf_dump_args *a = (void *)arg;
struct net *net = sock_net(a->skb->sk);
return tcf_fill_node(net, a->skb, tp, n, NETLINK_CB(a->cb->skb).portid,
return tcf_fill_node(net, a->skb, tp, a->q, a->parent,
n, NETLINK_CB(a->cb->skb).portid,
a->cb->nlh->nlmsg_seq, NLM_F_MULTI,
RTM_NEWTFILTER);
}
static bool tcf_chain_dump(struct tcf_chain *chain, struct sk_buff *skb,
struct netlink_callback *cb,
static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
struct sk_buff *skb, struct netlink_callback *cb,
long index_start, long *p_index)
{
struct net *net = sock_net(skb->sk);
@ -786,7 +796,7 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct sk_buff *skb,
memset(&cb->args[1], 0,
sizeof(cb->args) - sizeof(cb->args[0]));
if (cb->args[1] == 0) {
if (tcf_fill_node(net, skb, tp, 0,
if (tcf_fill_node(net, skb, tp, q, parent, 0,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
RTM_NEWTFILTER) <= 0)
@ -799,6 +809,8 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct sk_buff *skb,
arg.w.fn = tcf_node_dump;
arg.skb = skb;
arg.cb = cb;
arg.q = q;
arg.parent = parent;
arg.w.stop = 0;
arg.w.skip = cb->args[1] - 1;
arg.w.count = 0;
@ -824,6 +836,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
const struct Qdisc_class_ops *cops;
long index_start;
long index;
u32 parent;
int err;
if (nlmsg_len(cb->nlh) < sizeof(*tcm))
@ -837,10 +850,13 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
if (!dev)
return skb->len;
if (!tcm->tcm_parent)
parent = tcm->tcm_parent;
if (!parent) {
q = dev->qdisc;
else
parent = q->handle;
} else {
q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));
}
if (!q)
goto out;
cops = q->ops->cl_ops;
@ -864,7 +880,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
if (tca[TCA_CHAIN] &&
nla_get_u32(tca[TCA_CHAIN]) != chain->index)
continue;
if (!tcf_chain_dump(chain, skb, cb, index_start, &index))
if (!tcf_chain_dump(chain, q, parent, skb, cb,
index_start, &index))
break;
}

View File

@ -491,8 +491,11 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
perturb_period = nla_get_u32(tb[TCA_FLOW_PERTURB]) * HZ;
}
if (TC_H_MAJ(baseclass) == 0)
baseclass = TC_H_MAKE(tp->q->handle, baseclass);
if (TC_H_MAJ(baseclass) == 0) {
struct Qdisc *q = tcf_block_q(tp->chain->block);
baseclass = TC_H_MAKE(q->handle, baseclass);
}
if (TC_H_MIN(baseclass) == 0)
baseclass = TC_H_MAKE(baseclass, 1);

View File

@ -28,6 +28,7 @@
#include <net/netlink.h>
#include <net/act_api.h>
#include <net/pkt_cls.h>
#include <net/sch_generic.h>
#define HTSIZE 256
@ -83,9 +84,11 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
}
}
} else {
struct Qdisc *q = tcf_block_q(tp->chain->block);
/* Old method: classify the packet using its skb mark. */
if (id && (TC_H_MAJ(id) == 0 ||
!(TC_H_MAJ(id ^ tp->q->handle)))) {
!(TC_H_MAJ(id ^ q->handle)))) {
res->classid = id;
res->class = 0;
return 0;

View File

@ -13,6 +13,7 @@
#include <net/act_api.h>
#include <net/netlink.h>
#include <net/pkt_cls.h>
#include <net/sch_generic.h>
/*
* Passing parameters to the root seems to be done more awkwardly than really
@ -90,9 +91,11 @@ static int tcindex_classify(struct sk_buff *skb, const struct tcf_proto *tp,
f = tcindex_lookup(p, key);
if (!f) {
struct Qdisc *q = tcf_block_q(tp->chain->block);
if (!p->fall_through)
return -1;
res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle), key);
res->classid = TC_H_MAKE(TC_H_MAJ(q->handle), key);
res->class = 0;
pr_debug("alg 0x%x\n", res->classid);
return 0;

View File

@ -93,7 +93,7 @@ struct tc_u_hnode {
struct tc_u_common {
struct tc_u_hnode __rcu *hlist;
struct Qdisc *q;
struct tcf_block *block;
int refcnt;
struct idr handle_idr;
struct hlist_node hnode;
@ -335,11 +335,7 @@ static struct hlist_head *tc_u_common_hash;
static unsigned int tc_u_hash(const struct tcf_proto *tp)
{
struct net_device *dev = tp->q->dev_queue->dev;
u32 qhandle = tp->q->handle;
int ifindex = dev->ifindex;
return hash_64((u64)ifindex << 32 | qhandle, U32_HASH_SHIFT);
return hash_64((u64) tp->chain->block, U32_HASH_SHIFT);
}
static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp)
@ -349,7 +345,7 @@ static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp)
h = tc_u_hash(tp);
hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) {
if (tc->q == tp->q)
if (tc->block == tp->chain->block)
return tc;
}
return NULL;
@ -378,7 +374,7 @@ static int u32_init(struct tcf_proto *tp)
kfree(root_ht);
return -ENOBUFS;
}
tp_c->q = tp->q;
tp_c->block = tp->chain->block;
INIT_HLIST_NODE(&tp_c->hnode);
idr_init(&tp_c->handle_idr);

View File

@ -178,7 +178,7 @@ static int tcf_em_validate(struct tcf_proto *tp,
struct tcf_ematch_hdr *em_hdr = nla_data(nla);
int data_len = nla_len(nla) - sizeof(*em_hdr);
void *data = (void *) em_hdr + sizeof(*em_hdr);
struct net *net = dev_net(qdisc_dev(tp->q));
struct net *net = tp->chain->block->net;
if (!TCF_EM_REL_VALID(em_hdr->flags))
goto errout;

View File

@ -1661,9 +1661,11 @@ static int tcf_node_bind(struct tcf_proto *tp, void *n, struct tcf_walker *arg)
struct tcf_bind_args *a = (void *)arg;
if (tp->ops->bind_class) {
tcf_tree_lock(tp);
struct Qdisc *q = tcf_block_q(tp->chain->block);
sch_tree_lock(q);
tp->ops->bind_class(n, a->classid, a->cl);
tcf_tree_unlock(tp);
sch_tree_unlock(q);
}
return 0;
}

View File

@ -281,7 +281,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
goto err_out;
}
error = tcf_block_get(&flow->block, &flow->filter_list);
error = tcf_block_get(&flow->block, &flow->filter_list, sch);
if (error) {
kfree(flow);
goto err_out;
@ -546,7 +546,7 @@ static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt)
p->link.q = &noop_qdisc;
pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
err = tcf_block_get(&p->link.block, &p->link.filter_list);
err = tcf_block_get(&p->link.block, &p->link.filter_list, sch);
if (err)
return err;

View File

@ -1566,7 +1566,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (cl == NULL)
goto failure;
err = tcf_block_get(&cl->block, &cl->filter_list);
err = tcf_block_get(&cl->block, &cl->filter_list, sch);
if (err) {
kfree(cl);
return err;

View File

@ -412,7 +412,7 @@ static int drr_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
struct drr_sched *q = qdisc_priv(sch);
int err;
err = tcf_block_get(&q->block, &q->filter_list);
err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
err = qdisc_class_hash_init(&q->clhash);

View File

@ -344,7 +344,7 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
if (!opt)
goto errout;
err = tcf_block_get(&p->block, &p->filter_list);
err = tcf_block_get(&p->block, &p->filter_list, sch);
if (err)
return err;

View File

@ -481,7 +481,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
return err;
}
err = tcf_block_get(&q->block, &q->filter_list);
err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;

View File

@ -1033,7 +1033,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
if (cl == NULL)
return -ENOBUFS;
err = tcf_block_get(&cl->block, &cl->filter_list);
err = tcf_block_get(&cl->block, &cl->filter_list, sch);
if (err) {
kfree(cl);
return err;
@ -1405,7 +1405,7 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
return err;
q->eligible = RB_ROOT;
err = tcf_block_get(&q->root.block, &q->root.filter_list);
err = tcf_block_get(&q->root.block, &q->root.filter_list, sch);
if (err)
return err;

View File

@ -1030,7 +1030,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
if (!opt)
return -EINVAL;
err = tcf_block_get(&q->block, &q->filter_list);
err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
@ -1393,7 +1393,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
if (!cl)
goto failure;
err = tcf_block_get(&cl->block, &cl->filter_list);
err = tcf_block_get(&cl->block, &cl->filter_list, sch);
if (err) {
kfree(cl);
goto failure;

View File

@ -59,7 +59,7 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
struct net_device *dev = qdisc_dev(sch);
int err;
err = tcf_block_get(&q->block, &dev->ingress_cl_list);
err = tcf_block_get(&q->block, &dev->ingress_cl_list, sch);
if (err)
return err;
@ -153,11 +153,11 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
struct net_device *dev = qdisc_dev(sch);
int err;
err = tcf_block_get(&q->ingress_block, &dev->ingress_cl_list);
err = tcf_block_get(&q->ingress_block, &dev->ingress_cl_list, sch);
if (err)
return err;
err = tcf_block_get(&q->egress_block, &dev->egress_cl_list);
err = tcf_block_get(&q->egress_block, &dev->egress_cl_list, sch);
if (err)
return err;

View File

@ -245,7 +245,7 @@ static int multiq_init(struct Qdisc *sch, struct nlattr *opt)
if (opt == NULL)
return -EINVAL;
err = tcf_block_get(&q->block, &q->filter_list);
err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;

View File

@ -212,7 +212,7 @@ static int prio_init(struct Qdisc *sch, struct nlattr *opt)
if (!opt)
return -EINVAL;
err = tcf_block_get(&q->block, &q->filter_list);
err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;

View File

@ -1419,7 +1419,7 @@ static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
int i, j, err;
u32 max_cl_shift, maxbudg_shift, max_classes;
err = tcf_block_get(&q->block, &q->filter_list);
err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;

View File

@ -553,7 +553,7 @@ static int sfb_init(struct Qdisc *sch, struct nlattr *opt)
struct sfb_sched_data *q = qdisc_priv(sch);
int err;
err = tcf_block_get(&q->block, &q->filter_list);
err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;

View File

@ -725,7 +725,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
setup_deferrable_timer(&q->perturb_timer, sfq_perturbation,
(unsigned long)sch);
err = tcf_block_get(&q->block, &q->filter_list);
err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;