libnl 2.0

/build/buildd/libnl2-2.0/lib/route/cls/basic.c

00001 /*
00002  * lib/route/cls/basic.c        Basic Classifier
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) 2008-2009 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup cls
00014  * @defgroup basic Basic Classifier
00015  *
00016  * @par Introduction
00017  * The basic classifier is the simplest form of a classifier. It does
00018  * not have any special classification capabilities, instead it can be
00019  * used to classify exclusively based on extended matches or to
00020  * create a "catch-all" filter.
00021  *
00022  * @{
00023  */
00024 
00025 #include <netlink-local.h>
00026 #include <netlink-tc.h>
00027 #include <netlink/netlink.h>
00028 #include <netlink/route/classifier.h>
00029 #include <netlink/route/classifier-modules.h>
00030 #include <netlink/route/cls/basic.h>
00031 #include <netlink/route/cls/ematch.h>
00032 
00033 struct rtnl_basic
00034 {
00035         uint32_t                        b_classid;
00036         struct rtnl_ematch_tree *       b_ematch;
00037         int                             b_mask;
00038 };
00039 
00040 /** @cond SKIP */
00041 #define BASIC_ATTR_CLASSID      0x001
00042 #define BASIC_ATTR_EMATCH       0x002
00043 /** @endcond */
00044 
00045 static struct nla_policy basic_policy[TCA_FW_MAX+1] = {
00046         [TCA_BASIC_CLASSID]     = { .type = NLA_U32 },
00047         [TCA_BASIC_EMATCHES]    = { .type = NLA_NESTED },
00048         [TCA_BASIC_ACT]         = { .type = NLA_NESTED },
00049         [TCA_BASIC_POLICE]      = { .type = NLA_NESTED },
00050 };
00051 
00052 static int basic_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
00053 {
00054         return -NLE_OPNOTSUPP;
00055 }
00056 
00057 static void basic_free_data(struct rtnl_cls *cls)
00058 {
00059         struct rtnl_basic *basic = rtnl_cls_data(cls);
00060 
00061         rtnl_ematch_tree_free(basic->b_ematch);
00062 }
00063 
00064 static int basic_msg_parser(struct rtnl_cls *cls)
00065 {
00066         struct nlattr *tb[TCA_BASIC_MAX + 1];
00067         struct rtnl_basic *basic = rtnl_cls_data(cls);
00068         int err;
00069 
00070         err = tca_parse(tb, TCA_BASIC_MAX, (struct rtnl_tca *) cls, basic_policy);
00071         if (err < 0)
00072                 return err;
00073 
00074         if (tb[TCA_BASIC_CLASSID]) {
00075                 basic->b_classid = nla_get_u32(tb[TCA_BASIC_CLASSID]);
00076                 basic->b_mask |= BASIC_ATTR_CLASSID;
00077         }
00078 
00079         if (tb[TCA_BASIC_EMATCHES]) {
00080                 if ((err = rtnl_ematch_parse(tb[TCA_BASIC_EMATCHES],
00081                                              &basic->b_ematch)) < 0)
00082                         return err;
00083 
00084                 if (basic->b_ematch)
00085                         basic->b_mask |= BASIC_ATTR_EMATCH;
00086         }
00087 
00088         if (tb[TCA_BASIC_ACT]) {
00089                 /* XXX */
00090         }
00091 
00092         if (tb[TCA_BASIC_POLICE]) {
00093                 /* XXX */
00094         }
00095 
00096         return 0;
00097 }
00098 
00099 static void basic_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
00100 {
00101         struct rtnl_basic *b = rtnl_cls_data(cls);
00102         char buf[32];
00103 
00104         if (b->b_mask & BASIC_ATTR_EMATCH)
00105                 nl_dump(p, " ematch");
00106         else
00107                 nl_dump(p, " match-all");
00108 
00109         if (b->b_mask & BASIC_ATTR_CLASSID)
00110                 nl_dump(p, " classify-to %s",
00111                         rtnl_tc_handle2str(b->b_classid, buf, sizeof(buf)));
00112 }
00113 
00114 static void basic_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
00115 {
00116         struct rtnl_basic *b = rtnl_cls_data(cls);
00117 
00118         if (b->b_mask & BASIC_ATTR_EMATCH) {
00119                 nl_dump(p, "\n");
00120                 nl_dump_line(p, "    ematch ");
00121                 rtnl_ematch_tree_dump(b->b_ematch, p);
00122         } else
00123                 nl_dump(p, "no options.\n");
00124 }
00125 
00126 static int basic_get_opts(struct rtnl_cls *cls, struct nl_msg *msg)
00127 {
00128         struct rtnl_basic *b = rtnl_cls_data(cls);
00129 
00130         if (!(b->b_mask & BASIC_ATTR_CLASSID))
00131                 return -NLE_MISSING_ATTR;
00132 
00133         NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_classid);
00134 
00135         return 0;
00136 
00137 nla_put_failure:
00138         return -NLE_NOMEM;
00139 }
00140 
00141 /**
00142  * @name Attribute Modifications
00143  * @{
00144  */
00145 
00146 int rtnl_basic_set_classid(struct rtnl_cls *cls, uint32_t classid)
00147 {
00148         struct rtnl_basic *b = rtnl_cls_data(cls);
00149 
00150         b->b_classid = classid;
00151         b->b_mask |= BASIC_ATTR_CLASSID;
00152 
00153         return 0;
00154 }
00155 
00156 uint32_t rtnl_basic_get_classid(struct rtnl_cls *cls)
00157 {
00158         struct rtnl_basic *b = rtnl_cls_data(cls);
00159 
00160         return b->b_classid;
00161 }
00162 
00163 int rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
00164 {
00165         struct rtnl_basic *b = rtnl_cls_data(cls);
00166 
00167         if (b->b_ematch) {
00168                 rtnl_ematch_tree_free(b->b_ematch);
00169                 b->b_mask &= ~BASIC_ATTR_EMATCH;
00170         }
00171 
00172         b->b_ematch = tree;
00173 
00174         if (tree)
00175                 b->b_mask |= BASIC_ATTR_EMATCH;
00176 
00177         return 0;
00178 }
00179 
00180 struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls)
00181 {
00182         struct rtnl_basic *b = rtnl_cls_data(cls);
00183         return b->b_ematch;
00184 }
00185 
00186 /** @} */
00187 
00188 static struct rtnl_cls_ops basic_ops = {
00189         .co_kind                = "basic",
00190         .co_size                = sizeof(struct rtnl_basic),
00191         .co_msg_parser          = basic_msg_parser,
00192         .co_clone               = basic_clone,
00193         .co_free_data           = basic_free_data,
00194         .co_get_opts            = basic_get_opts,
00195         .co_dump = {
00196             [NL_DUMP_LINE]      = basic_dump_line,
00197             [NL_DUMP_DETAILS]   = basic_dump_details,
00198         },
00199 };
00200 
00201 static void __init basic_init(void)
00202 {
00203         rtnl_cls_register(&basic_ops);
00204 }
00205 
00206 static void __exit basic_exit(void)
00207 {
00208         rtnl_cls_unregister(&basic_ops);
00209 }
00210 
00211 /** @} */