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