cgroup.c

00001 /*
00002  * lib/route/cls/cgroup.c       Control Groups Classifier
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2009-2011 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup cls
00014  * @defgroup cls_cgroup Control Groups Classifier
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 /** @cond SKIP */
00030 #define CGROUP_ATTR_EMATCH      0x001
00031 /** @endcond */
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  * @name Attribute Modifications
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 /** @} */