diff options
| -rw-r--r-- | include/linux/cgroup_subsys.h | 2 | ||||
| -rw-r--r-- | include/net/cls_cgroup.h | 40 | ||||
| -rw-r--r-- | net/Kconfig | 7 | ||||
| -rw-r--r-- | net/core/Makefile | 1 | ||||
| -rw-r--r-- | net/core/netclassid_cgroup.c | 120 | ||||
| -rw-r--r-- | net/core/sock.c | 12 | ||||
| -rw-r--r-- | net/sched/Kconfig | 1 | ||||
| -rw-r--r-- | net/sched/cls_cgroup.c | 111 |
8 files changed, 143 insertions, 151 deletions
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index b613ffd402d1..58bf94de4b8e 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h | |||
| @@ -31,7 +31,7 @@ SUBSYS(devices) | |||
| 31 | SUBSYS(freezer) | 31 | SUBSYS(freezer) |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | #if IS_SUBSYS_ENABLED(CONFIG_NET_CLS_CGROUP) | 34 | #if IS_SUBSYS_ENABLED(CONFIG_CGROUP_NET_CLASSID) |
| 35 | SUBSYS(net_cls) | 35 | SUBSYS(net_cls) |
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h index 33d03b648646..9cf2d5ef38d9 100644 --- a/include/net/cls_cgroup.h +++ b/include/net/cls_cgroup.h | |||
| @@ -16,17 +16,16 @@ | |||
| 16 | #include <linux/cgroup.h> | 16 | #include <linux/cgroup.h> |
| 17 | #include <linux/hardirq.h> | 17 | #include <linux/hardirq.h> |
| 18 | #include <linux/rcupdate.h> | 18 | #include <linux/rcupdate.h> |
| 19 | #include <net/sock.h> | ||
| 19 | 20 | ||
| 20 | #if IS_ENABLED(CONFIG_NET_CLS_CGROUP) | 21 | #ifdef CONFIG_CGROUP_NET_CLASSID |
| 21 | struct cgroup_cls_state | 22 | struct cgroup_cls_state { |
| 22 | { | ||
| 23 | struct cgroup_subsys_state css; | 23 | struct cgroup_subsys_state css; |
| 24 | u32 classid; | 24 | u32 classid; |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | void sock_update_classid(struct sock *sk); | 27 | struct cgroup_cls_state *task_cls_state(struct task_struct *p); |
| 28 | 28 | ||
| 29 | #if IS_BUILTIN(CONFIG_NET_CLS_CGROUP) | ||
| 30 | static inline u32 task_cls_classid(struct task_struct *p) | 29 | static inline u32 task_cls_classid(struct task_struct *p) |
| 31 | { | 30 | { |
| 32 | u32 classid; | 31 | u32 classid; |
| @@ -41,33 +40,18 @@ static inline u32 task_cls_classid(struct task_struct *p) | |||
| 41 | 40 | ||
| 42 | return classid; | 41 | return classid; |
| 43 | } | 42 | } |
| 44 | #elif IS_MODULE(CONFIG_NET_CLS_CGROUP) | ||
| 45 | static inline u32 task_cls_classid(struct task_struct *p) | ||
| 46 | { | ||
| 47 | struct cgroup_subsys_state *css; | ||
| 48 | u32 classid = 0; | ||
| 49 | |||
| 50 | if (in_interrupt()) | ||
| 51 | return 0; | ||
| 52 | |||
| 53 | rcu_read_lock(); | ||
| 54 | css = task_css(p, net_cls_subsys_id); | ||
| 55 | if (css) | ||
| 56 | classid = container_of(css, | ||
| 57 | struct cgroup_cls_state, css)->classid; | ||
| 58 | rcu_read_unlock(); | ||
| 59 | 43 | ||
| 60 | return classid; | ||
| 61 | } | ||
| 62 | #endif | ||
| 63 | #else /* !CGROUP_NET_CLS_CGROUP */ | ||
| 64 | static inline void sock_update_classid(struct sock *sk) | 44 | static inline void sock_update_classid(struct sock *sk) |
| 65 | { | 45 | { |
| 66 | } | 46 | u32 classid; |
| 67 | 47 | ||
| 68 | static inline u32 task_cls_classid(struct task_struct *p) | 48 | classid = task_cls_classid(current); |
| 49 | if (classid != sk->sk_classid) | ||
| 50 | sk->sk_classid = classid; | ||
| 51 | } | ||
| 52 | #else /* !CONFIG_CGROUP_NET_CLASSID */ | ||
| 53 | static inline void sock_update_classid(struct sock *sk) | ||
| 69 | { | 54 | { |
| 70 | return 0; | ||
| 71 | } | 55 | } |
| 72 | #endif /* CGROUP_NET_CLS_CGROUP */ | 56 | #endif /* CONFIG_CGROUP_NET_CLASSID */ |
| 73 | #endif /* _NET_CLS_CGROUP_H */ | 57 | #endif /* _NET_CLS_CGROUP_H */ |
diff --git a/net/Kconfig b/net/Kconfig index d334678c0bd8..7da10b830d70 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
| @@ -245,6 +245,13 @@ config NETPRIO_CGROUP | |||
| 245 | Cgroup subsystem for use in assigning processes to network priorities on | 245 | Cgroup subsystem for use in assigning processes to network priorities on |
| 246 | a per-interface basis | 246 | a per-interface basis |
| 247 | 247 | ||
| 248 | config CGROUP_NET_CLASSID | ||
| 249 | boolean "Network classid cgroup" | ||
| 250 | depends on CGROUPS | ||
| 251 | ---help--- | ||
| 252 | Cgroup subsystem for use as general purpose socket classid marker that is | ||
| 253 | being used in cls_cgroup and for netfilter matching. | ||
| 254 | |||
| 248 | config NET_RX_BUSY_POLL | 255 | config NET_RX_BUSY_POLL |
| 249 | boolean | 256 | boolean |
| 250 | default y | 257 | default y |
diff --git a/net/core/Makefile b/net/core/Makefile index b33b996f5dd6..4839a2796964 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
| @@ -22,3 +22,4 @@ obj-$(CONFIG_TRACEPOINTS) += net-traces.o | |||
| 22 | obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o | 22 | obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o |
| 23 | obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o | 23 | obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o |
| 24 | obj-$(CONFIG_NETPRIO_CGROUP) += netprio_cgroup.o | 24 | obj-$(CONFIG_NETPRIO_CGROUP) += netprio_cgroup.o |
| 25 | obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o | ||
diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c new file mode 100644 index 000000000000..719efd541668 --- /dev/null +++ b/net/core/netclassid_cgroup.c | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | /* | ||
| 2 | * net/core/netclassid_cgroup.c Classid Cgroupfs Handling | ||
| 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/cgroup.h> | ||
| 15 | #include <linux/fdtable.h> | ||
| 16 | #include <net/cls_cgroup.h> | ||
| 17 | #include <net/sock.h> | ||
| 18 | |||
| 19 | static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css) | ||
| 20 | { | ||
| 21 | return css ? container_of(css, struct cgroup_cls_state, css) : NULL; | ||
| 22 | } | ||
| 23 | |||
| 24 | struct cgroup_cls_state *task_cls_state(struct task_struct *p) | ||
| 25 | { | ||
| 26 | return css_cls_state(task_css(p, net_cls_subsys_id)); | ||
| 27 | } | ||
| 28 | EXPORT_SYMBOL_GPL(task_cls_state); | ||
| 29 | |||
| 30 | static struct cgroup_subsys_state * | ||
| 31 | cgrp_css_alloc(struct cgroup_subsys_state *parent_css) | ||
| 32 | { | ||
| 33 | struct cgroup_cls_state *cs; | ||
| 34 | |||
| 35 | cs = kzalloc(sizeof(*cs), GFP_KERNEL); | ||
| 36 | if (!cs) | ||
| 37 | return ERR_PTR(-ENOMEM); | ||
| 38 | |||
| 39 | return &cs->css; | ||
| 40 | } | ||
| 41 | |||
| 42 | static int cgrp_css_online(struct cgroup_subsys_state *css) | ||
| 43 | { | ||
| 44 | struct cgroup_cls_state *cs = css_cls_state(css); | ||
| 45 | struct cgroup_cls_state *parent = css_cls_state(css_parent(css)); | ||
| 46 | |||
| 47 | if (parent) | ||
| 48 | cs->classid = parent->classid; | ||
| 49 | |||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | static void cgrp_css_free(struct cgroup_subsys_state *css) | ||
| 54 | { | ||
| 55 | kfree(css_cls_state(css)); | ||
| 56 | } | ||
| 57 | |||
| 58 | static int update_classid(const void *v, struct file *file, unsigned n) | ||
| 59 | { | ||
| 60 | int err; | ||
| 61 | struct socket *sock = sock_from_file(file, &err); | ||
| 62 | |||
| 63 | if (sock) | ||
| 64 | sock->sk->sk_classid = (u32)(unsigned long)v; | ||
| 65 | |||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | static void cgrp_attach(struct cgroup_subsys_state *css, | ||
| 70 | struct cgroup_taskset *tset) | ||
| 71 | { | ||
| 72 | struct cgroup_cls_state *cs = css_cls_state(css); | ||
| 73 | void *v = (void *)(unsigned long)cs->classid; | ||
| 74 | struct task_struct *p; | ||
| 75 | |||
| 76 | cgroup_taskset_for_each(p, css, tset) { | ||
| 77 | task_lock(p); | ||
| 78 | iterate_fd(p->files, 0, update_classid, v); | ||
| 79 | task_unlock(p); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft) | ||
| 84 | { | ||
| 85 | return css_cls_state(css)->classid; | ||
| 86 | } | ||
| 87 | |||
| 88 | static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft, | ||
| 89 | u64 value) | ||
| 90 | { | ||
| 91 | css_cls_state(css)->classid = (u32) value; | ||
| 92 | |||
| 93 | return 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | static struct cftype ss_files[] = { | ||
| 97 | { | ||
| 98 | .name = "classid", | ||
| 99 | .read_u64 = read_classid, | ||
| 100 | .write_u64 = write_classid, | ||
| 101 | }, | ||
| 102 | { } /* terminate */ | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct cgroup_subsys net_cls_subsys = { | ||
| 106 | .name = "net_cls", | ||
| 107 | .css_alloc = cgrp_css_alloc, | ||
| 108 | .css_online = cgrp_css_online, | ||
| 109 | .css_free = cgrp_css_free, | ||
| 110 | .attach = cgrp_attach, | ||
| 111 | .subsys_id = net_cls_subsys_id, | ||
| 112 | .base_cftypes = ss_files, | ||
| 113 | .module = THIS_MODULE, | ||
| 114 | }; | ||
| 115 | |||
| 116 | static int __init init_netclassid_cgroup(void) | ||
| 117 | { | ||
| 118 | return cgroup_load_subsys(&net_cls_subsys); | ||
| 119 | } | ||
| 120 | __initcall(init_netclassid_cgroup); | ||
diff --git a/net/core/sock.c b/net/core/sock.c index ab20ed9b0f31..3f150729fb15 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -1308,18 +1308,6 @@ static void sk_prot_free(struct proto *prot, struct sock *sk) | |||
| 1308 | module_put(owner); | 1308 | module_put(owner); |
| 1309 | } | 1309 | } |
| 1310 | 1310 | ||
| 1311 | #if IS_ENABLED(CONFIG_NET_CLS_CGROUP) | ||
| 1312 | void sock_update_classid(struct sock *sk) | ||
| 1313 | { | ||
| 1314 | u32 classid; | ||
| 1315 | |||
| 1316 | classid = task_cls_classid(current); | ||
| 1317 | if (classid != sk->sk_classid) | ||
| 1318 | sk->sk_classid = classid; | ||
| 1319 | } | ||
| 1320 | EXPORT_SYMBOL(sock_update_classid); | ||
| 1321 | #endif | ||
| 1322 | |||
| 1323 | #if IS_ENABLED(CONFIG_NETPRIO_CGROUP) | 1311 | #if IS_ENABLED(CONFIG_NETPRIO_CGROUP) |
| 1324 | void sock_update_netprioidx(struct sock *sk) | 1312 | void sock_update_netprioidx(struct sock *sk) |
| 1325 | { | 1313 | { |
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index ad1f1d819203..f711a471d0b7 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
| @@ -435,6 +435,7 @@ config NET_CLS_FLOW | |||
| 435 | config NET_CLS_CGROUP | 435 | config NET_CLS_CGROUP |
| 436 | tristate "Control Group Classifier" | 436 | tristate "Control Group Classifier" |
| 437 | select NET_CLS | 437 | select NET_CLS |
| 438 | select CGROUP_NET_CLASSID | ||
| 438 | depends on CGROUPS | 439 | depends on CGROUPS |
| 439 | ---help--- | 440 | ---help--- |
| 440 | Say Y here if you want to classify packets based on the control | 441 | Say Y here if you want to classify packets based on the control |
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index 16006c92c3fd..838fa40abad1 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c | |||
| @@ -11,109 +11,13 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/slab.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> | 14 | #include <linux/skbuff.h> |
| 18 | #include <linux/cgroup.h> | ||
| 19 | #include <linux/rcupdate.h> | 15 | #include <linux/rcupdate.h> |
| 20 | #include <linux/fdtable.h> | ||
| 21 | #include <net/rtnetlink.h> | 16 | #include <net/rtnetlink.h> |
| 22 | #include <net/pkt_cls.h> | 17 | #include <net/pkt_cls.h> |
| 23 | #include <net/sock.h> | 18 | #include <net/sock.h> |
| 24 | #include <net/cls_cgroup.h> | 19 | #include <net/cls_cgroup.h> |
| 25 | 20 | ||
| 26 | static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state *css) | ||
| 27 | { | ||
| 28 | return css ? container_of(css, struct cgroup_cls_state, css) : NULL; | ||
| 29 | } | ||
| 30 | |||
| 31 | static inline struct cgroup_cls_state *task_cls_state(struct task_struct *p) | ||
| 32 | { | ||
| 33 | return css_cls_state(task_css(p, net_cls_subsys_id)); | ||
| 34 | } | ||
| 35 | |||
| 36 | static struct cgroup_subsys_state * | ||
| 37 | cgrp_css_alloc(struct cgroup_subsys_state *parent_css) | ||
| 38 | { | ||
| 39 | struct cgroup_cls_state *cs; | ||
| 40 | |||
| 41 | cs = kzalloc(sizeof(*cs), GFP_KERNEL); | ||
| 42 | if (!cs) | ||
| 43 | return ERR_PTR(-ENOMEM); | ||
| 44 | return &cs->css; | ||
| 45 | } | ||
| 46 | |||
| 47 | static int cgrp_css_online(struct cgroup_subsys_state *css) | ||
| 48 | { | ||
| 49 | struct cgroup_cls_state *cs = css_cls_state(css); | ||
| 50 | struct cgroup_cls_state *parent = css_cls_state(css_parent(css)); | ||
| 51 | |||
| 52 | if (parent) | ||
| 53 | cs->classid = parent->classid; | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | static void cgrp_css_free(struct cgroup_subsys_state *css) | ||
| 58 | { | ||
| 59 | kfree(css_cls_state(css)); | ||
| 60 | } | ||
| 61 | |||
| 62 | static int update_classid(const void *v, struct file *file, unsigned n) | ||
| 63 | { | ||
| 64 | int err; | ||
| 65 | struct socket *sock = sock_from_file(file, &err); | ||
| 66 | if (sock) | ||
| 67 | sock->sk->sk_classid = (u32)(unsigned long)v; | ||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | static void cgrp_attach(struct cgroup_subsys_state *css, | ||
| 72 | struct cgroup_taskset *tset) | ||
| 73 | { | ||
| 74 | struct task_struct *p; | ||
| 75 | struct cgroup_cls_state *cs = css_cls_state(css); | ||
| 76 | void *v = (void *)(unsigned long)cs->classid; | ||
| 77 | |||
| 78 | cgroup_taskset_for_each(p, css, tset) { | ||
| 79 | task_lock(p); | ||
| 80 | iterate_fd(p->files, 0, update_classid, v); | ||
| 81 | task_unlock(p); | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | static u64 read_classid(struct cgroup_subsys_state *css, struct cftype *cft) | ||
| 86 | { | ||
| 87 | return css_cls_state(css)->classid; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int write_classid(struct cgroup_subsys_state *css, struct cftype *cft, | ||
| 91 | u64 value) | ||
| 92 | { | ||
| 93 | css_cls_state(css)->classid = (u32) value; | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static struct cftype ss_files[] = { | ||
| 98 | { | ||
| 99 | .name = "classid", | ||
| 100 | .read_u64 = read_classid, | ||
| 101 | .write_u64 = write_classid, | ||
| 102 | }, | ||
| 103 | { } /* terminate */ | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct cgroup_subsys net_cls_subsys = { | ||
| 107 | .name = "net_cls", | ||
| 108 | .css_alloc = cgrp_css_alloc, | ||
| 109 | .css_online = cgrp_css_online, | ||
| 110 | .css_free = cgrp_css_free, | ||
| 111 | .attach = cgrp_attach, | ||
| 112 | .subsys_id = net_cls_subsys_id, | ||
| 113 | .base_cftypes = ss_files, | ||
| 114 | .module = THIS_MODULE, | ||
| 115 | }; | ||
| 116 | |||
| 117 | struct cls_cgroup_head { | 21 | struct cls_cgroup_head { |
| 118 | u32 handle; | 22 | u32 handle; |
| 119 | struct tcf_exts exts; | 23 | struct tcf_exts exts; |
| @@ -309,25 +213,12 @@ static struct tcf_proto_ops cls_cgroup_ops __read_mostly = { | |||
| 309 | 213 | ||
| 310 | static int __init init_cgroup_cls(void) | 214 | static int __init init_cgroup_cls(void) |
| 311 | { | 215 | { |
| 312 | int ret; | 216 | return register_tcf_proto_ops(&cls_cgroup_ops); |
| 313 | |||
| 314 | ret = cgroup_load_subsys(&net_cls_subsys); | ||
| 315 | if (ret) | ||
| 316 | goto out; | ||
| 317 | |||
| 318 | ret = register_tcf_proto_ops(&cls_cgroup_ops); | ||
| 319 | if (ret) | ||
| 320 | cgroup_unload_subsys(&net_cls_subsys); | ||
| 321 | |||
| 322 | out: | ||
| 323 | return ret; | ||
| 324 | } | 217 | } |
| 325 | 218 | ||
| 326 | static void __exit exit_cgroup_cls(void) | 219 | static void __exit exit_cgroup_cls(void) |
| 327 | { | 220 | { |
| 328 | unregister_tcf_proto_ops(&cls_cgroup_ops); | 221 | unregister_tcf_proto_ops(&cls_cgroup_ops); |
| 329 | |||
| 330 | cgroup_unload_subsys(&net_cls_subsys); | ||
| 331 | } | 222 | } |
| 332 | 223 | ||
| 333 | module_init(init_cgroup_cls); | 224 | module_init(init_cgroup_cls); |
