Commit 94134bf8 authored by David S. Miller's avatar David S. Miller

Merge branch 'sched-cls_api-small-cleanup'

Jiri Pirko says:

====================
sched: cls_api: small cleanup

This patchset makes couple of things in cls_api code a bit nicer and easier
for reader to digest.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b4c4ebcf 40c81b25
...@@ -17,6 +17,8 @@ struct tcf_walker { ...@@ -17,6 +17,8 @@ struct tcf_walker {
int register_tcf_proto_ops(struct tcf_proto_ops *ops); int register_tcf_proto_ops(struct tcf_proto_ops *ops);
int unregister_tcf_proto_ops(struct tcf_proto_ops *ops); int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
void tcf_destroy_chain(struct tcf_proto __rcu **fl);
static inline unsigned long static inline unsigned long
__cls_set_class(unsigned long *clp, unsigned long cl) __cls_set_class(unsigned long *clp, unsigned long cl)
{ {
......
...@@ -405,8 +405,6 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue, ...@@ -405,8 +405,6 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
const struct Qdisc_ops *ops, u32 parentid); const struct Qdisc_ops *ops, u32 parentid);
void __qdisc_calculate_pkt_len(struct sk_buff *skb, void __qdisc_calculate_pkt_len(struct sk_buff *skb,
const struct qdisc_size_table *stab); const struct qdisc_size_table *stab);
bool tcf_destroy(struct tcf_proto *tp, bool force);
void tcf_destroy_chain(struct tcf_proto __rcu **fl);
int skb_do_redirect(struct sk_buff *); int skb_do_redirect(struct sk_buff *);
static inline void skb_reset_tc(struct sk_buff *skb) static inline void skb_reset_tc(struct sk_buff *skb)
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/err.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kmod.h> #include <linux/kmod.h>
...@@ -38,14 +39,14 @@ static DEFINE_RWLOCK(cls_mod_lock); ...@@ -38,14 +39,14 @@ static DEFINE_RWLOCK(cls_mod_lock);
/* Find classifier type by string name */ /* Find classifier type by string name */
static const struct tcf_proto_ops *tcf_proto_lookup_ops(struct nlattr *kind) static const struct tcf_proto_ops *tcf_proto_lookup_ops(const char *kind)
{ {
const struct tcf_proto_ops *t, *res = NULL; const struct tcf_proto_ops *t, *res = NULL;
if (kind) { if (kind) {
read_lock(&cls_mod_lock); read_lock(&cls_mod_lock);
list_for_each_entry(t, &tcf_proto_base, head) { list_for_each_entry(t, &tcf_proto_base, head) {
if (nla_strcmp(kind, t->kind) == 0) { if (strcmp(kind, t->kind) == 0) {
if (try_module_get(t->owner)) if (try_module_get(t->owner))
res = t; res = t;
break; break;
...@@ -127,6 +128,77 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp) ...@@ -127,6 +128,77 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
return first; return first;
} }
static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
u32 prio, u32 parent, struct Qdisc *q)
{
struct tcf_proto *tp;
int err;
tp = kzalloc(sizeof(*tp), GFP_KERNEL);
if (!tp)
return ERR_PTR(-ENOBUFS);
err = -ENOENT;
tp->ops = tcf_proto_lookup_ops(kind);
if (!tp->ops) {
#ifdef CONFIG_MODULES
rtnl_unlock();
request_module("cls_%s", kind);
rtnl_lock();
tp->ops = tcf_proto_lookup_ops(kind);
/* We dropped the RTNL semaphore in order to perform
* the module load. So, even if we succeeded in loading
* the module we have to replay the request. We indicate
* this using -EAGAIN.
*/
if (tp->ops) {
module_put(tp->ops->owner);
err = -EAGAIN;
} else {
err = -ENOENT;
}
goto errout;
#endif
}
tp->classify = tp->ops->classify;
tp->protocol = protocol;
tp->prio = prio;
tp->classid = parent;
tp->q = q;
err = tp->ops->init(tp);
if (err) {
module_put(tp->ops->owner);
goto errout;
}
return tp;
errout:
kfree(tp);
return ERR_PTR(err);
}
static bool tcf_proto_destroy(struct tcf_proto *tp, bool force)
{
if (tp->ops->destroy(tp, force)) {
module_put(tp->ops->owner);
kfree_rcu(tp, rcu);
return true;
}
return false;
}
void tcf_destroy_chain(struct tcf_proto __rcu **fl)
{
struct tcf_proto *tp;
while ((tp = rtnl_dereference(*fl)) != NULL) {
RCU_INIT_POINTER(*fl, tp->next);
tcf_proto_destroy(tp, true);
}
}
EXPORT_SYMBOL(tcf_destroy_chain);
/* Add/change/delete/get a filter node */ /* Add/change/delete/get a filter node */
static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
...@@ -142,8 +214,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -142,8 +214,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
struct Qdisc *q; struct Qdisc *q;
struct tcf_proto __rcu **back; struct tcf_proto __rcu **back;
struct tcf_proto __rcu **chain; struct tcf_proto __rcu **chain;
struct tcf_proto *next;
struct tcf_proto *tp; struct tcf_proto *tp;
const struct tcf_proto_ops *tp_ops;
const struct Qdisc_class_ops *cops; const struct Qdisc_class_ops *cops;
unsigned long cl; unsigned long cl;
unsigned long fh; unsigned long fh;
...@@ -222,9 +294,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -222,9 +294,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
/* And the last stroke */ /* And the last stroke */
chain = cops->tcf_chain(q, cl); chain = cops->tcf_chain(q, cl);
err = -EINVAL; if (chain == NULL) {
if (chain == NULL) err = -EINVAL;
goto errout; goto errout;
}
if (n->nlmsg_type == RTM_DELTFILTER && prio == 0) { if (n->nlmsg_type == RTM_DELTFILTER && prio == 0) {
tfilter_notify_chain(net, skb, n, chain, RTM_DELTFILTER); tfilter_notify_chain(net, skb, n, chain, RTM_DELTFILTER);
tcf_destroy_chain(chain); tcf_destroy_chain(chain);
...@@ -239,10 +312,13 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -239,10 +312,13 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
if (tp->prio >= prio) { if (tp->prio >= prio) {
if (tp->prio == prio) { if (tp->prio == prio) {
if (!nprio || if (!nprio ||
(tp->protocol != protocol && protocol)) (tp->protocol != protocol && protocol)) {
err = -EINVAL;
goto errout; goto errout;
} else }
} else {
tp = NULL; tp = NULL;
}
break; break;
} }
} }
...@@ -250,110 +326,69 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -250,110 +326,69 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
if (tp == NULL) { if (tp == NULL) {
/* Proto-tcf does not exist, create new one */ /* Proto-tcf does not exist, create new one */
if (tca[TCA_KIND] == NULL || !protocol) if (tca[TCA_KIND] == NULL || !protocol) {
err = -EINVAL;
goto errout; goto errout;
}
err = -ENOENT;
if (n->nlmsg_type != RTM_NEWTFILTER || if (n->nlmsg_type != RTM_NEWTFILTER ||
!(n->nlmsg_flags & NLM_F_CREATE)) !(n->nlmsg_flags & NLM_F_CREATE)) {
err = -ENOENT;
goto errout; goto errout;
}
if (!nprio)
nprio = TC_H_MAJ(tcf_auto_prio(rtnl_dereference(*back)));
/* Create new proto tcf */ tp = tcf_proto_create(nla_data(tca[TCA_KIND]),
protocol, nprio, parent, q);
err = -ENOBUFS; if (IS_ERR(tp)) {
tp = kzalloc(sizeof(*tp), GFP_KERNEL); err = PTR_ERR(tp);
if (tp == NULL)
goto errout;
err = -ENOENT;
tp_ops = tcf_proto_lookup_ops(tca[TCA_KIND]);
if (tp_ops == NULL) {
#ifdef CONFIG_MODULES
struct nlattr *kind = tca[TCA_KIND];
char name[IFNAMSIZ];
if (kind != NULL &&
nla_strlcpy(name, kind, IFNAMSIZ) < IFNAMSIZ) {
rtnl_unlock();
request_module("cls_%s", name);
rtnl_lock();
tp_ops = tcf_proto_lookup_ops(kind);
/* We dropped the RTNL semaphore in order to
* perform the module load. So, even if we
* succeeded in loading the module we have to
* replay the request. We indicate this using
* -EAGAIN.
*/
if (tp_ops != NULL) {
module_put(tp_ops->owner);
err = -EAGAIN;
}
}
#endif
kfree(tp);
goto errout; goto errout;
} }
tp->ops = tp_ops;
tp->protocol = protocol;
tp->prio = nprio ? :
TC_H_MAJ(tcf_auto_prio(rtnl_dereference(*back)));
tp->q = q;
tp->classify = tp_ops->classify;
tp->classid = parent;
err = tp_ops->init(tp);
if (err != 0) {
module_put(tp_ops->owner);
kfree(tp);
goto errout;
}
tp_created = 1; tp_created = 1;
} else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind)) {
} else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind)) err = -EINVAL;
goto errout; goto errout;
}
fh = tp->ops->get(tp, t->tcm_handle); fh = tp->ops->get(tp, t->tcm_handle);
if (fh == 0) { if (fh == 0) {
if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) { if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
struct tcf_proto *next = rtnl_dereference(tp->next); next = rtnl_dereference(tp->next);
RCU_INIT_POINTER(*back, next); RCU_INIT_POINTER(*back, next);
tfilter_notify(net, skb, n, tp, fh, tfilter_notify(net, skb, n, tp, fh,
RTM_DELTFILTER, false); RTM_DELTFILTER, false);
tcf_destroy(tp, true); tcf_proto_destroy(tp, true);
err = 0; err = 0;
goto errout; goto errout;
} }
err = -ENOENT;
if (n->nlmsg_type != RTM_NEWTFILTER || if (n->nlmsg_type != RTM_NEWTFILTER ||
!(n->nlmsg_flags & NLM_F_CREATE)) !(n->nlmsg_flags & NLM_F_CREATE)) {
err = -ENOENT;
goto errout; goto errout;
}
} else { } else {
switch (n->nlmsg_type) { switch (n->nlmsg_type) {
case RTM_NEWTFILTER: case RTM_NEWTFILTER:
err = -EEXIST;
if (n->nlmsg_flags & NLM_F_EXCL) { if (n->nlmsg_flags & NLM_F_EXCL) {
if (tp_created) if (tp_created)
tcf_destroy(tp, true); tcf_proto_destroy(tp, true);
err = -EEXIST;
goto errout; goto errout;
} }
break; break;
case RTM_DELTFILTER: case RTM_DELTFILTER:
err = tp->ops->delete(tp, fh); err = tp->ops->delete(tp, fh);
if (err == 0) { if (err)
struct tcf_proto *next = rtnl_dereference(tp->next); goto errout;
next = rtnl_dereference(tp->next);
tfilter_notify(net, skb, n, tp, tfilter_notify(net, skb, n, tp, t->tcm_handle,
t->tcm_handle, RTM_DELTFILTER, false);
RTM_DELTFILTER, false); if (tcf_proto_destroy(tp, false))
if (tcf_destroy(tp, false)) RCU_INIT_POINTER(*back, next);
RCU_INIT_POINTER(*back, next);
}
goto errout;
case RTM_GETTFILTER: case RTM_GETTFILTER:
err = tfilter_notify(net, skb, n, tp, fh, err = tfilter_notify(net, skb, n, tp, fh,
RTM_NEWTFILTER, true); RTM_NEWTFILTER, true);
...@@ -374,7 +409,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -374,7 +409,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER, false); tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER, false);
} else { } else {
if (tp_created) if (tp_created)
tcf_destroy(tp, true); tcf_proto_destroy(tp, true);
} }
errout: errout:
......
...@@ -1900,28 +1900,6 @@ int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp, ...@@ -1900,28 +1900,6 @@ int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
} }
EXPORT_SYMBOL(tc_classify); EXPORT_SYMBOL(tc_classify);
bool tcf_destroy(struct tcf_proto *tp, bool force)
{
if (tp->ops->destroy(tp, force)) {
module_put(tp->ops->owner);
kfree_rcu(tp, rcu);
return true;
}
return false;
}
void tcf_destroy_chain(struct tcf_proto __rcu **fl)
{
struct tcf_proto *tp;
while ((tp = rtnl_dereference(*fl)) != NULL) {
RCU_INIT_POINTER(*fl, tp->next);
tcf_destroy(tp, true);
}
}
EXPORT_SYMBOL(tcf_destroy_chain);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
static int psched_show(struct seq_file *seq, void *v) static int psched_show(struct seq_file *seq, void *v)
{ {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/file.h> /* for fput */ #include <linux/file.h> /* for fput */
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
/* /*
* The ATM queuing discipline provides a framework for invoking classifiers * The ATM queuing discipline provides a framework for invoking classifiers
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
/* Class-Based Queueing (CBQ) algorithm. /* Class-Based Queueing (CBQ) algorithm.
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/red.h> #include <net/red.h>
#include <net/flow_dissector.h> #include <net/flow_dissector.h>
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
#include <net/dsfield.h> #include <net/dsfield.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
#include <net/codel.h> #include <net/codel.h>
#include <net/codel_impl.h> #include <net/codel_impl.h>
#include <net/codel_qdisc.h> #include <net/codel_qdisc.h>
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <net/netlink.h> #include <net/netlink.h>
#include <net/sch_generic.h> #include <net/sch_generic.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
/* HTB algorithm. /* HTB algorithm.
Author: devik@cdi.cz Author: devik@cdi.cz
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg) static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
{ {
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
struct multiq_sched_data { struct multiq_sched_data {
u16 bands; u16 bands;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
struct prio_sched_data { struct prio_sched_data {
int bands; int bands;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/jhash.h> #include <linux/jhash.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
/* /*
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
#include <net/pkt_cls.h>
#include <net/red.h> #include <net/red.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment