Home | History | Annotate | Download | only in cls
      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-2013 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 /**
     13  * @ingroup cls
     14  * @defgroup cls_cgroup Control Groups Classifier
     15  *
     16  * @{
     17  */
     18 
     19 #include <netlink-private/netlink.h>
     20 #include <netlink-private/tc.h>
     21 #include <netlink/netlink.h>
     22 #include <netlink/attr.h>
     23 #include <netlink/utils.h>
     24 #include <netlink-private/route/tc-api.h>
     25 #include <netlink/route/classifier.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 int cgroup_clone(void *dst, void *src)
     38 {
     39 	return -NLE_OPNOTSUPP;
     40 }
     41 
     42 static void cgroup_free_data(struct rtnl_tc *tc, void *data)
     43 {
     44 	struct rtnl_cgroup *c = data;
     45 
     46 	if (!c)
     47 		return;
     48 
     49 	rtnl_ematch_tree_free(c->cg_ematch);
     50 }
     51 
     52 static int cgroup_msg_parser(struct rtnl_tc *tc, void *data)
     53 {
     54 	struct nlattr *tb[TCA_CGROUP_MAX + 1];
     55 	struct rtnl_cgroup *c = data;
     56 	int err;
     57 
     58 	err = tca_parse(tb, TCA_CGROUP_MAX, tc, cgroup_policy);
     59 	if (err < 0)
     60 		return err;
     61 
     62 	if (tb[TCA_CGROUP_EMATCHES]) {
     63 		if ((err = rtnl_ematch_parse_attr(tb[TCA_CGROUP_EMATCHES],
     64 						  &c->cg_ematch)) < 0)
     65 			return err;
     66 		c->cg_mask |= CGROUP_ATTR_EMATCH;
     67 	}
     68 
     69 #if 0
     70 	TODO:
     71 	TCA_CGROUP_ACT,
     72 	TCA_CGROUP_POLICE,
     73 #endif
     74 
     75 	return 0;
     76 }
     77 
     78 static void cgroup_dump_line(struct rtnl_tc *tc, void *data,
     79 			     struct nl_dump_params *p)
     80 {
     81 	struct rtnl_cgroup *c = data;
     82 
     83 	if (!c)
     84 		return;
     85 
     86 	if (c->cg_mask & CGROUP_ATTR_EMATCH)
     87 		nl_dump(p, " ematch");
     88 	else
     89 		nl_dump(p, " match-all");
     90 }
     91 
     92 static void cgroup_dump_details(struct rtnl_tc *tc, void *data,
     93 				struct nl_dump_params *p)
     94 {
     95 	struct rtnl_cgroup *c = data;
     96 
     97 	if (!c)
     98 		return;
     99 
    100 	if (c->cg_mask & CGROUP_ATTR_EMATCH) {
    101 		nl_dump_line(p, "    ematch ");
    102 
    103 		if (c->cg_ematch)
    104 			rtnl_ematch_tree_dump(c->cg_ematch, p);
    105 		else
    106 			nl_dump(p, "<no tree>");
    107 	} else
    108 		nl_dump(p, "no options");
    109 }
    110 
    111 static int cgroup_fill_msg(struct rtnl_tc *tc, void *data,
    112 			   struct nl_msg *msg)
    113 {
    114 	struct rtnl_cgroup *c = data;
    115 
    116 	if (!c)
    117 		BUG();
    118 
    119 	if (!(tc->ce_mask & TCA_ATTR_HANDLE))
    120 		return -NLE_MISSING_ATTR;
    121 
    122 	if (c->cg_mask & CGROUP_ATTR_EMATCH)
    123 		return rtnl_ematch_fill_attr(msg, TCA_CGROUP_EMATCHES,
    124 					     c->cg_ematch);
    125 
    126 	return 0;
    127 }
    128 
    129 
    130 /**
    131  * @name Attribute Modifications
    132  * @{
    133  */
    134 
    135 void rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
    136 {
    137 	struct rtnl_cgroup *c;
    138 
    139 	if (!(c = rtnl_tc_data(TC_CAST(cls))))
    140 		BUG();
    141 
    142 	if (c->cg_ematch) {
    143 		rtnl_ematch_tree_free(c->cg_ematch);
    144 		c->cg_mask &= ~CGROUP_ATTR_EMATCH;
    145 	}
    146 
    147 	c->cg_ematch = tree;
    148 
    149 	if (tree)
    150 		c->cg_mask |= CGROUP_ATTR_EMATCH;
    151 }
    152 
    153 struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls)
    154 {
    155 	struct rtnl_cgroup *c;
    156 
    157 	if (!(c = rtnl_tc_data(TC_CAST(cls))))
    158 		BUG();
    159 
    160 	return c->cg_ematch;
    161 }
    162 
    163 /** @} */
    164 
    165 static struct rtnl_tc_ops cgroup_ops = {
    166 	.to_kind		= "cgroup",
    167 	.to_type		= RTNL_TC_TYPE_CLS,
    168 	.to_size		= sizeof(struct rtnl_cgroup),
    169 	.to_clone		= cgroup_clone,
    170 	.to_msg_parser		= cgroup_msg_parser,
    171 	.to_free_data		= cgroup_free_data,
    172 	.to_msg_fill		= cgroup_fill_msg,
    173 	.to_dump = {
    174 	    [NL_DUMP_LINE]	= cgroup_dump_line,
    175 	    [NL_DUMP_DETAILS]	= cgroup_dump_details,
    176 	},
    177 };
    178 
    179 static void __init cgroup_init(void)
    180 {
    181 	rtnl_tc_register(&cgroup_ops);
    182 }
    183 
    184 static void __exit cgroup_exit(void)
    185 {
    186 	rtnl_tc_unregister(&cgroup_ops);
    187 }
    188 
    189 /** @} */
    190