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