00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <netlink-local.h>
00020 #include <netlink-tc.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/utils.h>
00023 #include <netlink/route/qdisc.h>
00024 #include <netlink/route/qdisc-modules.h>
00025 #include <netlink/route/class.h>
00026 #include <netlink/route/class-modules.h>
00027 #include <netlink/route/sch/dsmark.h>
00028
00029
00030 #define SCH_DSMARK_ATTR_INDICES 0x1
00031 #define SCH_DSMARK_ATTR_DEFAULT_INDEX 0x2
00032 #define SCH_DSMARK_ATTR_SET_TC_INDEX 0x4
00033
00034 #define SCH_DSMARK_ATTR_MASK 0x1
00035 #define SCH_DSMARK_ATTR_VALUE 0x2
00036
00037
00038 static inline struct rtnl_dsmark_qdisc *dsmark_qdisc(struct rtnl_qdisc *qdisc)
00039 {
00040 return (struct rtnl_dsmark_qdisc *) qdisc->q_subdata;
00041 }
00042
00043 static inline struct rtnl_dsmark_qdisc *
00044 dsmark_qdisc_alloc(struct rtnl_qdisc *qdisc)
00045 {
00046 if (!qdisc->q_subdata)
00047 qdisc->q_subdata = calloc(1, sizeof(struct rtnl_dsmark_qdisc));
00048
00049 return dsmark_qdisc(qdisc);
00050 }
00051
00052 static struct nla_policy dsmark_policy[TCA_DSMARK_MAX+1] = {
00053 [TCA_DSMARK_INDICES] = { .type = NLA_U16 },
00054 [TCA_DSMARK_DEFAULT_INDEX] = { .type = NLA_U16 },
00055 [TCA_DSMARK_SET_TC_INDEX] = { .type = NLA_FLAG },
00056 [TCA_DSMARK_VALUE] = { .type = NLA_U8 },
00057 [TCA_DSMARK_MASK] = { .type = NLA_U8 },
00058 };
00059
00060 static int dsmark_qdisc_msg_parser(struct rtnl_qdisc *qdisc)
00061 {
00062 int err;
00063 struct nlattr *tb[TCA_DSMARK_MAX + 1];
00064 struct rtnl_dsmark_qdisc *dsmark;
00065
00066 err = tca_parse(tb, TCA_DSMARK_MAX, (struct rtnl_tca *) qdisc,
00067 dsmark_policy);
00068 if (err < 0)
00069 return err;
00070
00071 dsmark = dsmark_qdisc_alloc(qdisc);
00072 if (!dsmark)
00073 return -NLE_NOMEM;
00074
00075 if (tb[TCA_DSMARK_INDICES]) {
00076 dsmark->qdm_indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
00077 dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES;
00078 }
00079
00080 if (tb[TCA_DSMARK_DEFAULT_INDEX]) {
00081 dsmark->qdm_default_index =
00082 nla_get_u16(tb[TCA_DSMARK_DEFAULT_INDEX]);
00083 dsmark->qdm_mask |= SCH_DSMARK_ATTR_DEFAULT_INDEX;
00084 }
00085
00086 if (tb[TCA_DSMARK_SET_TC_INDEX]) {
00087 dsmark->qdm_set_tc_index = 1;
00088 dsmark->qdm_mask |= SCH_DSMARK_ATTR_SET_TC_INDEX;
00089 }
00090
00091 return 0;
00092 }
00093
00094 static inline struct rtnl_dsmark_class *dsmark_class(struct rtnl_class *class)
00095 {
00096 return (struct rtnl_dsmark_class *) class->c_subdata;
00097 }
00098
00099 static inline struct rtnl_dsmark_class *
00100 dsmark_class_alloc(struct rtnl_class *class)
00101 {
00102 if (!class->c_subdata)
00103 class->c_subdata = calloc(1, sizeof(struct rtnl_dsmark_class));
00104
00105 return dsmark_class(class);
00106 }
00107
00108 static int dsmark_class_msg_parser(struct rtnl_class *class)
00109 {
00110 int err;
00111 struct nlattr *tb[TCA_DSMARK_MAX + 1];
00112 struct rtnl_dsmark_class *dsmark;
00113
00114 err = tca_parse(tb, TCA_DSMARK_MAX, (struct rtnl_tca *) class,
00115 dsmark_policy);
00116 if (err < 0)
00117 return err;
00118
00119 dsmark = dsmark_class_alloc(class);
00120 if (!dsmark)
00121 return -NLE_NOMEM;
00122
00123 if (tb[TCA_DSMARK_MASK]) {
00124 dsmark->cdm_bmask = nla_get_u8(tb[TCA_DSMARK_MASK]);
00125 dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK;
00126 }
00127
00128 if (tb[TCA_DSMARK_VALUE]) {
00129 dsmark->cdm_value = nla_get_u8(tb[TCA_DSMARK_VALUE]);
00130 dsmark->cdm_mask |= SCH_DSMARK_ATTR_VALUE;
00131 }
00132
00133 return 0;
00134 }
00135
00136 static void dsmark_qdisc_dump_line(struct rtnl_qdisc *qdisc,
00137 struct nl_dump_params *p)
00138 {
00139 struct rtnl_dsmark_qdisc *dsmark = dsmark_qdisc(qdisc);
00140
00141 if (dsmark && (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES))
00142 nl_dump(p, " indices 0x%04x", dsmark->qdm_indices);
00143 }
00144
00145 static void dsmark_qdisc_dump_details(struct rtnl_qdisc *qdisc,
00146 struct nl_dump_params *p)
00147 {
00148 struct rtnl_dsmark_qdisc *dsmark = dsmark_qdisc(qdisc);
00149
00150 if (!dsmark)
00151 return;
00152
00153 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
00154 nl_dump(p, " default index 0x%04x", dsmark->qdm_default_index);
00155
00156 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
00157 nl_dump(p, " set-tc-index");
00158 }
00159
00160 static void dsmark_class_dump_line(struct rtnl_class *class,
00161 struct nl_dump_params *p)
00162 {
00163 struct rtnl_dsmark_class *dsmark = dsmark_class(class);
00164
00165 if (!dsmark)
00166 return;
00167
00168 if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
00169 nl_dump(p, " value 0x%02x", dsmark->cdm_value);
00170
00171 if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
00172 nl_dump(p, " mask 0x%02x", dsmark->cdm_bmask);
00173 }
00174
00175 static struct nl_msg *dsmark_qdisc_get_opts(struct rtnl_qdisc *qdisc)
00176 {
00177 struct rtnl_dsmark_qdisc *dsmark = dsmark_qdisc(qdisc);
00178 struct nl_msg *msg;
00179
00180 if (!dsmark)
00181 return NULL;
00182
00183 msg = nlmsg_alloc();
00184 if (!msg)
00185 goto nla_put_failure;
00186
00187 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
00188 NLA_PUT_U16(msg, TCA_DSMARK_INDICES, dsmark->qdm_indices);
00189
00190 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
00191 NLA_PUT_U16(msg, TCA_DSMARK_DEFAULT_INDEX,
00192 dsmark->qdm_default_index);
00193
00194 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
00195 NLA_PUT_FLAG(msg, TCA_DSMARK_SET_TC_INDEX);
00196
00197 return msg;
00198
00199 nla_put_failure:
00200 nlmsg_free(msg);
00201 return NULL;
00202 }
00203
00204 static struct nl_msg *dsmark_class_get_opts(struct rtnl_class *class)
00205 {
00206 struct rtnl_dsmark_class *dsmark = dsmark_class(class);
00207 struct nl_msg *msg;
00208
00209 if (!dsmark)
00210 return NULL;
00211
00212 msg = nlmsg_alloc();
00213 if (!msg)
00214 goto nla_put_failure;
00215
00216 if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
00217 NLA_PUT_U8(msg, TCA_DSMARK_MASK, dsmark->cdm_bmask);
00218
00219 if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
00220 NLA_PUT_U8(msg, TCA_DSMARK_VALUE, dsmark->cdm_value);
00221
00222 return msg;
00223
00224 nla_put_failure:
00225 nlmsg_free(msg);
00226 return NULL;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 int rtnl_class_dsmark_set_bitmask(struct rtnl_class *class, uint8_t mask)
00241 {
00242 struct rtnl_dsmark_class *dsmark;
00243
00244 dsmark = dsmark_class(class);
00245 if (!dsmark)
00246 return -NLE_NOMEM;
00247
00248 dsmark->cdm_bmask = mask;
00249 dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK;
00250
00251 return 0;
00252 }
00253
00254
00255
00256
00257
00258
00259 int rtnl_class_dsmark_get_bitmask(struct rtnl_class *class)
00260 {
00261 struct rtnl_dsmark_class *dsmark;
00262
00263 dsmark = dsmark_class(class);
00264 if (dsmark && dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
00265 return dsmark->cdm_bmask;
00266 else
00267 return -NLE_NOATTR;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276 int rtnl_class_dsmark_set_value(struct rtnl_class *class, uint8_t value)
00277 {
00278 struct rtnl_dsmark_class *dsmark;
00279
00280 dsmark = dsmark_class(class);
00281 if (!dsmark)
00282 return -NLE_NOMEM;
00283
00284 dsmark->cdm_value = value;
00285 dsmark->cdm_mask |= SCH_DSMARK_ATTR_VALUE;
00286
00287 return 0;
00288 }
00289
00290
00291
00292
00293
00294
00295 int rtnl_class_dsmark_get_value(struct rtnl_class *class)
00296 {
00297 struct rtnl_dsmark_class *dsmark;
00298
00299 dsmark = dsmark_class(class);
00300 if (dsmark && dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
00301 return dsmark->cdm_value;
00302 else
00303 return -NLE_NOATTR;
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 int rtnl_qdisc_dsmark_set_indices(struct rtnl_qdisc *qdisc, uint16_t indices)
00319 {
00320 struct rtnl_dsmark_qdisc *dsmark;
00321
00322 dsmark = dsmark_qdisc(qdisc);
00323 if (!dsmark)
00324 return -NLE_NOMEM;
00325
00326 dsmark->qdm_indices = indices;
00327 dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES;
00328
00329 return 0;
00330 }
00331
00332
00333
00334
00335
00336
00337 int rtnl_qdisc_dsmark_get_indices(struct rtnl_qdisc *qdisc)
00338 {
00339 struct rtnl_dsmark_qdisc *dsmark;
00340
00341 dsmark = dsmark_qdisc(qdisc);
00342 if (dsmark && dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
00343 return dsmark->qdm_indices;
00344 else
00345 return -NLE_NOATTR;
00346 }
00347
00348
00349
00350
00351
00352
00353
00354 int rtnl_qdisc_dsmark_set_default_index(struct rtnl_qdisc *qdisc,
00355 uint16_t default_index)
00356 {
00357 struct rtnl_dsmark_qdisc *dsmark;
00358
00359 dsmark = dsmark_qdisc(qdisc);
00360 if (!dsmark)
00361 return -NLE_NOMEM;
00362
00363 dsmark->qdm_default_index = default_index;
00364 dsmark->qdm_mask |= SCH_DSMARK_ATTR_DEFAULT_INDEX;
00365
00366 return 0;
00367 }
00368
00369
00370
00371
00372
00373
00374 int rtnl_qdisc_dsmark_get_default_index(struct rtnl_qdisc *qdisc)
00375 {
00376 struct rtnl_dsmark_qdisc *dsmark;
00377
00378 dsmark = dsmark_qdisc(qdisc);
00379 if (dsmark && dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
00380 return dsmark->qdm_default_index;
00381 else
00382 return -NLE_NOATTR;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391 int rtnl_qdisc_dsmark_set_set_tc_index(struct rtnl_qdisc *qdisc, int flag)
00392 {
00393 struct rtnl_dsmark_qdisc *dsmark;
00394
00395 dsmark = dsmark_qdisc(qdisc);
00396 if (!dsmark)
00397 return -NLE_NOMEM;
00398
00399 dsmark->qdm_set_tc_index = !!flag;
00400 dsmark->qdm_mask |= SCH_DSMARK_ATTR_SET_TC_INDEX;
00401
00402 return 0;
00403 }
00404
00405
00406
00407
00408
00409
00410
00411 int rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc *qdisc)
00412 {
00413 struct rtnl_dsmark_qdisc *dsmark;
00414
00415 dsmark = dsmark_qdisc(qdisc);
00416 if (dsmark && dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
00417 return dsmark->qdm_set_tc_index;
00418 else
00419 return -NLE_NOATTR;
00420 }
00421
00422
00423
00424 static struct rtnl_qdisc_ops dsmark_qdisc_ops = {
00425 .qo_kind = "dsmark",
00426 .qo_msg_parser = dsmark_qdisc_msg_parser,
00427 .qo_dump = {
00428 [NL_DUMP_LINE] = dsmark_qdisc_dump_line,
00429 [NL_DUMP_DETAILS] = dsmark_qdisc_dump_details,
00430 },
00431 .qo_get_opts = dsmark_qdisc_get_opts,
00432 };
00433
00434 static struct rtnl_class_ops dsmark_class_ops = {
00435 .co_kind = "dsmark",
00436 .co_msg_parser = dsmark_class_msg_parser,
00437 .co_dump[NL_DUMP_LINE] = dsmark_class_dump_line,
00438 .co_get_opts = dsmark_class_get_opts,
00439 };
00440
00441 static void __init dsmark_init(void)
00442 {
00443 rtnl_qdisc_register(&dsmark_qdisc_ops);
00444 rtnl_class_register(&dsmark_class_ops);
00445 }
00446
00447 static void __exit dsmark_exit(void)
00448 {
00449 rtnl_qdisc_unregister(&dsmark_qdisc_ops);
00450 rtnl_class_unregister(&dsmark_class_ops);
00451 }
00452
00453