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 nl_errno(ENOMEM);
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 nl_errno(ENOMEM);
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 int dsmark_qdisc_dump_brief(struct rtnl_qdisc *qdisc,
00137 struct nl_dump_params *p, int line)
00138 {
00139 struct rtnl_dsmark_qdisc *dsmark = dsmark_qdisc(qdisc);
00140
00141 if (dsmark && (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES))
00142 dp_dump(p, " indices 0x%04x", dsmark->qdm_indices);
00143
00144 return line;
00145 }
00146
00147 static int dsmark_qdisc_dump_full(struct rtnl_qdisc *qdisc,
00148 struct nl_dump_params *p, int line)
00149 {
00150 struct rtnl_dsmark_qdisc *dsmark = dsmark_qdisc(qdisc);
00151
00152 if (!dsmark)
00153 goto ignore;
00154
00155 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
00156 dp_dump(p, " default index 0x%04x", dsmark->qdm_default_index);
00157
00158 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
00159 dp_dump(p, " set-tc-index");
00160
00161 ignore:
00162 return line;
00163 }
00164
00165 static int dsmark_class_dump_brief(struct rtnl_class *class,
00166 struct nl_dump_params *p, int line)
00167 {
00168 struct rtnl_dsmark_class *dsmark = dsmark_class(class);
00169
00170 if (!dsmark)
00171 goto ignore;
00172
00173 if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
00174 dp_dump(p, " value 0x%02x", dsmark->cdm_value);
00175
00176 if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
00177 dp_dump(p, " mask 0x%02x", dsmark->cdm_bmask);
00178
00179 ignore:
00180 return line;
00181 }
00182
00183 static struct nl_msg *dsmark_qdisc_get_opts(struct rtnl_qdisc *qdisc)
00184 {
00185 struct rtnl_dsmark_qdisc *dsmark = dsmark_qdisc(qdisc);
00186 struct nl_msg *msg;
00187
00188 if (!dsmark)
00189 return NULL;
00190
00191 msg = nlmsg_alloc();
00192 if (!msg)
00193 goto nla_put_failure;
00194
00195 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
00196 NLA_PUT_U16(msg, TCA_DSMARK_INDICES, dsmark->qdm_indices);
00197
00198 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
00199 NLA_PUT_U16(msg, TCA_DSMARK_DEFAULT_INDEX,
00200 dsmark->qdm_default_index);
00201
00202 if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
00203 NLA_PUT_FLAG(msg, TCA_DSMARK_SET_TC_INDEX);
00204
00205 return msg;
00206
00207 nla_put_failure:
00208 nlmsg_free(msg);
00209 return NULL;
00210 }
00211
00212 static struct nl_msg *dsmark_class_get_opts(struct rtnl_class *class)
00213 {
00214 struct rtnl_dsmark_class *dsmark = dsmark_class(class);
00215 struct nl_msg *msg;
00216
00217 if (!dsmark)
00218 return NULL;
00219
00220 msg = nlmsg_alloc();
00221 if (!msg)
00222 goto nla_put_failure;
00223
00224 if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
00225 NLA_PUT_U8(msg, TCA_DSMARK_MASK, dsmark->cdm_bmask);
00226
00227 if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
00228 NLA_PUT_U8(msg, TCA_DSMARK_VALUE, dsmark->cdm_value);
00229
00230 return msg;
00231
00232 nla_put_failure:
00233 nlmsg_free(msg);
00234 return NULL;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 int rtnl_class_dsmark_set_bitmask(struct rtnl_class *class, uint8_t mask)
00249 {
00250 struct rtnl_dsmark_class *dsmark;
00251
00252 dsmark = dsmark_class(class);
00253 if (!dsmark)
00254 return nl_errno(ENOMEM);
00255
00256 dsmark->cdm_bmask = mask;
00257 dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK;
00258
00259 return 0;
00260 }
00261
00262
00263
00264
00265
00266
00267 int rtnl_class_dsmark_get_bitmask(struct rtnl_class *class)
00268 {
00269 struct rtnl_dsmark_class *dsmark;
00270
00271 dsmark = dsmark_class(class);
00272 if (dsmark && dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
00273 return dsmark->cdm_bmask;
00274 else
00275 return nl_errno(ENOENT);
00276 }
00277
00278
00279
00280
00281
00282
00283
00284 int rtnl_class_dsmark_set_value(struct rtnl_class *class, uint8_t value)
00285 {
00286 struct rtnl_dsmark_class *dsmark;
00287
00288 dsmark = dsmark_class(class);
00289 if (!dsmark)
00290 return nl_errno(ENOMEM);
00291
00292 dsmark->cdm_value = value;
00293 dsmark->cdm_mask |= SCH_DSMARK_ATTR_VALUE;
00294
00295 return 0;
00296 }
00297
00298
00299
00300
00301
00302
00303 int rtnl_class_dsmark_get_value(struct rtnl_class *class)
00304 {
00305 struct rtnl_dsmark_class *dsmark;
00306
00307 dsmark = dsmark_class(class);
00308 if (dsmark && dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
00309 return dsmark->cdm_value;
00310 else
00311 return nl_errno(ENOENT);
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 int rtnl_qdisc_dsmark_set_indices(struct rtnl_qdisc *qdisc, uint16_t indices)
00327 {
00328 struct rtnl_dsmark_qdisc *dsmark;
00329
00330 dsmark = dsmark_qdisc(qdisc);
00331 if (!dsmark)
00332 return nl_errno(ENOMEM);
00333
00334 dsmark->qdm_indices = indices;
00335 dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES;
00336
00337 return 0;
00338 }
00339
00340
00341
00342
00343
00344
00345 int rtnl_qdisc_dsmark_get_indices(struct rtnl_qdisc *qdisc)
00346 {
00347 struct rtnl_dsmark_qdisc *dsmark;
00348
00349 dsmark = dsmark_qdisc(qdisc);
00350 if (dsmark && dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
00351 return dsmark->qdm_indices;
00352 else
00353 return nl_errno(ENOENT);
00354 }
00355
00356
00357
00358
00359
00360
00361
00362 int rtnl_qdisc_dsmark_set_default_index(struct rtnl_qdisc *qdisc,
00363 uint16_t default_index)
00364 {
00365 struct rtnl_dsmark_qdisc *dsmark;
00366
00367 dsmark = dsmark_qdisc(qdisc);
00368 if (!dsmark)
00369 return nl_errno(ENOMEM);
00370
00371 dsmark->qdm_default_index = default_index;
00372 dsmark->qdm_mask |= SCH_DSMARK_ATTR_DEFAULT_INDEX;
00373
00374 return 0;
00375 }
00376
00377
00378
00379
00380
00381
00382 int rtnl_qdisc_dsmark_get_default_index(struct rtnl_qdisc *qdisc)
00383 {
00384 struct rtnl_dsmark_qdisc *dsmark;
00385
00386 dsmark = dsmark_qdisc(qdisc);
00387 if (dsmark && dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
00388 return dsmark->qdm_default_index;
00389 else
00390 return nl_errno(ENOENT);
00391 }
00392
00393
00394
00395
00396
00397
00398
00399 int rtnl_qdisc_dsmark_set_set_tc_index(struct rtnl_qdisc *qdisc, int flag)
00400 {
00401 struct rtnl_dsmark_qdisc *dsmark;
00402
00403 dsmark = dsmark_qdisc(qdisc);
00404 if (!dsmark)
00405 return nl_errno(ENOMEM);
00406
00407 dsmark->qdm_set_tc_index = !!flag;
00408 dsmark->qdm_mask |= SCH_DSMARK_ATTR_SET_TC_INDEX;
00409
00410 return 0;
00411 }
00412
00413
00414
00415
00416
00417
00418
00419 int rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc *qdisc)
00420 {
00421 struct rtnl_dsmark_qdisc *dsmark;
00422
00423 dsmark = dsmark_qdisc(qdisc);
00424 if (dsmark && dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
00425 return dsmark->qdm_set_tc_index;
00426 else
00427 return nl_errno(ENOENT);
00428 }
00429
00430
00431
00432 static struct rtnl_qdisc_ops dsmark_qdisc_ops = {
00433 .qo_kind = "dsmark",
00434 .qo_msg_parser = dsmark_qdisc_msg_parser,
00435 .qo_dump[NL_DUMP_BRIEF] = dsmark_qdisc_dump_brief,
00436 .qo_dump[NL_DUMP_FULL] = dsmark_qdisc_dump_full,
00437 .qo_get_opts = dsmark_qdisc_get_opts,
00438 };
00439
00440 static struct rtnl_class_ops dsmark_class_ops = {
00441 .co_kind = "dsmark",
00442 .co_msg_parser = dsmark_class_msg_parser,
00443 .co_dump[NL_DUMP_BRIEF] = dsmark_class_dump_brief,
00444 .co_get_opts = dsmark_class_get_opts,
00445 };
00446
00447 static void __init dsmark_init(void)
00448 {
00449 rtnl_qdisc_register(&dsmark_qdisc_ops);
00450 rtnl_class_register(&dsmark_class_ops);
00451 }
00452
00453 static void __exit dsmark_exit(void)
00454 {
00455 rtnl_qdisc_unregister(&dsmark_qdisc_ops);
00456 rtnl_class_unregister(&dsmark_class_ops);
00457 }
00458
00459