cls_cgroup.c (19fdb9eefb21b72edbc365b838502780c392bad6) | cls_cgroup.c (f845172531fb7410c7fb7780b1a6e51ee6df7d52) |
---|---|
1/* 2 * net/sched/cls_cgroup.c Control Group Classifier 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Thomas Graf <tgraf@suug.ch> 10 */ 11 12#include <linux/module.h> 13#include <linux/slab.h> 14#include <linux/types.h> 15#include <linux/string.h> 16#include <linux/errno.h> 17#include <linux/skbuff.h> 18#include <linux/cgroup.h> | 1/* 2 * net/sched/cls_cgroup.c Control Group Classifier 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: Thomas Graf <tgraf@suug.ch> 10 */ 11 12#include <linux/module.h> 13#include <linux/slab.h> 14#include <linux/types.h> 15#include <linux/string.h> 16#include <linux/errno.h> 17#include <linux/skbuff.h> 18#include <linux/cgroup.h> |
19#include <linux/rcupdate.h> |
|
19#include <net/rtnetlink.h> 20#include <net/pkt_cls.h> | 20#include <net/rtnetlink.h> 21#include <net/pkt_cls.h> |
22#include <net/sock.h> 23#include <net/cls_cgroup.h> |
|
21 | 24 |
22struct cgroup_cls_state 23{ 24 struct cgroup_subsys_state css; 25 u32 classid; 26}; 27 | |
28static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss, 29 struct cgroup *cgrp); 30static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp); 31static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp); 32 33struct cgroup_subsys net_cls_subsys = { 34 .name = "net_cls", 35 .create = cgrp_create, --- 71 unchanged lines hidden (view full) --- 107}; 108 109static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp, 110 struct tcf_result *res) 111{ 112 struct cls_cgroup_head *head = tp->root; 113 u32 classid; 114 | 25static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss, 26 struct cgroup *cgrp); 27static void cgrp_destroy(struct cgroup_subsys *ss, struct cgroup *cgrp); 28static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp); 29 30struct cgroup_subsys net_cls_subsys = { 31 .name = "net_cls", 32 .create = cgrp_create, --- 71 unchanged lines hidden (view full) --- 104}; 105 106static int cls_cgroup_classify(struct sk_buff *skb, struct tcf_proto *tp, 107 struct tcf_result *res) 108{ 109 struct cls_cgroup_head *head = tp->root; 110 u32 classid; 111 |
112 rcu_read_lock(); 113 classid = task_cls_state(current)->classid; 114 rcu_read_unlock(); 115 |
|
115 /* 116 * Due to the nature of the classifier it is required to ignore all 117 * packets originating from softirq context as accessing `current' 118 * would lead to false results. 119 * 120 * This test assumes that all callers of dev_queue_xmit() explicitely 121 * disable bh. Knowing this, it is possible to detect softirq based 122 * calls by looking at the number of nested bh disable calls because 123 * softirqs always disables bh. 124 */ | 116 /* 117 * Due to the nature of the classifier it is required to ignore all 118 * packets originating from softirq context as accessing `current' 119 * would lead to false results. 120 * 121 * This test assumes that all callers of dev_queue_xmit() explicitely 122 * disable bh. Knowing this, it is possible to detect softirq based 123 * calls by looking at the number of nested bh disable calls because 124 * softirqs always disables bh. 125 */ |
125 if (softirq_count() != SOFTIRQ_OFFSET) 126 return -1; | 126 if (softirq_count() != SOFTIRQ_OFFSET) { 127 /* If there is an sk_classid we'll use that. */ 128 if (!skb->sk) 129 return -1; 130 classid = skb->sk->sk_classid; 131 } |
127 | 132 |
128 rcu_read_lock(); 129 classid = task_cls_state(current)->classid; 130 rcu_read_unlock(); 131 | |
132 if (!classid) 133 return -1; 134 135 if (!tcf_em_tree_match(skb, &head->ematches, NULL)) 136 return -1; 137 138 res->classid = classid; 139 res->class = 0; --- 144 unchanged lines hidden (view full) --- 284 .delete = cls_cgroup_delete, 285 .walk = cls_cgroup_walk, 286 .dump = cls_cgroup_dump, 287 .owner = THIS_MODULE, 288}; 289 290static int __init init_cgroup_cls(void) 291{ | 133 if (!classid) 134 return -1; 135 136 if (!tcf_em_tree_match(skb, &head->ematches, NULL)) 137 return -1; 138 139 res->classid = classid; 140 res->class = 0; --- 144 unchanged lines hidden (view full) --- 285 .delete = cls_cgroup_delete, 286 .walk = cls_cgroup_walk, 287 .dump = cls_cgroup_dump, 288 .owner = THIS_MODULE, 289}; 290 291static int __init init_cgroup_cls(void) 292{ |
292 int ret = register_tcf_proto_ops(&cls_cgroup_ops); 293 if (ret) 294 return ret; | 293 int ret; 294 |
295 ret = cgroup_load_subsys(&net_cls_subsys); 296 if (ret) | 295 ret = cgroup_load_subsys(&net_cls_subsys); 296 if (ret) |
297 unregister_tcf_proto_ops(&cls_cgroup_ops); | 297 goto out; 298 299#ifndef CONFIG_NET_CLS_CGROUP 300 /* We can't use rcu_assign_pointer because this is an int. */ 301 smp_wmb(); 302 net_cls_subsys_id = net_cls_subsys.subsys_id; 303#endif 304 305 ret = register_tcf_proto_ops(&cls_cgroup_ops); 306 if (ret) 307 cgroup_unload_subsys(&net_cls_subsys); 308 309out: |
298 return ret; 299} 300 301static void __exit exit_cgroup_cls(void) 302{ 303 unregister_tcf_proto_ops(&cls_cgroup_ops); | 310 return ret; 311} 312 313static void __exit exit_cgroup_cls(void) 314{ 315 unregister_tcf_proto_ops(&cls_cgroup_ops); |
316 317#ifndef CONFIG_NET_CLS_CGROUP 318 net_cls_subsys_id = -1; 319 synchronize_rcu(); 320#endif 321 |
|
304 cgroup_unload_subsys(&net_cls_subsys); 305} 306 307module_init(init_cgroup_cls); 308module_exit(exit_cgroup_cls); 309MODULE_LICENSE("GPL"); | 322 cgroup_unload_subsys(&net_cls_subsys); 323} 324 325module_init(init_cgroup_cls); 326module_exit(exit_cgroup_cls); 327MODULE_LICENSE("GPL"); |