--- /dev/null
+/*
+ * lib/cli/cls/cgroup.c cgroup classifier module for CLI lib
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <netlink/cli/utils.h>
+#include <netlink/cli/cls.h>
+#include <netlink/route/cls/cgroup.h>
+
+static void print_usage(void)
+{
+ printf(
+"Usage: nl-cls-add [...] cgroup [OPTIONS]...\n"
+"\n"
+"OPTIONS\n"
+" -h, --help Show this help text.\n"
+" -e, --ematch=EXPR Ematch expression\n"
+"\n"
+"EXAMPLE"
+" nl-cls-add --dev=eth0 --parent=q_root cgroup\n");
+}
+
+static int parse_argv(struct rtnl_cls *cls, int argc, char **argv)
+{
+ struct rtnl_ematch_tree *tree;
+
+ for (;;) {
+ int c, optidx = 0;
+ static struct option long_opts[] = {
+ { "help", 0, 0, 'h' },
+ { "ematch", 1, 0, 'e' },
+ { 0, 0, 0, 0 }
+ };
+
+ c = getopt_long(argc, argv, "he:", long_opts, &optidx);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage();
+ exit(0);
+
+ case 'e':
+ tree = nl_cli_cls_parse_ematch(cls, optarg);
+ rtnl_cgroup_set_ematch(cls, tree);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static struct nl_cli_cls_module cgroup_module =
+{
+ .cm_name = "cgroup",
+ .cm_parse_argv = parse_argv,
+};
+
+static void __init cgroup_init(void)
+{
+ nl_cli_cls_register(&cgroup_module);
+}
+
+static void __exit cgroup_exit(void)
+{
+ nl_cli_cls_unregister(&cgroup_module);
+}
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2009 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2009-2010 Thomas Graf <tgraf@suug.ch>
*/
/**
[TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED },
};
+static int cgroup_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
+{
+ return -NLE_OPNOTSUPP;
+}
+
static void cgroup_free_data(struct rtnl_cls *cls)
{
- struct rtnl_cgroup *cg = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c = rtnl_cls_data(cls);
- rtnl_ematch_tree_free(cg->cg_ematch);
+ rtnl_ematch_tree_free(c->cg_ematch);
}
static int cgroup_msg_parser(struct rtnl_cls *cls)
{
- struct rtnl_cgroup *cg = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c = rtnl_cls_data(cls);
struct nlattr *tb[TCA_CGROUP_MAX + 1];
int err;
return err;
if (tb[TCA_CGROUP_EMATCHES]) {
- if ((err = rtnl_ematch_parse(tb[TCA_CGROUP_EMATCHES],
- &cg->cg_ematch)) < 0)
+ if ((err = rtnl_ematch_parse_attr(tb[TCA_CGROUP_EMATCHES],
+ &c->cg_ematch)) < 0)
return err;
- cg->cg_mask |= CGROUP_ATTR_EMATCH;
+ c->cg_mask |= CGROUP_ATTR_EMATCH;
}
#if 0
static void cgroup_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
{
- struct rtnl_cgroup *cg = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c = rtnl_cls_data(cls);
- if (cg->cg_mask & CGROUP_ATTR_EMATCH)
+ if (c->cg_mask & CGROUP_ATTR_EMATCH)
nl_dump(p, " ematch");
else
nl_dump(p, " match-all");
static void cgroup_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
{
- struct rtnl_cgroup *cg = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c = rtnl_cls_data(cls);
- if (cg->cg_mask & CGROUP_ATTR_EMATCH) {
- nl_dump(p, "\n");
+ if (c->cg_mask & CGROUP_ATTR_EMATCH) {
nl_dump_line(p, " ematch ");
- rtnl_ematch_tree_dump(cg->cg_ematch, p);
- }
+ rtnl_ematch_tree_dump(c->cg_ematch, p);
+ } else
+ nl_dump(p, "no options.\n");
+}
+
+static int cgroup_get_opts(struct rtnl_cls *cls, struct nl_msg *msg)
+{
+ struct rtnl_cgroup *c = rtnl_cls_data(cls);
+
+ if (!(cls->ce_mask & TCA_ATTR_HANDLE))
+ return -NLE_MISSING_ATTR;
+
+ if (c->cg_mask & CGROUP_ATTR_EMATCH)
+ return rtnl_ematch_fill_attr(msg, TCA_CGROUP_EMATCHES,
+ c->cg_ematch);
+
+ return 0;
}
+
/**
* @name Attribute Modifications
* @{
*/
-int rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
+void rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
{
- struct rtnl_cgroup *cg = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c = rtnl_cls_data(cls);
- if (cg->cg_ematch) {
- rtnl_ematch_tree_free(cg->cg_ematch);
- cg->cg_mask &= ~CGROUP_ATTR_EMATCH;
+ if (c->cg_ematch) {
+ rtnl_ematch_tree_free(c->cg_ematch);
+ c->cg_mask &= ~CGROUP_ATTR_EMATCH;
}
- cg->cg_ematch = tree;
+ c->cg_ematch = tree;
if (tree)
- cg->cg_mask |= CGROUP_ATTR_EMATCH;
-
- return 0;
+ c->cg_mask |= CGROUP_ATTR_EMATCH;
}
struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls)
{
- struct rtnl_cgroup *cg = rtnl_cls_data(cls);
- return cg->cg_ematch;
+ return ((struct rtnl_cgroup *) rtnl_cls_data(cls))->cg_ematch;
}
+/** @} */
+
static struct rtnl_cls_ops cgroup_ops = {
.co_kind = "cgroup",
.co_size = sizeof(struct rtnl_cgroup),
+ .co_clone = cgroup_clone,
.co_msg_parser = cgroup_msg_parser,
.co_free_data = cgroup_free_data,
+ .co_get_opts = cgroup_get_opts,
.co_dump = {
[NL_DUMP_LINE] = cgroup_dump_line,
[NL_DUMP_DETAILS] = cgroup_dump_details,