libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/route/qdisc/dsmark.c
00001 /*
00002  * lib/route/qdisc/dsmark.c     DSMARK
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup qdisc
00014  * @ingroup class
00015  * @defgroup qdisc_dsmark Differentiated Services Marker (DSMARK)
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 /** @cond SKIP */
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 /** @endcond */
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  * @name Class Attribute Access
00182  * @{
00183  */
00184 
00185 /**
00186  * Set bitmask of DSMARK class.
00187  * @arg class           DSMARK class to be modified.
00188  * @arg mask            New bitmask.
00189  * @return 0 on success or a negative error code.
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  * Get bitmask of DSMARK class.
00206  * @arg class           DSMARK class.
00207  * @return Bitmask or a negative error code.
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  * Set value of DSMARK class.
00224  * @arg class           DSMARK class to be modified.
00225  * @arg value           New value.
00226  * @return 0 on success or a negative errror code.
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  * Get value of DSMARK class.
00243  * @arg class           DSMARK class.
00244  * @return Value or a negative error code.
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  * @name Qdisc Attribute Access
00263  * @{
00264  */
00265 
00266 /**
00267  * Set indices of DSMARK qdisc.
00268  * @arg qdisc           DSMARK qdisc to be modified.
00269  * @arg indices         New indices.
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  * Get indices of DSMARK qdisc.
00286  * @arg qdisc           DSMARK qdisc.
00287  * @return Indices or a negative error code.
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  * Set default index of DSMARK qdisc.
00304  * @arg qdisc           DSMARK qdisc to be modified.
00305  * @arg default_index   New default index.
00306  * @return 0 on success or a negative error code.
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  * Get default index of DSMARK qdisc.
00324  * @arg qdisc           DSMARK qdisc.
00325  * @return Default index or a negative error code.
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  * Set set-tc-index flag of DSMARK qdisc.
00342  * @arg qdisc           DSMARK qdisc to be modified.
00343  * @arg flag            Flag indicating whether to enable or disable.
00344  * @return 0 on success or a negative error code.
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  * Get set-tc-index flag of DSMARK qdisc.
00361  * @arg qdisc           DSMARK qdisc to be modified.
00362  * @return 1 or 0 to indicate wehther the flag is enabled or a negative
00363  *         error code.
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 /** @} */