1 /* 2 * lib/route/cls/cgroup.c Control Groups Classifier 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2009 Thomas Graf <tgraf (at) suug.ch> 10 */ 11 12 /** 13 * @ingroup cls_api 14 * @defgroup cgroup Control Groups Classifier 15 * 16 * @{ 17 */ 18 19 #include <netlink-local.h> 20 #include <netlink-tc.h> 21 #include <netlink/netlink.h> 22 #include <netlink/attr.h> 23 #include <netlink/utils.h> 24 #include <netlink/route/classifier.h> 25 #include <netlink/route/classifier-modules.h> 26 #include <netlink/route/cls/cgroup.h> 27 #include <netlink/route/cls/ematch.h> 28 29 /** @cond SKIP */ 30 #define CGROUP_ATTR_EMATCH 0x001 31 /** @endcond */ 32 33 static struct nla_policy cgroup_policy[TCA_CGROUP_MAX+1] = { 34 [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED }, 35 }; 36 37 static void cgroup_free_data(struct rtnl_cls *cls) 38 { 39 struct rtnl_cgroup *cg = rtnl_cls_data(cls); 40 41 rtnl_ematch_tree_free(cg->cg_ematch); 42 } 43 44 static int cgroup_msg_parser(struct rtnl_cls *cls) 45 { 46 struct rtnl_cgroup *cg = rtnl_cls_data(cls); 47 struct nlattr *tb[TCA_CGROUP_MAX + 1]; 48 int err; 49 50 err = tca_parse(tb, TCA_CGROUP_MAX, (struct rtnl_tca *) cls, 51 cgroup_policy); 52 if (err < 0) 53 return err; 54 55 if (tb[TCA_CGROUP_EMATCHES]) { 56 if ((err = rtnl_ematch_parse(tb[TCA_CGROUP_EMATCHES], 57 &cg->cg_ematch)) < 0) 58 return err; 59 cg->cg_mask |= CGROUP_ATTR_EMATCH; 60 } 61 62 #if 0 63 TODO: 64 TCA_CGROUP_ACT, 65 TCA_CGROUP_POLICE, 66 #endif 67 68 return 0; 69 } 70 71 static void cgroup_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p) 72 { 73 struct rtnl_cgroup *cg = rtnl_cls_data(cls); 74 75 if (cg->cg_mask & CGROUP_ATTR_EMATCH) 76 nl_dump(p, " ematch"); 77 else 78 nl_dump(p, " match-all"); 79 } 80 81 static void cgroup_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p) 82 { 83 struct rtnl_cgroup *cg = rtnl_cls_data(cls); 84 85 if (cg->cg_mask & CGROUP_ATTR_EMATCH) { 86 nl_dump(p, "\n"); 87 nl_dump_line(p, " ematch "); 88 rtnl_ematch_tree_dump(cg->cg_ematch, p); 89 } 90 } 91 92 /** 93 * @name Attribute Modifications 94 * @{ 95 */ 96 97 int rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree) 98 { 99 struct rtnl_cgroup *cg = rtnl_cls_data(cls); 100 101 if (cg->cg_ematch) { 102 rtnl_ematch_tree_free(cg->cg_ematch); 103 cg->cg_mask &= ~CGROUP_ATTR_EMATCH; 104 } 105 106 cg->cg_ematch = tree; 107 108 if (tree) 109 cg->cg_mask |= CGROUP_ATTR_EMATCH; 110 111 return 0; 112 } 113 114 struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls) 115 { 116 struct rtnl_cgroup *cg = rtnl_cls_data(cls); 117 return cg->cg_ematch; 118 } 119 120 static struct rtnl_cls_ops cgroup_ops = { 121 .co_kind = "cgroup", 122 .co_size = sizeof(struct rtnl_cgroup), 123 .co_msg_parser = cgroup_msg_parser, 124 .co_free_data = cgroup_free_data, 125 .co_dump = { 126 [NL_DUMP_LINE] = cgroup_dump_line, 127 [NL_DUMP_DETAILS] = cgroup_dump_details, 128 }, 129 }; 130 131 static void __init cgroup_init(void) 132 { 133 rtnl_cls_register(&cgroup_ops); 134 } 135 136 static void __exit cgroup_exit(void) 137 { 138 rtnl_cls_unregister(&cgroup_ops); 139 } 140 141 /** @} */ 142