00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00041 #define BASIC_ATTR_CLASSID 0x001
00042 #define BASIC_ATTR_EMATCH 0x002
00043
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
00090 }
00091
00092 if (tb[TCA_BASIC_POLICE]) {
00093
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
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