mirror of https://gitee.com/openkylin/linux.git
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
94134bf89a
|
@ -17,6 +17,8 @@ struct tcf_walker {
|
|||
int register_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
|
||||
__cls_set_class(unsigned long *clp, unsigned long cl)
|
||||
{
|
||||
|
|
|
@ -405,8 +405,6 @@ struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
|
|||
const struct Qdisc_ops *ops, u32 parentid);
|
||||
void __qdisc_calculate_pkt_len(struct sk_buff *skb,
|
||||
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 *);
|
||||
|
||||
static inline void skb_reset_tc(struct sk_buff *skb)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kmod.h>
|
||||
|
@ -38,14 +39,14 @@ static DEFINE_RWLOCK(cls_mod_lock);
|
|||
|
||||
/* 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;
|
||||
|
||||
if (kind) {
|
||||
read_lock(&cls_mod_lock);
|
||||
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))
|
||||
res = t;
|
||||
break;
|
||||
|
@ -127,6 +128,77 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
|
|||
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 */
|
||||
|
||||
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 tcf_proto __rcu **back;
|
||||
struct tcf_proto __rcu **chain;
|
||||
struct tcf_proto *next;
|
||||
struct tcf_proto *tp;
|
||||
const struct tcf_proto_ops *tp_ops;
|
||||
const struct Qdisc_class_ops *cops;
|
||||
unsigned long cl;
|
||||
unsigned long fh;
|
||||
|
@ -222,9 +294,10 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
|
|||
|
||||
/* And the last stroke */
|
||||
chain = cops->tcf_chain(q, cl);
|
||||
err = -EINVAL;
|
||||
if (chain == NULL)
|
||||
if (chain == NULL) {
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
if (n->nlmsg_type == RTM_DELTFILTER && prio == 0) {
|
||||
tfilter_notify_chain(net, skb, n, chain, RTM_DELTFILTER);
|
||||
tcf_destroy_chain(chain);
|
||||
|
@ -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 (!nprio ||
|
||||
(tp->protocol != protocol && protocol))
|
||||
(tp->protocol != protocol && protocol)) {
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
tp = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -250,110 +326,69 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
|
|||
if (tp == NULL) {
|
||||
/* Proto-tcf does not exist, create new one */
|
||||
|
||||
if (tca[TCA_KIND] == NULL || !protocol)
|
||||
if (tca[TCA_KIND] == NULL || !protocol) {
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
err = -ENOENT;
|
||||
if (n->nlmsg_type != RTM_NEWTFILTER ||
|
||||
!(n->nlmsg_flags & NLM_F_CREATE))
|
||||
goto errout;
|
||||
|
||||
|
||||
/* Create new proto tcf */
|
||||
|
||||
err = -ENOBUFS;
|
||||
tp = kzalloc(sizeof(*tp), GFP_KERNEL);
|
||||
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;
|
||||
}
|
||||
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);
|
||||
!(n->nlmsg_flags & NLM_F_CREATE)) {
|
||||
err = -ENOENT;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (!nprio)
|
||||
nprio = TC_H_MAJ(tcf_auto_prio(rtnl_dereference(*back)));
|
||||
|
||||
tp = tcf_proto_create(nla_data(tca[TCA_KIND]),
|
||||
protocol, nprio, parent, q);
|
||||
if (IS_ERR(tp)) {
|
||||
err = PTR_ERR(tp);
|
||||
goto errout;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
fh = tp->ops->get(tp, t->tcm_handle);
|
||||
|
||||
if (fh == 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);
|
||||
|
||||
tfilter_notify(net, skb, n, tp, fh,
|
||||
RTM_DELTFILTER, false);
|
||||
tcf_destroy(tp, true);
|
||||
tcf_proto_destroy(tp, true);
|
||||
err = 0;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
err = -ENOENT;
|
||||
if (n->nlmsg_type != RTM_NEWTFILTER ||
|
||||
!(n->nlmsg_flags & NLM_F_CREATE))
|
||||
!(n->nlmsg_flags & NLM_F_CREATE)) {
|
||||
err = -ENOENT;
|
||||
goto errout;
|
||||
}
|
||||
} else {
|
||||
switch (n->nlmsg_type) {
|
||||
case RTM_NEWTFILTER:
|
||||
err = -EEXIST;
|
||||
if (n->nlmsg_flags & NLM_F_EXCL) {
|
||||
if (tp_created)
|
||||
tcf_destroy(tp, true);
|
||||
tcf_proto_destroy(tp, true);
|
||||
err = -EEXIST;
|
||||
goto errout;
|
||||
}
|
||||
break;
|
||||
case RTM_DELTFILTER:
|
||||
err = tp->ops->delete(tp, fh);
|
||||
if (err == 0) {
|
||||
struct tcf_proto *next = rtnl_dereference(tp->next);
|
||||
|
||||
tfilter_notify(net, skb, n, tp,
|
||||
t->tcm_handle,
|
||||
RTM_DELTFILTER, false);
|
||||
if (tcf_destroy(tp, false))
|
||||
RCU_INIT_POINTER(*back, next);
|
||||
}
|
||||
goto errout;
|
||||
if (err)
|
||||
goto errout;
|
||||
next = rtnl_dereference(tp->next);
|
||||
tfilter_notify(net, skb, n, tp, t->tcm_handle,
|
||||
RTM_DELTFILTER, false);
|
||||
if (tcf_proto_destroy(tp, false))
|
||||
RCU_INIT_POINTER(*back, next);
|
||||
case RTM_GETTFILTER:
|
||||
err = tfilter_notify(net, skb, n, tp, fh,
|
||||
RTM_NEWTFILTER, true);
|
||||
|
@ -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);
|
||||
} else {
|
||||
if (tp_created)
|
||||
tcf_destroy(tp, true);
|
||||
tcf_proto_destroy(tp, true);
|
||||
}
|
||||
|
||||
errout:
|
||||
|
|
|
@ -1900,28 +1900,6 @@ int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
|
|||
}
|
||||
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
|
||||
static int psched_show(struct seq_file *seq, void *v)
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/file.h> /* for fput */
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
/*
|
||||
* The ATM queuing discipline provides a framework for invoking classifiers
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
|
||||
/* Class-Based Queueing (CBQ) algorithm.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/inet_ecn.h>
|
||||
#include <net/red.h>
|
||||
#include <net/flow_dissector.h>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/rtnetlink.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/dsfield.h>
|
||||
#include <net/inet_ecn.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/vmalloc.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/codel.h>
|
||||
#include <net/codel_impl.h>
|
||||
#include <net/codel_qdisc.h>
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <net/netlink.h>
|
||||
#include <net/sch_generic.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
/* HTB algorithm.
|
||||
Author: devik@cdi.cz
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
struct multiq_sched_data {
|
||||
u16 bands;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
struct prio_sched_data {
|
||||
int bands;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/jhash.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/inet_ecn.h>
|
||||
|
||||
/*
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/vmalloc.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <net/red.h>
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue