libnl  3.6.0
cgroup.c
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * Copyright (c) 2009-2013 Thomas Graf <tgraf@suug.ch>
4  */
5 
6 /**
7  * @ingroup cls
8  * @defgroup cls_cgroup Control Groups Classifier
9  *
10  * @{
11  */
12 
13 #include <netlink-private/netlink.h>
14 #include <netlink-private/tc.h>
15 #include <netlink/netlink.h>
16 #include <netlink/attr.h>
17 #include <netlink/utils.h>
18 #include <netlink-private/route/tc-api.h>
19 #include <netlink/route/classifier.h>
20 #include <netlink/route/cls/cgroup.h>
21 #include <netlink/route/cls/ematch.h>
22 
23 /** @cond SKIP */
24 #define CGROUP_ATTR_EMATCH 0x001
25 /** @endcond */
26 
27 static struct nla_policy cgroup_policy[TCA_CGROUP_MAX+1] = {
28  [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED },
29 };
30 
31 static int cgroup_clone(void *_dst, void *_src)
32 {
33  struct rtnl_cgroup *dst = _dst, *src = _src;
34 
35  dst->cg_ematch = NULL;
36 
37  if (src->cg_ematch) {
38  dst->cg_ematch = rtnl_ematch_tree_clone(src->cg_ematch);
39  if (!dst->cg_ematch)
40  return -NLE_NOMEM;
41  }
42 
43  return 0;
44 }
45 
46 static void cgroup_free_data(struct rtnl_tc *tc, void *data)
47 {
48  struct rtnl_cgroup *c = data;
49 
50  if (!c)
51  return;
52 
53  rtnl_ematch_tree_free(c->cg_ematch);
54 }
55 
56 static int cgroup_msg_parser(struct rtnl_tc *tc, void *data)
57 {
58  struct nlattr *tb[TCA_CGROUP_MAX + 1];
59  struct rtnl_cgroup *c = data;
60  int err;
61 
62  err = tca_parse(tb, TCA_CGROUP_MAX, tc, cgroup_policy);
63  if (err < 0)
64  return err;
65 
66  if (tb[TCA_CGROUP_EMATCHES]) {
67  if ((err = rtnl_ematch_parse_attr(tb[TCA_CGROUP_EMATCHES],
68  &c->cg_ematch)) < 0)
69  return err;
70  c->cg_mask |= CGROUP_ATTR_EMATCH;
71  }
72 
73 #if 0
74  TODO:
75  TCA_CGROUP_ACT,
76  TCA_CGROUP_POLICE,
77 #endif
78 
79  return 0;
80 }
81 
82 static void cgroup_dump_line(struct rtnl_tc *tc, void *data,
83  struct nl_dump_params *p)
84 {
85  struct rtnl_cgroup *c = data;
86 
87  if (!c)
88  return;
89 
90  if (c->cg_mask & CGROUP_ATTR_EMATCH)
91  nl_dump(p, " ematch");
92  else
93  nl_dump(p, " match-all");
94 }
95 
96 static void cgroup_dump_details(struct rtnl_tc *tc, void *data,
97  struct nl_dump_params *p)
98 {
99  struct rtnl_cgroup *c = data;
100 
101  if (!c)
102  return;
103 
104  if (c->cg_mask & CGROUP_ATTR_EMATCH) {
105  nl_dump_line(p, " ematch ");
106 
107  if (c->cg_ematch)
108  rtnl_ematch_tree_dump(c->cg_ematch, p);
109  else
110  nl_dump(p, "<no tree>");
111  } else
112  nl_dump(p, "no options");
113 }
114 
115 static int cgroup_fill_msg(struct rtnl_tc *tc, void *data,
116  struct nl_msg *msg)
117 {
118  struct rtnl_cgroup *c = data;
119 
120  if (!c)
121  BUG();
122 
123  if (!(tc->ce_mask & TCA_ATTR_HANDLE))
124  return -NLE_MISSING_ATTR;
125 
126  if (c->cg_mask & CGROUP_ATTR_EMATCH)
127  return rtnl_ematch_fill_attr(msg, TCA_CGROUP_EMATCHES,
128  c->cg_ematch);
129 
130  return 0;
131 }
132 
133 
134 /**
135  * @name Attribute Modifications
136  * @{
137  */
138 
139 void rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
140 {
141  struct rtnl_cgroup *c;
142 
143  if (!(c = rtnl_tc_data(TC_CAST(cls))))
144  BUG();
145 
146  if (c->cg_ematch) {
147  rtnl_ematch_tree_free(c->cg_ematch);
148  c->cg_mask &= ~CGROUP_ATTR_EMATCH;
149  }
150 
151  c->cg_ematch = tree;
152 
153  if (tree)
154  c->cg_mask |= CGROUP_ATTR_EMATCH;
155 }
156 
157 struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls)
158 {
159  struct rtnl_cgroup *c;
160 
161  if (!(c = rtnl_tc_data(TC_CAST(cls))))
162  BUG();
163 
164  return c->cg_ematch;
165 }
166 
167 /** @} */
168 
169 static struct rtnl_tc_ops cgroup_ops = {
170  .to_kind = "cgroup",
171  .to_type = RTNL_TC_TYPE_CLS,
172  .to_size = sizeof(struct rtnl_cgroup),
173  .to_clone = cgroup_clone,
174  .to_msg_parser = cgroup_msg_parser,
175  .to_free_data = cgroup_free_data,
176  .to_msg_fill = cgroup_fill_msg,
177  .to_dump = {
178  [NL_DUMP_LINE] = cgroup_dump_line,
179  [NL_DUMP_DETAILS] = cgroup_dump_details,
180  },
181 };
182 
183 static void __init cgroup_init(void)
184 {
185  rtnl_tc_register(&cgroup_ops);
186 }
187 
188 static void __exit cgroup_exit(void)
189 {
190  rtnl_tc_unregister(&cgroup_ops);
191 }
192 
193 /** @} */
@ NLA_NESTED
Nested attributes.
Definition: attr.h:42
struct rtnl_ematch_tree * rtnl_ematch_tree_clone(struct rtnl_ematch_tree *src)
Clone ematch tree object.
Definition: ematch.c:328
void rtnl_ematch_tree_free(struct rtnl_ematch_tree *tree)
Free ematch tree object.
Definition: ematch.c:274
int rtnl_ematch_parse_attr(struct nlattr *attr, struct rtnl_ematch_tree **result)
Parse ematch netlink attributes.
Definition: ematch.c:392
void * rtnl_tc_data(struct rtnl_tc *tc)
Return pointer to private data of traffic control object.
Definition: tc.c:1079
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition: tc.h:50
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
Definition: tc.c:1018
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
Definition: tc.c:1052
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
Dumping parameters.
Definition: types.h:28
Attribute validation policy.
Definition: attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65