Home | History | Annotate | Download | only in qdisc
      1 /*
      2  * lib/route/qdisc/dsmark.c	DSMARK
      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) 2003-2011 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 /**
     13  * @ingroup qdisc
     14  * @ingroup class
     15  * @defgroup qdisc_dsmark Differentiated Services Marker (DSMARK)
     16  * @{
     17  */
     18 
     19 #include <netlink-private/netlink.h>
     20 #include <netlink-private/tc.h>
     21 #include <netlink/netlink.h>
     22 #include <netlink/utils.h>
     23 #include <netlink/route/qdisc.h>
     24 #include <netlink-private/route/tc-api.h>
     25 #include <netlink/route/class.h>
     26 #include <netlink/route/qdisc/dsmark.h>
     27 
     28 /** @cond SKIP */
     29 #define SCH_DSMARK_ATTR_INDICES		0x1
     30 #define SCH_DSMARK_ATTR_DEFAULT_INDEX	0x2
     31 #define SCH_DSMARK_ATTR_SET_TC_INDEX	0x4
     32 
     33 #define SCH_DSMARK_ATTR_MASK		0x1
     34 #define SCH_DSMARK_ATTR_VALUE		0x2
     35 /** @endcond */
     36 
     37 static struct nla_policy dsmark_policy[TCA_DSMARK_MAX+1] = {
     38 	[TCA_DSMARK_INDICES]		= { .type = NLA_U16 },
     39 	[TCA_DSMARK_DEFAULT_INDEX]	= { .type = NLA_U16 },
     40 	[TCA_DSMARK_SET_TC_INDEX]	= { .type = NLA_FLAG },
     41 	[TCA_DSMARK_VALUE]		= { .type = NLA_U8 },
     42 	[TCA_DSMARK_MASK]		= { .type = NLA_U8 },
     43 };
     44 
     45 static int dsmark_qdisc_msg_parser(struct rtnl_tc *tc, void *data)
     46 {
     47 	struct rtnl_dsmark_qdisc *dsmark = data;
     48 	struct nlattr *tb[TCA_DSMARK_MAX + 1];
     49 	int err;
     50 
     51 	err = tca_parse(tb, TCA_DSMARK_MAX, tc, dsmark_policy);
     52 	if (err < 0)
     53 		return err;
     54 
     55 	if (tb[TCA_DSMARK_INDICES]) {
     56 		dsmark->qdm_indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
     57 		dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES;
     58 	}
     59 
     60 	if (tb[TCA_DSMARK_DEFAULT_INDEX]) {
     61 		dsmark->qdm_default_index =
     62 				nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
     63 		dsmark->qdm_mask |= SCH_DSMARK_ATTR_DEFAULT_INDEX;
     64 	}
     65 
     66 	if (tb[TCA_DSMARK_SET_TC_INDEX]) {
     67 		dsmark->qdm_set_tc_index = 1;
     68 		dsmark->qdm_mask |= SCH_DSMARK_ATTR_SET_TC_INDEX;
     69 	}
     70 
     71 	return 0;
     72 }
     73 
     74 static int dsmark_class_msg_parser(struct rtnl_tc *tc, void *data)
     75 {
     76 	struct rtnl_dsmark_class *dsmark = data;
     77 	struct nlattr *tb[TCA_DSMARK_MAX + 1];
     78 	int err;
     79 
     80 	err = tca_parse(tb, TCA_DSMARK_MAX, tc, dsmark_policy);
     81 	if (err < 0)
     82 		return err;
     83 
     84 	if (tb[TCA_DSMARK_MASK]) {
     85 		dsmark->cdm_bmask = nla_get_u8(tb[TCA_DSMARK_MASK]);
     86 		dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK;
     87 	}
     88 
     89 	if (tb[TCA_DSMARK_VALUE]) {
     90 		dsmark->cdm_value = nla_get_u8(tb[TCA_DSMARK_VALUE]);
     91 		dsmark->cdm_mask |= SCH_DSMARK_ATTR_VALUE;
     92 	}
     93 
     94 	return 0;
     95 }
     96 
     97 static void dsmark_qdisc_dump_line(struct rtnl_tc *tc, void *data,
     98 				   struct nl_dump_params *p)
     99 {
    100 	struct rtnl_dsmark_qdisc *dsmark = data;
    101 
    102 	if (dsmark && (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES))
    103 		nl_dump(p, " indices 0x%04x", dsmark->qdm_indices);
    104 }
    105 
    106 static void dsmark_qdisc_dump_details(struct rtnl_tc *tc, void *data,
    107 				      struct nl_dump_params *p)
    108 {
    109 	struct rtnl_dsmark_qdisc *dsmark = data;
    110 
    111 	if (!dsmark)
    112 		return;
    113 
    114 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
    115 		nl_dump(p, " default index 0x%04x", dsmark->qdm_default_index);
    116 
    117 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
    118 		nl_dump(p, " set-tc-index");
    119 }
    120 
    121 static void dsmark_class_dump_line(struct rtnl_tc *tc, void *data,
    122 				   struct nl_dump_params *p)
    123 {
    124 	struct rtnl_dsmark_class *dsmark = data;
    125 
    126 	if (!dsmark)
    127 		return;
    128 
    129 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
    130 		nl_dump(p, " value 0x%02x", dsmark->cdm_value);
    131 
    132 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
    133 		nl_dump(p, " mask 0x%02x", dsmark->cdm_bmask);
    134 }
    135 
    136 static int dsmark_qdisc_msg_fill(struct rtnl_tc *tc, void *data,
    137 				 struct nl_msg *msg)
    138 {
    139 	struct rtnl_dsmark_qdisc *dsmark = data;
    140 
    141 	if (!dsmark)
    142 		return 0;
    143 
    144 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
    145 		NLA_PUT_U16(msg, TCA_DSMARK_INDICES, dsmark->qdm_indices);
    146 
    147 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
    148 		NLA_PUT_U16(msg, TCA_DSMARK_DEFAULT_INDEX,
    149 			    dsmark->qdm_default_index);
    150 
    151 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
    152 		NLA_PUT_FLAG(msg, TCA_DSMARK_SET_TC_INDEX);
    153 
    154 	return 0;
    155 
    156 nla_put_failure:
    157 	return -NLE_MSGSIZE;
    158 }
    159 
    160 static int dsmark_class_msg_fill(struct rtnl_tc *tc, void *data,
    161 				 struct nl_msg *msg)
    162 {
    163 	struct rtnl_dsmark_class *dsmark = data;
    164 
    165 	if (!dsmark)
    166 		return 0;
    167 
    168 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
    169 		NLA_PUT_U8(msg, TCA_DSMARK_MASK, dsmark->cdm_bmask);
    170 
    171 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
    172 		NLA_PUT_U8(msg, TCA_DSMARK_VALUE, dsmark->cdm_value);
    173 
    174 	return 0;
    175 
    176 nla_put_failure:
    177 	return -NLE_MSGSIZE;
    178 }
    179 
    180 /**
    181  * @name Class Attribute Access
    182  * @{
    183  */
    184 
    185 /**
    186  * Set bitmask of DSMARK class.
    187  * @arg class		DSMARK class to be modified.
    188  * @arg mask		New bitmask.
    189  * @return 0 on success or a negative error code.
    190  */
    191 int rtnl_class_dsmark_set_bitmask(struct rtnl_class *class, uint8_t mask)
    192 {
    193 	struct rtnl_dsmark_class *dsmark;
    194 
    195 	if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
    196 		return -NLE_NOMEM;
    197 
    198 	dsmark->cdm_bmask = mask;
    199 	dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK;
    200 
    201 	return 0;
    202 }
    203 
    204 /**
    205  * Get bitmask of DSMARK class.
    206  * @arg class		DSMARK class.
    207  * @return Bitmask or a negative error code.
    208  */
    209 int rtnl_class_dsmark_get_bitmask(struct rtnl_class *class)
    210 {
    211 	struct rtnl_dsmark_class *dsmark;
    212 
    213 	if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
    214 		return -NLE_NOMEM;
    215 
    216 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
    217 		return dsmark->cdm_bmask;
    218 	else
    219 		return -NLE_NOATTR;
    220 }
    221 
    222 /**
    223  * Set value of DSMARK class.
    224  * @arg class		DSMARK class to be modified.
    225  * @arg value		New value.
    226  * @return 0 on success or a negative errror code.
    227  */
    228 int rtnl_class_dsmark_set_value(struct rtnl_class *class, uint8_t value)
    229 {
    230 	struct rtnl_dsmark_class *dsmark;
    231 
    232 	if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
    233 		return -NLE_NOMEM;
    234 
    235 	dsmark->cdm_value = value;
    236 	dsmark->cdm_mask |= SCH_DSMARK_ATTR_VALUE;
    237 
    238 	return 0;
    239 }
    240 
    241 /**
    242  * Get value of DSMARK class.
    243  * @arg class		DSMARK class.
    244  * @return Value or a negative error code.
    245  */
    246 int rtnl_class_dsmark_get_value(struct rtnl_class *class)
    247 {
    248 	struct rtnl_dsmark_class *dsmark;
    249 
    250 	if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
    251 		return -NLE_NOMEM;
    252 
    253 	if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
    254 		return dsmark->cdm_value;
    255 	else
    256 		return -NLE_NOATTR;
    257 }
    258 
    259 /** @} */
    260 
    261 /**
    262  * @name Qdisc Attribute Access
    263  * @{
    264  */
    265 
    266 /**
    267  * Set indices of DSMARK qdisc.
    268  * @arg qdisc		DSMARK qdisc to be modified.
    269  * @arg indices		New indices.
    270  */
    271 int rtnl_qdisc_dsmark_set_indices(struct rtnl_qdisc *qdisc, uint16_t indices)
    272 {
    273 	struct rtnl_dsmark_qdisc *dsmark;
    274 
    275 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
    276 		return -NLE_NOMEM;
    277 
    278 	dsmark->qdm_indices = indices;
    279 	dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES;
    280 
    281 	return 0;
    282 }
    283 
    284 /**
    285  * Get indices of DSMARK qdisc.
    286  * @arg qdisc		DSMARK qdisc.
    287  * @return Indices or a negative error code.
    288  */
    289 int rtnl_qdisc_dsmark_get_indices(struct rtnl_qdisc *qdisc)
    290 {
    291 	struct rtnl_dsmark_qdisc *dsmark;
    292 
    293 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
    294 		return -NLE_NOMEM;
    295 
    296 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
    297 		return dsmark->qdm_indices;
    298 	else
    299 		return -NLE_NOATTR;
    300 }
    301 
    302 /**
    303  * Set default index of DSMARK qdisc.
    304  * @arg qdisc		DSMARK qdisc to be modified.
    305  * @arg default_index	New default index.
    306  * @return 0 on success or a negative error code.
    307  */
    308 int rtnl_qdisc_dsmark_set_default_index(struct rtnl_qdisc *qdisc,
    309 					uint16_t default_index)
    310 {
    311 	struct rtnl_dsmark_qdisc *dsmark;
    312 
    313 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
    314 		return -NLE_NOMEM;
    315 
    316 	dsmark->qdm_default_index = default_index;
    317 	dsmark->qdm_mask |= SCH_DSMARK_ATTR_DEFAULT_INDEX;
    318 
    319 	return 0;
    320 }
    321 
    322 /**
    323  * Get default index of DSMARK qdisc.
    324  * @arg qdisc		DSMARK qdisc.
    325  * @return Default index or a negative error code.
    326  */
    327 int rtnl_qdisc_dsmark_get_default_index(struct rtnl_qdisc *qdisc)
    328 {
    329 	struct rtnl_dsmark_qdisc *dsmark;
    330 
    331 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
    332 		return -NLE_NOMEM;
    333 
    334 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
    335 		return dsmark->qdm_default_index;
    336 	else
    337 		return -NLE_NOATTR;
    338 }
    339 
    340 /**
    341  * Set set-tc-index flag of DSMARK qdisc.
    342  * @arg qdisc		DSMARK qdisc to be modified.
    343  * @arg flag		Flag indicating whether to enable or disable.
    344  * @return 0 on success or a negative error code.
    345  */
    346 int rtnl_qdisc_dsmark_set_set_tc_index(struct rtnl_qdisc *qdisc, int flag)
    347 {
    348 	struct rtnl_dsmark_qdisc *dsmark;
    349 
    350 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
    351 		return -NLE_NOMEM;
    352 
    353 	dsmark->qdm_set_tc_index = !!flag;
    354 	dsmark->qdm_mask |= SCH_DSMARK_ATTR_SET_TC_INDEX;
    355 
    356 	return 0;
    357 }
    358 
    359 /**
    360  * Get set-tc-index flag of DSMARK qdisc.
    361  * @arg qdisc		DSMARK qdisc to be modified.
    362  * @return 1 or 0 to indicate wehther the flag is enabled or a negative
    363  *         error code.
    364  */
    365 int rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc *qdisc)
    366 {
    367 	struct rtnl_dsmark_qdisc *dsmark;
    368 
    369 	if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
    370 		return -NLE_NOMEM;
    371 
    372 	if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
    373 		return dsmark->qdm_set_tc_index;
    374 	else
    375 		return -NLE_NOATTR;
    376 }
    377 
    378 /** @} */
    379 
    380 static struct rtnl_tc_ops dsmark_qdisc_ops = {
    381 	.to_kind		= "dsmark",
    382 	.to_type		= RTNL_TC_TYPE_QDISC,
    383 	.to_size		= sizeof(struct rtnl_dsmark_qdisc),
    384 	.to_msg_parser		= dsmark_qdisc_msg_parser,
    385 	.to_dump = {
    386 	    [NL_DUMP_LINE]	= dsmark_qdisc_dump_line,
    387 	    [NL_DUMP_DETAILS]	= dsmark_qdisc_dump_details,
    388 	},
    389 	.to_msg_fill		= dsmark_qdisc_msg_fill,
    390 };
    391 
    392 static struct rtnl_tc_ops dsmark_class_ops = {
    393 	.to_kind		= "dsmark",
    394 	.to_type		= RTNL_TC_TYPE_CLASS,
    395 	.to_size		= sizeof(struct rtnl_dsmark_class),
    396 	.to_msg_parser		= dsmark_class_msg_parser,
    397 	.to_dump[NL_DUMP_LINE]	= dsmark_class_dump_line,
    398 	.to_msg_fill		= dsmark_class_msg_fill,
    399 };
    400 
    401 static void __init dsmark_init(void)
    402 {
    403 	rtnl_tc_register(&dsmark_qdisc_ops);
    404 	rtnl_tc_register(&dsmark_class_ops);
    405 }
    406 
    407 static void __exit dsmark_exit(void)
    408 {
    409 	rtnl_tc_unregister(&dsmark_qdisc_ops);
    410 	rtnl_tc_unregister(&dsmark_class_ops);
    411 }
    412 
    413 /** @} */
    414