00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <netlink-local.h>
00020 #include <netlink-tc.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/attr.h>
00023 #include <netlink/utils.h>
00024 #include <netlink/route/tc-api.h>
00025 #include <netlink/route/classifier.h>
00026 #include <netlink/route/cls/cgroup.h>
00027 #include <netlink/route/cls/ematch.h>
00028
00029
00030 #define CGROUP_ATTR_EMATCH 0x001
00031
00032
00033 static struct nla_policy cgroup_policy[TCA_CGROUP_MAX+1] = {
00034 [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED },
00035 };
00036
00037 static int cgroup_clone(void *dst, void *src)
00038 {
00039 return -NLE_OPNOTSUPP;
00040 }
00041
00042 static void cgroup_free_data(struct rtnl_tc *tc, void *data)
00043 {
00044 struct rtnl_cgroup *c = data;
00045
00046 if (!c)
00047 return;
00048
00049 rtnl_ematch_tree_free(c->cg_ematch);
00050 }
00051
00052 static int cgroup_msg_parser(struct rtnl_tc *tc, void *data)
00053 {
00054 struct nlattr *tb[TCA_CGROUP_MAX + 1];
00055 struct rtnl_cgroup *c = data;
00056 int err;
00057
00058 err = tca_parse(tb, TCA_CGROUP_MAX, tc, cgroup_policy);
00059 if (err < 0)
00060 return err;
00061
00062 if (tb[TCA_CGROUP_EMATCHES]) {
00063 if ((err = rtnl_ematch_parse_attr(tb[TCA_CGROUP_EMATCHES],
00064 &c->cg_ematch)) < 0)
00065 return err;
00066 c->cg_mask |= CGROUP_ATTR_EMATCH;
00067 }
00068
00069 #if 0
00070 TODO:
00071 TCA_CGROUP_ACT,
00072 TCA_CGROUP_POLICE,
00073 #endif
00074
00075 return 0;
00076 }
00077
00078 static void cgroup_dump_line(struct rtnl_tc *tc, void *data,
00079 struct nl_dump_params *p)
00080 {
00081 struct rtnl_cgroup *c = data;
00082
00083 if (!c)
00084 return;
00085
00086 if (c->cg_mask & CGROUP_ATTR_EMATCH)
00087 nl_dump(p, " ematch");
00088 else
00089 nl_dump(p, " match-all");
00090 }
00091
00092 static void cgroup_dump_details(struct rtnl_tc *tc, void *data,
00093 struct nl_dump_params *p)
00094 {
00095 struct rtnl_cgroup *c = data;
00096
00097 if (!c)
00098 return;
00099
00100 if (c->cg_mask & CGROUP_ATTR_EMATCH) {
00101 nl_dump_line(p, " ematch ");
00102
00103 if (c->cg_ematch)
00104 rtnl_ematch_tree_dump(c->cg_ematch, p);
00105 else
00106 nl_dump(p, "<no tree>");
00107 } else
00108 nl_dump(p, "no options");
00109 }
00110
00111 static int cgroup_fill_msg(struct rtnl_tc *tc, void *data,
00112 struct nl_msg *msg)
00113 {
00114 struct rtnl_cgroup *c = data;
00115
00116 if (!c)
00117 BUG();
00118
00119 if (!(tc->ce_mask & TCA_ATTR_HANDLE))
00120 return -NLE_MISSING_ATTR;
00121
00122 if (c->cg_mask & CGROUP_ATTR_EMATCH)
00123 return rtnl_ematch_fill_attr(msg, TCA_CGROUP_EMATCHES,
00124 c->cg_ematch);
00125
00126 return 0;
00127 }
00128
00129
00130
00131
00132
00133
00134
00135 void rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
00136 {
00137 struct rtnl_cgroup *c;
00138
00139 if (!(c = rtnl_tc_data(TC_CAST(cls))))
00140 BUG();
00141
00142 if (c->cg_ematch) {
00143 rtnl_ematch_tree_free(c->cg_ematch);
00144 c->cg_mask &= ~CGROUP_ATTR_EMATCH;
00145 }
00146
00147 c->cg_ematch = tree;
00148
00149 if (tree)
00150 c->cg_mask |= CGROUP_ATTR_EMATCH;
00151 }
00152
00153 struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls)
00154 {
00155 struct rtnl_cgroup *c;
00156
00157 if (!(c = rtnl_tc_data(TC_CAST(cls))))
00158 BUG();
00159
00160 return c->cg_ematch;
00161 }
00162
00163
00164
00165 static struct rtnl_tc_ops cgroup_ops = {
00166 .to_kind = "cgroup",
00167 .to_type = RTNL_TC_TYPE_CLS,
00168 .to_size = sizeof(struct rtnl_cgroup),
00169 .to_clone = cgroup_clone,
00170 .to_msg_parser = cgroup_msg_parser,
00171 .to_free_data = cgroup_free_data,
00172 .to_msg_fill = cgroup_fill_msg,
00173 .to_dump = {
00174 [NL_DUMP_LINE] = cgroup_dump_line,
00175 [NL_DUMP_DETAILS] = cgroup_dump_details,
00176 },
00177 };
00178
00179 static void __init cgroup_init(void)
00180 {
00181 rtnl_tc_register(&cgroup_ops);
00182 }
00183
00184 static void __exit cgroup_exit(void)
00185 {
00186 rtnl_tc_unregister(&cgroup_ops);
00187 }
00188
00189