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/tc-api.h>
00029 #include <netlink/route/classifier.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_target;
00036 struct rtnl_ematch_tree * b_ematch;
00037 int b_mask;
00038 };
00039
00040
00041 #define BASIC_ATTR_TARGET 0x001
00042 #define BASIC_ATTR_EMATCH 0x002
00043
00044
00045 static struct nla_policy basic_policy[TCA_BASIC_MAX+1] = {
00046 [TCA_BASIC_CLASSID] = { .type = NLA_U32 },
00047 [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED },
00048 };
00049
00050 static int basic_clone(void *_dst, void *_src)
00051 {
00052 return -NLE_OPNOTSUPP;
00053 }
00054
00055 static void basic_free_data(struct rtnl_tc *tc, void *data)
00056 {
00057 struct rtnl_basic *b = data;
00058
00059 if (!b)
00060 return;
00061
00062 rtnl_ematch_tree_free(b->b_ematch);
00063 }
00064
00065 static int basic_msg_parser(struct rtnl_tc *tc, void *data)
00066 {
00067 struct nlattr *tb[TCA_BASIC_MAX + 1];
00068 struct rtnl_basic *b = data;
00069 int err;
00070
00071 err = tca_parse(tb, TCA_BASIC_MAX, tc, basic_policy);
00072 if (err < 0)
00073 return err;
00074
00075 if (tb[TCA_BASIC_CLASSID]) {
00076 b->b_target = nla_get_u32(tb[TCA_BASIC_CLASSID]);
00077 b->b_mask |= BASIC_ATTR_TARGET;
00078 }
00079
00080 if (tb[TCA_BASIC_EMATCHES]) {
00081 if ((err = rtnl_ematch_parse_attr(tb[TCA_BASIC_EMATCHES],
00082 &b->b_ematch)) < 0)
00083 return err;
00084
00085 if (b->b_ematch)
00086 b->b_mask |= BASIC_ATTR_EMATCH;
00087 }
00088
00089 return 0;
00090 }
00091
00092 static void basic_dump_line(struct rtnl_tc *tc, void *data,
00093 struct nl_dump_params *p)
00094 {
00095 struct rtnl_basic *b = data;
00096 char buf[32];
00097
00098 if (!b)
00099 return;
00100
00101 if (b->b_mask & BASIC_ATTR_EMATCH)
00102 nl_dump(p, " ematch");
00103 else
00104 nl_dump(p, " match-all");
00105
00106 if (b->b_mask & BASIC_ATTR_TARGET)
00107 nl_dump(p, " target %s",
00108 rtnl_tc_handle2str(b->b_target, buf, sizeof(buf)));
00109 }
00110
00111 static void basic_dump_details(struct rtnl_tc *tc, void *data,
00112 struct nl_dump_params *p)
00113 {
00114 struct rtnl_basic *b = data;
00115
00116 if (!b)
00117 return;
00118
00119 if (b->b_mask & BASIC_ATTR_EMATCH) {
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_msg_fill(struct rtnl_tc *tc, void *data,
00127 struct nl_msg *msg)
00128 {
00129 struct rtnl_basic *b = data;
00130
00131 if (!b)
00132 return 0;
00133
00134 if (!(b->b_mask & BASIC_ATTR_TARGET))
00135 return -NLE_MISSING_ATTR;
00136
00137 NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_target);
00138
00139 if (b->b_mask & BASIC_ATTR_EMATCH &&
00140 rtnl_ematch_fill_attr(msg, TCA_BASIC_EMATCHES, b->b_ematch) < 0)
00141 goto nla_put_failure;
00142
00143 return 0;
00144
00145 nla_put_failure:
00146 return -NLE_NOMEM;
00147 }
00148
00149
00150
00151
00152
00153
00154 void rtnl_basic_set_target(struct rtnl_cls *cls, uint32_t target)
00155 {
00156 struct rtnl_basic *b;
00157
00158 if (!(b = rtnl_tc_data(TC_CAST(cls))))
00159 return;
00160
00161 b->b_target = target;
00162 b->b_mask |= BASIC_ATTR_TARGET;
00163 }
00164
00165 uint32_t rtnl_basic_get_target(struct rtnl_cls *cls)
00166 {
00167 struct rtnl_basic *b;
00168
00169 if (!(b = rtnl_tc_data(TC_CAST(cls))))
00170 return 0;
00171
00172 return b->b_target;
00173 }
00174
00175 void rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
00176 {
00177 struct rtnl_basic *b;
00178
00179 if (!(b = rtnl_tc_data(TC_CAST(cls))))
00180 return;
00181
00182 if (b->b_ematch) {
00183 rtnl_ematch_tree_free(b->b_ematch);
00184 b->b_mask &= ~BASIC_ATTR_EMATCH;
00185 }
00186
00187 b->b_ematch = tree;
00188
00189 if (tree)
00190 b->b_mask |= BASIC_ATTR_EMATCH;
00191 }
00192
00193 struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls)
00194 {
00195 struct rtnl_basic *b;
00196
00197 if (!(b = rtnl_tc_data(TC_CAST(cls))))
00198 return NULL;
00199
00200 return b->b_ematch;
00201 }
00202
00203
00204
00205 static struct rtnl_tc_ops basic_ops = {
00206 .to_kind = "basic",
00207 .to_type = RTNL_TC_TYPE_CLS,
00208 .to_size = sizeof(struct rtnl_basic),
00209 .to_msg_parser = basic_msg_parser,
00210 .to_clone = basic_clone,
00211 .to_free_data = basic_free_data,
00212 .to_msg_fill = basic_msg_fill,
00213 .to_dump = {
00214 [NL_DUMP_LINE] = basic_dump_line,
00215 [NL_DUMP_DETAILS] = basic_dump_details,
00216 },
00217 };
00218
00219 static void __init basic_init(void)
00220 {
00221 rtnl_tc_register(&basic_ops);
00222 }
00223
00224 static void __exit basic_exit(void)
00225 {
00226 rtnl_tc_unregister(&basic_ops);
00227 }
00228
00229