libnl
3.2.3
|
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-2011 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup cls 00014 * @defgroup cls_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/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 /** @cond SKIP */ 00041 #define BASIC_ATTR_TARGET 0x001 00042 #define BASIC_ATTR_EMATCH 0x002 00043 /** @endcond */ 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 * @name Attribute Modifications 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 /** @} */