|
@@ -16,14 +16,11 @@
|
|
#include <linux/errno.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/skbuff.h>
|
|
#include <linux/cgroup.h>
|
|
#include <linux/cgroup.h>
|
|
|
|
+#include <linux/rcupdate.h>
|
|
#include <net/rtnetlink.h>
|
|
#include <net/rtnetlink.h>
|
|
#include <net/pkt_cls.h>
|
|
#include <net/pkt_cls.h>
|
|
-
|
|
|
|
-struct cgroup_cls_state
|
|
|
|
-{
|
|
|
|
- struct cgroup_subsys_state css;
|
|
|
|
- u32 classid;
|
|
|
|
-};
|
|
|
|
|
|
+#include <net/sock.h>
|
|
|
|
+#include <net/cls_cgroup.h>
|
|
|
|
|
|
static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
|
|
static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
|
|
struct cgroup *cgrp);
|
|
struct cgroup *cgrp);
|
|
@@ -112,6 +109,10 @@ static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
|
|
struct cls_cgroup_head *head = tp->root;
|
|
struct cls_cgroup_head *head = tp->root;
|
|
u32 classid;
|
|
u32 classid;
|
|
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
+ classid = task_cls_state(current)->classid;
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Due to the nature of the classifier it is required to ignore all
|
|
* Due to the nature of the classifier it is required to ignore all
|
|
* packets originating from softirq context as accessing `current'
|
|
* packets originating from softirq context as accessing `current'
|
|
@@ -122,12 +123,12 @@ static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp,
|
|
* calls by looking at the number of nested bh disable calls because
|
|
* calls by looking at the number of nested bh disable calls because
|
|
* softirqs always disables bh.
|
|
* softirqs always disables bh.
|
|
*/
|
|
*/
|
|
- if (softirq_count() != SOFTIRQ_OFFSET)
|
|
|
|
- return -1;
|
|
|
|
-
|
|
|
|
- rcu_read_lock();
|
|
|
|
- classid = task_cls_state(current)->classid;
|
|
|
|
- rcu_read_unlock();
|
|
|
|
|
|
+ if (softirq_count() != SOFTIRQ_OFFSET) {
|
|
|
|
+ /* If there is an sk_classid we'll use that. */
|
|
|
|
+ if (!skb->sk)
|
|
|
|
+ return -1;
|
|
|
|
+ classid = skb->sk->sk_classid;
|
|
|
|
+ }
|
|
|
|
|
|
if (!classid)
|
|
if (!classid)
|
|
return -1;
|
|
return -1;
|
|
@@ -289,18 +290,35 @@ static struct tcf_proto_ops cls_cgroup_ops __read_mostly = {
|
|
|
|
|
|
static int __init init_cgroup_cls(void)
|
|
static int __init init_cgroup_cls(void)
|
|
{
|
|
{
|
|
- int ret = register_tcf_proto_ops(&cls_cgroup_ops);
|
|
|
|
- if (ret)
|
|
|
|
- return ret;
|
|
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
ret = cgroup_load_subsys(&net_cls_subsys);
|
|
ret = cgroup_load_subsys(&net_cls_subsys);
|
|
if (ret)
|
|
if (ret)
|
|
- unregister_tcf_proto_ops(&cls_cgroup_ops);
|
|
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+#ifndef CONFIG_NET_CLS_CGROUP
|
|
|
|
+ /* We can't use rcu_assign_pointer because this is an int. */
|
|
|
|
+ smp_wmb();
|
|
|
|
+ net_cls_subsys_id = net_cls_subsys.subsys_id;
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ ret = register_tcf_proto_ops(&cls_cgroup_ops);
|
|
|
|
+ if (ret)
|
|
|
|
+ cgroup_unload_subsys(&net_cls_subsys);
|
|
|
|
+
|
|
|
|
+out:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
static void __exit exit_cgroup_cls(void)
|
|
static void __exit exit_cgroup_cls(void)
|
|
{
|
|
{
|
|
unregister_tcf_proto_ops(&cls_cgroup_ops);
|
|
unregister_tcf_proto_ops(&cls_cgroup_ops);
|
|
|
|
+
|
|
|
|
+#ifndef CONFIG_NET_CLS_CGROUP
|
|
|
|
+ net_cls_subsys_id = -1;
|
|
|
|
+ synchronize_rcu();
|
|
|
|
+#endif
|
|
|
|
+
|
|
cgroup_unload_subsys(&net_cls_subsys);
|
|
cgroup_unload_subsys(&net_cls_subsys);
|
|
}
|
|
}
|
|
|
|
|