• 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 	return -NLE_OPNOTSUPP;
40 }
41 
cgroup_free_data(struct rtnl_tc * tc,void * data)42 static void cgroup_free_data(struct rtnl_tc *tc, void *data)
43 {
44 	struct rtnl_cgroup *c = data;
45 
46 	if (!c)
47 		return;
48 
49 	rtnl_ematch_tree_free(c->cg_ematch);
50 }
51 
cgroup_msg_parser(struct rtnl_tc * tc,void * data)52 static int cgroup_msg_parser(struct rtnl_tc *tc, void *data)
53 {
54 	struct nlattr *tb[TCA_CGROUP_MAX + 1];
55 	struct rtnl_cgroup *c = data;
56 	int err;
57 
58 	err = tca_parse(tb, TCA_CGROUP_MAX, tc, cgroup_policy);
59 	if (err < 0)
60 		return err;
61 
62 	if (tb[TCA_CGROUP_EMATCHES]) {
63 		if ((err = rtnl_ematch_parse_attr(tb[TCA_CGROUP_EMATCHES],
64 						  &c->cg_ematch)) < 0)
65 			return err;
66 		c->cg_mask |= CGROUP_ATTR_EMATCH;
67 	}
68 
69 #if 0
70 	TODO:
71 	TCA_CGROUP_ACT,
72 	TCA_CGROUP_POLICE,
73 #endif
74 
75 	return 0;
76 }
77 
cgroup_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)78 static void cgroup_dump_line(struct rtnl_tc *tc, void *data,
79 			     struct nl_dump_params *p)
80 {
81 	struct rtnl_cgroup *c = data;
82 
83 	if (!c)
84 		return;
85 
86 	if (c->cg_mask & CGROUP_ATTR_EMATCH)
87 		nl_dump(p, " ematch");
88 	else
89 		nl_dump(p, " match-all");
90 }
91 
cgroup_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)92 static void cgroup_dump_details(struct rtnl_tc *tc, void *data,
93 				struct nl_dump_params *p)
94 {
95 	struct rtnl_cgroup *c = data;
96 
97 	if (!c)
98 		return;
99 
100 	if (c->cg_mask & CGROUP_ATTR_EMATCH) {
101 		nl_dump_line(p, "    ematch ");
102 
103 		if (c->cg_ematch)
104 			rtnl_ematch_tree_dump(c->cg_ematch, p);
105 		else
106 			nl_dump(p, "<no tree>");
107 	} else
108 		nl_dump(p, "no options");
109 }
110 
cgroup_fill_msg(struct rtnl_tc * tc,void * data,struct nl_msg * msg)111 static int cgroup_fill_msg(struct rtnl_tc *tc, void *data,
112 			   struct nl_msg *msg)
113 {
114 	struct rtnl_cgroup *c = data;
115 
116 	if (!c)
117 		BUG();
118 
119 	if (!(tc->ce_mask & TCA_ATTR_HANDLE))
120 		return -NLE_MISSING_ATTR;
121 
122 	if (c->cg_mask & CGROUP_ATTR_EMATCH)
123 		return rtnl_ematch_fill_attr(msg, TCA_CGROUP_EMATCHES,
124 					     c->cg_ematch);
125 
126 	return 0;
127 }
128 
129 
130 /**
131  * @name Attribute Modifications
132  * @{
133  */
134 
rtnl_cgroup_set_ematch(struct rtnl_cls * cls,struct rtnl_ematch_tree * tree)135 void rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
136 {
137 	struct rtnl_cgroup *c;
138 
139 	if (!(c = rtnl_tc_data(TC_CAST(cls))))
140 		BUG();
141 
142 	if (c->cg_ematch) {
143 		rtnl_ematch_tree_free(c->cg_ematch);
144 		c->cg_mask &= ~CGROUP_ATTR_EMATCH;
145 	}
146 
147 	c->cg_ematch = tree;
148 
149 	if (tree)
150 		c->cg_mask |= CGROUP_ATTR_EMATCH;
151 }
152 
rtnl_cgroup_get_ematch(struct rtnl_cls * cls)153 struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls)
154 {
155 	struct rtnl_cgroup *c;
156 
157 	if (!(c = rtnl_tc_data(TC_CAST(cls))))
158 		BUG();
159 
160 	return c->cg_ematch;
161 }
162 
163 /** @} */
164 
165 static struct rtnl_tc_ops cgroup_ops = {
166 	.to_kind		= "cgroup",
167 	.to_type		= RTNL_TC_TYPE_CLS,
168 	.to_size		= sizeof(struct rtnl_cgroup),
169 	.to_clone		= cgroup_clone,
170 	.to_msg_parser		= cgroup_msg_parser,
171 	.to_free_data		= cgroup_free_data,
172 	.to_msg_fill		= cgroup_fill_msg,
173 	.to_dump = {
174 	    [NL_DUMP_LINE]	= cgroup_dump_line,
175 	    [NL_DUMP_DETAILS]	= cgroup_dump_details,
176 	},
177 };
178 
cgroup_init(void)179 static void __init cgroup_init(void)
180 {
181 	rtnl_tc_register(&cgroup_ops);
182 }
183 
cgroup_exit(void)184 static void __exit cgroup_exit(void)
185 {
186 	rtnl_tc_unregister(&cgroup_ops);
187 }
188 
189 /** @} */
190