1 /*
2  * lib/route/cls/cgroup.c	Control Groups Classifier
3  *
4  *	This library is free software; you can redistribute it and/or
5  *	modify it under the terms of the GNU Lesser General Public
6  *	License as published by the Free Software Foundation version 2.1
7  *	of the License.
8  *
9  * Copyright (c) 2009 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup cls_api
14  * @defgroup cgroup Control Groups Classifier
15  *
16  * @{
17  */
18 
19 #include <netlink-local.h>
20 #include <netlink-tc.h>
21 #include <netlink/netlink.h>
22 #include <netlink/attr.h>
23 #include <netlink/utils.h>
24 #include <netlink/route/classifier.h>
25 #include <netlink/route/classifier-modules.h>
26 #include <netlink/route/cls/cgroup.h>
27 #include <netlink/route/cls/ematch.h>
28 
29 /** @cond SKIP */
30 #define CGROUP_ATTR_EMATCH      0x001
31 /** @endcond */
32 
33 static struct nla_policy cgroup_policy[TCA_CGROUP_MAX+1] = {
34 	[TCA_CGROUP_EMATCHES]	= { .type = NLA_NESTED },
35 };
36 
cgroup_free_data(struct rtnl_cls * cls)37 static void cgroup_free_data(struct rtnl_cls *cls)
38 {
39 	struct rtnl_cgroup *cg = rtnl_cls_data(cls);
40 
41 	rtnl_ematch_tree_free(cg->cg_ematch);
42 }
43 
cgroup_msg_parser(struct rtnl_cls * cls)44 static int cgroup_msg_parser(struct rtnl_cls *cls)
45 {
46 	struct rtnl_cgroup *cg = rtnl_cls_data(cls);
47 	struct nlattr *tb[TCA_CGROUP_MAX + 1];
48 	int err;
49 
50 	err = tca_parse(tb, TCA_CGROUP_MAX, (struct rtnl_tca *) cls,
51 			cgroup_policy);
52 	if (err < 0)
53 		return err;
54 
55 	if (tb[TCA_CGROUP_EMATCHES]) {
56 		if ((err = rtnl_ematch_parse(tb[TCA_CGROUP_EMATCHES],
57 					     &cg->cg_ematch)) < 0)
58 			return err;
59 		cg->cg_mask |= CGROUP_ATTR_EMATCH;
60 	}
61 
62 #if 0
63 	TODO:
64 	TCA_CGROUP_ACT,
65 	TCA_CGROUP_POLICE,
66 #endif
67 
68 	return 0;
69 }
70 
cgroup_dump_line(struct rtnl_cls * cls,struct nl_dump_params * p)71 static void cgroup_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
72 {
73 	struct rtnl_cgroup *cg = rtnl_cls_data(cls);
74 
75 	if (cg->cg_mask & CGROUP_ATTR_EMATCH)
76 		nl_dump(p, " ematch");
77 	else
78 		nl_dump(p, " match-all");
79 }
80 
cgroup_dump_details(struct rtnl_cls * cls,struct nl_dump_params * p)81 static void cgroup_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
82 {
83 	struct rtnl_cgroup *cg = rtnl_cls_data(cls);
84 
85 	if (cg->cg_mask & CGROUP_ATTR_EMATCH) {
86 		nl_dump(p, "\n");
87 		nl_dump_line(p, "    ematch ");
88 		rtnl_ematch_tree_dump(cg->cg_ematch, p);
89 	}
90 }
91 
92 /**
93  * @name Attribute Modifications
94  * @{
95  */
96 
rtnl_cgroup_set_ematch(struct rtnl_cls * cls,struct rtnl_ematch_tree * tree)97 int rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
98 {
99 	struct rtnl_cgroup *cg = rtnl_cls_data(cls);
100 
101 	if (cg->cg_ematch) {
102 		rtnl_ematch_tree_free(cg->cg_ematch);
103 		cg->cg_mask &= ~CGROUP_ATTR_EMATCH;
104 	}
105 
106 	cg->cg_ematch = tree;
107 
108 	if (tree)
109 		cg->cg_mask |= CGROUP_ATTR_EMATCH;
110 
111 	return 0;
112 }
113 
rtnl_cgroup_get_ematch(struct rtnl_cls * cls)114 struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls)
115 {
116 	struct rtnl_cgroup *cg = rtnl_cls_data(cls);
117 	return cg->cg_ematch;
118 }
119 
120 static struct rtnl_cls_ops cgroup_ops = {
121 	.co_kind		= "cgroup",
122 	.co_size		= sizeof(struct rtnl_cgroup),
123 	.co_msg_parser		= cgroup_msg_parser,
124 	.co_free_data		= cgroup_free_data,
125 	.co_dump = {
126 	    [NL_DUMP_LINE]	= cgroup_dump_line,
127 	    [NL_DUMP_DETAILS]	= cgroup_dump_details,
128 	},
129 };
130 
cgroup_init(void)131 static void __init cgroup_init(void)
132 {
133 	rtnl_cls_register(&cgroup_ops);
134 }
135 
cgroup_exit(void)136 static void __exit cgroup_exit(void)
137 {
138 	rtnl_cls_unregister(&cgroup_ops);
139 }
140 
141 /** @} */
142