| /* |
| * lib/route/cls/cgroup.c Control Groups Classifier |
| * |
| * 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) 2009 Thomas Graf <tgraf@suug.ch> |
| */ |
| |
| /** |
| * @ingroup cls_api |
| * @defgroup cgroup Control Groups Classifier |
| * |
| * @{ |
| */ |
| |
| #include <netlink-local.h> |
| #include <netlink-tc.h> |
| #include <netlink/netlink.h> |
| #include <netlink/attr.h> |
| #include <netlink/utils.h> |
| #include <netlink/route/classifier.h> |
| #include <netlink/route/classifier-modules.h> |
| #include <netlink/route/cls/cgroup.h> |
| #include <netlink/route/cls/ematch.h> |
| |
| /** @cond SKIP */ |
| #define CGROUP_ATTR_EMATCH 0x001 |
| /** @endcond */ |
| |
| static struct nla_policy cgroup_policy[TCA_CGROUP_MAX+1] = { |
| [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED }, |
| }; |
| |
| static void cgroup_free_data(struct rtnl_cls *cls) |
| { |
| struct rtnl_cgroup *cg = rtnl_cls_data(cls); |
| |
| rtnl_ematch_tree_free(cg->cg_ematch); |
| } |
| |
| static int cgroup_msg_parser(struct rtnl_cls *cls) |
| { |
| struct rtnl_cgroup *cg = rtnl_cls_data(cls); |
| struct nlattr *tb[TCA_CGROUP_MAX + 1]; |
| int err; |
| |
| err = tca_parse(tb, TCA_CGROUP_MAX, (struct rtnl_tca *) cls, |
| cgroup_policy); |
| if (err < 0) |
| return err; |
| |
| if (tb[TCA_CGROUP_EMATCHES]) { |
| if ((err = rtnl_ematch_parse(tb[TCA_CGROUP_EMATCHES], |
| &cg->cg_ematch)) < 0) |
| return err; |
| cg->cg_mask |= CGROUP_ATTR_EMATCH; |
| } |
| |
| #if 0 |
| TODO: |
| TCA_CGROUP_ACT, |
| TCA_CGROUP_POLICE, |
| #endif |
| |
| return 0; |
| } |
| |
| static void cgroup_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p) |
| { |
| struct rtnl_cgroup *cg = rtnl_cls_data(cls); |
| |
| if (cg->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); |
| |
| if (cg->cg_mask & CGROUP_ATTR_EMATCH) { |
| nl_dump(p, "\n"); |
| nl_dump_line(p, " ematch "); |
| rtnl_ematch_tree_dump(cg->cg_ematch, p); |
| } |
| } |
| |
| /** |
| * @name Attribute Modifications |
| * @{ |
| */ |
| |
| int rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree) |
| { |
| struct rtnl_cgroup *cg = rtnl_cls_data(cls); |
| |
| if (cg->cg_ematch) { |
| rtnl_ematch_tree_free(cg->cg_ematch); |
| cg->cg_mask &= ~CGROUP_ATTR_EMATCH; |
| } |
| |
| cg->cg_ematch = tree; |
| |
| if (tree) |
| cg->cg_mask |= CGROUP_ATTR_EMATCH; |
| |
| return 0; |
| } |
| |
| struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls) |
| { |
| struct rtnl_cgroup *cg = rtnl_cls_data(cls); |
| return cg->cg_ematch; |
| } |
| |
| static struct rtnl_cls_ops cgroup_ops = { |
| .co_kind = "cgroup", |
| .co_size = sizeof(struct rtnl_cgroup), |
| .co_msg_parser = cgroup_msg_parser, |
| .co_free_data = cgroup_free_data, |
| .co_dump = { |
| [NL_DUMP_LINE] = cgroup_dump_line, |
| [NL_DUMP_DETAILS] = cgroup_dump_details, |
| }, |
| }; |
| |
| static void __init cgroup_init(void) |
| { |
| rtnl_cls_register(&cgroup_ops); |
| } |
| |
| static void __exit cgroup_exit(void) |
| { |
| rtnl_cls_unregister(&cgroup_ops); |
| } |
| |
| /** @} */ |