libnl 2.0

/build/buildd/libnl2-2.0/lib/route/sch/dsmark.c

00001 /*
00002  * lib/route/sch/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-2008 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup qdisc_api
00014  * @ingroup class_api
00015  * @defgroup 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/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 /** @cond SKIP */
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 /** @endcond */
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  * @name Class Attribute Access
00231  * @{
00232  */
00233 
00234 /**
00235  * Set bitmask of DSMARK class.
00236  * @arg class           DSMARK class to be modified.
00237  * @arg mask            New bitmask.
00238  * @return 0 on success or a negative error code.
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  * Get bitmask of DSMARK class.
00256  * @arg class           DSMARK class.
00257  * @return Bitmask or a negative error code.
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  * Set value of DSMARK class.
00272  * @arg class           DSMARK class to be modified.
00273  * @arg value           New value.
00274  * @return 0 on success or a negative errror code.
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  * Get value of DSMARK class.
00292  * @arg class           DSMARK class.
00293  * @return Value or a negative error code.
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  * @name Qdisc Attribute Access
00310  * @{
00311  */
00312 
00313 /**
00314  * Set indices of DSMARK qdisc.
00315  * @arg qdisc           DSMARK qdisc to be modified.
00316  * @arg indices         New indices.
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  * Get indices of DSMARK qdisc.
00334  * @arg qdisc           DSMARK qdisc.
00335  * @return Indices or a negative error code.
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  * Set default index of DSMARK qdisc.
00350  * @arg qdisc           DSMARK qdisc to be modified.
00351  * @arg default_index   New default index.
00352  * @return 0 on success or a negative error code.
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  * Get default index of DSMARK qdisc.
00371  * @arg qdisc           DSMARK qdisc.
00372  * @return Default index or a negative error code.
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  * Set set-tc-index flag of DSMARK qdisc.
00387  * @arg qdisc           DSMARK qdisc to be modified.
00388  * @arg flag            Flag indicating whether to enable or disable.
00389  * @return 0 on success or a negative error code.
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  * Get set-tc-index flag of DSMARK qdisc.
00407  * @arg qdisc           DSMARK qdisc to be modified.
00408  * @return 1 or 0 to indicate wehther the flag is enabled or a negative
00409  *         error code.
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 /** @} */