libnl 1.1

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-2006 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 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  * @name Class Attribute Access
00239  * @{
00240  */
00241 
00242 /**
00243  * Set bitmask of DSMARK class.
00244  * @arg class           DSMARK class to be modified.
00245  * @arg mask            New bitmask.
00246  * @return 0 on success or a negative error code.
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  * Get bitmask of DSMARK class.
00264  * @arg class           DSMARK class.
00265  * @return Bitmask or a negative error code.
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  * Set value of DSMARK class.
00280  * @arg class           DSMARK class to be modified.
00281  * @arg value           New value.
00282  * @return 0 on success or a negative errror code.
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  * Get value of DSMARK class.
00300  * @arg class           DSMARK class.
00301  * @return Value or a negative error code.
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  * @name Qdisc Attribute Access
00318  * @{
00319  */
00320 
00321 /**
00322  * Set indices of DSMARK qdisc.
00323  * @arg qdisc           DSMARK qdisc to be modified.
00324  * @arg indices         New indices.
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  * Get indices of DSMARK qdisc.
00342  * @arg qdisc           DSMARK qdisc.
00343  * @return Indices or a negative error code.
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  * Set default index of DSMARK qdisc.
00358  * @arg qdisc           DSMARK qdisc to be modified.
00359  * @arg default_index   New default index.
00360  * @return 0 on success or a negative error code.
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  * Get default index of DSMARK qdisc.
00379  * @arg qdisc           DSMARK qdisc.
00380  * @return Default index or a negative error code.
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  * Set set-tc-index flag of DSMARK qdisc.
00395  * @arg qdisc           DSMARK qdisc to be modified.
00396  * @arg flag            Flag indicating whether to enable or disable.
00397  * @return 0 on success or a negative error code.
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  * Get set-tc-index flag of DSMARK qdisc.
00415  * @arg qdisc           DSMARK qdisc to be modified.
00416  * @return 1 or 0 to indicate wehther the flag is enabled or a negative
00417  *         error code.
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 /** @} */