Commit 33a48927 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller

sched: push TC filter protocol creation into a separate function

Make the long function tc_ctl_tfilter a little bit shorter and easier to
read. Also make the creation of filter proto symmetric to destruction.
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Acked-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cf1facda
...@@ -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,56 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp) ...@@ -127,6 +128,56 @@ 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) static bool tcf_proto_destroy(struct tcf_proto *tp, bool force)
{ {
if (tp->ops->destroy(tp, force)) { if (tp->ops->destroy(tp, force)) {
...@@ -164,7 +215,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -164,7 +215,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
struct tcf_proto __rcu **back; struct tcf_proto __rcu **back;
struct tcf_proto __rcu **chain; struct tcf_proto __rcu **chain;
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;
...@@ -279,58 +329,16 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n) ...@@ -279,58 +329,16 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
!(n->nlmsg_flags & NLM_F_CREATE)) !(n->nlmsg_flags & NLM_F_CREATE))
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))
goto errout; goto errout;
......
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