• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-2013 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup cls
14  * @defgroup cls_cgroup Control Groups Classifier
15  *
16  * @{
17  */
18 
19 #include <netlink-private/netlink.h>
20 #include <netlink-private/tc.h>
21 #include <netlink/netlink.h>
22 #include <netlink/attr.h>
23 #include <netlink/utils.h>
24 #include <netlink-private/route/tc-api.h>
25 #include <netlink/route/classifier.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_clone(void * _dst,void * _src)37 static int cgroup_clone(void *_dst, void *_src)
38 {
39 	struct rtnl_cgroup *dst = NULL, *src = _src;
40 
41 	dst = calloc(1, sizeof(*dst));
42 	if (!dst)
43 		return -NLE_NOMEM;
44 
45 	dst->cg_mask = src->cg_mask;
46 	dst->cg_ematch = rtnl_ematch_tree_clone(src->cg_ematch);
47 	if (!dst) {
48 		free(dst);
49 		return -NLE_NOMEM;
50 	}
51 
52 	return 0;
53 }
54 
cgroup_free_data(struct rtnl_tc * tc,void * data)55 static void cgroup_free_data(struct rtnl_tc *tc, void *data)
56 {
57 	struct rtnl_cgroup *c = data;
58 
59 	if (!c)
60 		return;
61 
62 	rtnl_ematch_tree_free(c->cg_ematch);
63 }
64 
cgroup_msg_parser(struct rtnl_tc * tc,void * data)65 static int cgroup_msg_parser(struct rtnl_tc *tc, void *data)
66 {
67 	struct nlattr *tb[TCA_CGROUP_MAX + 1];
68 	struct rtnl_cgroup *c = data;
69 	int err;
70 
71 	err = tca_parse(tb, TCA_CGROUP_MAX, tc, cgroup_policy);
72 	if (err < 0)
73 		return err;
74 
75 	if (tb[TCA_CGROUP_EMATCHES]) {
76 		if ((err = rtnl_ematch_parse_attr(tb[TCA_CGROUP_EMATCHES],
77 						  &c->cg_ematch)) < 0)
78 			return err;
79 		c->cg_mask |= CGROUP_ATTR_EMATCH;
80 	}
81 
82 #if 0
83 	TODO:
84 	TCA_CGROUP_ACT,
85 	TCA_CGROUP_POLICE,
86 #endif
87 
88 	return 0;
89 }
90 
cgroup_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)91 static void cgroup_dump_line(struct rtnl_tc *tc, void *data,
92 			     struct nl_dump_params *p)
93 {
94 	struct rtnl_cgroup *c = data;
95 
96 	if (!c)
97 		return;
98 
99 	if (c->cg_mask & CGROUP_ATTR_EMATCH)
100 		nl_dump(p, " ematch");
101 	else
102 		nl_dump(p, " match-all");
103 }
104 
cgroup_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)105 static void cgroup_dump_details(struct rtnl_tc *tc, void *data,
106 				struct nl_dump_params *p)
107 {
108 	struct rtnl_cgroup *c = data;
109 
110 	if (!c)
111 		return;
112 
113 	if (c->cg_mask & CGROUP_ATTR_EMATCH) {
114 		nl_dump_line(p, "    ematch ");
115 
116 		if (c->cg_ematch)
117 			rtnl_ematch_tree_dump(c->cg_ematch, p);
118 		else
119 			nl_dump(p, "<no tree>");
120 	} else
121 		nl_dump(p, "no options");
122 }
123 
cgroup_fill_msg(struct rtnl_tc * tc,void * data,struct nl_msg * msg)124 static int cgroup_fill_msg(struct rtnl_tc *tc, void *data,
125 			   struct nl_msg *msg)
126 {
127 	struct rtnl_cgroup *c = data;
128 
129 	if (!c)
130 		BUG();
131 
132 	if (!(tc->ce_mask & TCA_ATTR_HANDLE))
133 		return -NLE_MISSING_ATTR;
134 
135 	if (c->cg_mask & CGROUP_ATTR_EMATCH)
136 		return rtnl_ematch_fill_attr(msg, TCA_CGROUP_EMATCHES,
137 					     c->cg_ematch);
138 
139 	return 0;
140 }
141 
142 
143 /**
144  * @name Attribute Modifications
145  * @{
146  */
147 
rtnl_cgroup_set_ematch(struct rtnl_cls * cls,struct rtnl_ematch_tree * tree)148 void rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
149 {
150 	struct rtnl_cgroup *c;
151 
152 	if (!(c = rtnl_tc_data(TC_CAST(cls))))
153 		BUG();
154 
155 	if (c->cg_ematch) {
156 		rtnl_ematch_tree_free(c->cg_ematch);
157 		c->cg_mask &= ~CGROUP_ATTR_EMATCH;
158 	}
159 
160 	c->cg_ematch = tree;
161 
162 	if (tree)
163 		c->cg_mask |= CGROUP_ATTR_EMATCH;
164 }
165 
rtnl_cgroup_get_ematch(struct rtnl_cls * cls)166 struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls)
167 {
168 	struct rtnl_cgroup *c;
169 
170 	if (!(c = rtnl_tc_data(TC_CAST(cls))))
171 		BUG();
172 
173 	return c->cg_ematch;
174 }
175 
176 /** @} */
177 
178 static struct rtnl_tc_ops cgroup_ops = {
179 	.to_kind		= "cgroup",
180 	.to_type		= RTNL_TC_TYPE_CLS,
181 	.to_size		= sizeof(struct rtnl_cgroup),
182 	.to_clone		= cgroup_clone,
183 	.to_msg_parser		= cgroup_msg_parser,
184 	.to_free_data		= cgroup_free_data,
185 	.to_msg_fill		= cgroup_fill_msg,
186 	.to_dump = {
187 	    [NL_DUMP_LINE]	= cgroup_dump_line,
188 	    [NL_DUMP_DETAILS]	= cgroup_dump_details,
189 	},
190 };
191 
cgroup_init(void)192 static void __init cgroup_init(void)
193 {
194 	rtnl_tc_register(&cgroup_ops);
195 }
196 
cgroup_exit(void)197 static void __exit cgroup_exit(void)
198 {
199 	rtnl_tc_unregister(&cgroup_ops);
200 }
201 
202 /** @} */
203