1 /* 2 * lib/route/cls/basic.c Basic Classifier 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2008-2009 Thomas Graf <tgraf (at) suug.ch> 10 */ 11 12 /** 13 * @ingroup cls 14 * @defgroup basic Basic Classifier 15 * 16 * @par Introduction 17 * The basic classifier is the simplest form of a classifier. It does 18 * not have any special classification capabilities, instead it can be 19 * used to classify exclusively based on extended matches or to 20 * create a "catch-all" filter. 21 * 22 * @{ 23 */ 24 25 #include <netlink-local.h> 26 #include <netlink-tc.h> 27 #include <netlink/netlink.h> 28 #include <netlink/route/classifier.h> 29 #include <netlink/route/classifier-modules.h> 30 #include <netlink/route/cls/basic.h> 31 #include <netlink/route/cls/ematch.h> 32 33 struct rtnl_basic 34 { 35 uint32_t b_classid; 36 struct rtnl_ematch_tree * b_ematch; 37 int b_mask; 38 }; 39 40 /** @cond SKIP */ 41 #define BASIC_ATTR_CLASSID 0x001 42 #define BASIC_ATTR_EMATCH 0x002 43 /** @endcond */ 44 45 static struct nla_policy basic_policy[TCA_FW_MAX+1] = { 46 [TCA_BASIC_CLASSID] = { .type = NLA_U32 }, 47 [TCA_BASIC_EMATCHES] = { .type = NLA_NESTED }, 48 [TCA_BASIC_ACT] = { .type = NLA_NESTED }, 49 [TCA_BASIC_POLICE] = { .type = NLA_NESTED }, 50 }; 51 52 static int basic_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src) 53 { 54 return -NLE_OPNOTSUPP; 55 } 56 57 static void basic_free_data(struct rtnl_cls *cls) 58 { 59 struct rtnl_basic *basic = rtnl_cls_data(cls); 60 61 rtnl_ematch_tree_free(basic->b_ematch); 62 } 63 64 static int basic_msg_parser(struct rtnl_cls *cls) 65 { 66 struct nlattr *tb[TCA_BASIC_MAX + 1]; 67 struct rtnl_basic *basic = rtnl_cls_data(cls); 68 int err; 69 70 err = tca_parse(tb, TCA_BASIC_MAX, (struct rtnl_tca *) cls, basic_policy); 71 if (err < 0) 72 return err; 73 74 if (tb[TCA_BASIC_CLASSID]) { 75 basic->b_classid = nla_get_u32(tb[TCA_BASIC_CLASSID]); 76 basic->b_mask |= BASIC_ATTR_CLASSID; 77 } 78 79 if (tb[TCA_BASIC_EMATCHES]) { 80 if ((err = rtnl_ematch_parse(tb[TCA_BASIC_EMATCHES], 81 &basic->b_ematch)) < 0) 82 return err; 83 84 if (basic->b_ematch) 85 basic->b_mask |= BASIC_ATTR_EMATCH; 86 } 87 88 if (tb[TCA_BASIC_ACT]) { 89 /* XXX */ 90 } 91 92 if (tb[TCA_BASIC_POLICE]) { 93 /* XXX */ 94 } 95 96 return 0; 97 } 98 99 static void basic_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p) 100 { 101 struct rtnl_basic *b = rtnl_cls_data(cls); 102 char buf[32]; 103 104 if (b->b_mask & BASIC_ATTR_EMATCH) 105 nl_dump(p, " ematch"); 106 else 107 nl_dump(p, " match-all"); 108 109 if (b->b_mask & BASIC_ATTR_CLASSID) 110 nl_dump(p, " classify-to %s", 111 rtnl_tc_handle2str(b->b_classid, buf, sizeof(buf))); 112 } 113 114 static void basic_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p) 115 { 116 struct rtnl_basic *b = rtnl_cls_data(cls); 117 118 if (b->b_mask & BASIC_ATTR_EMATCH) { 119 nl_dump(p, "\n"); 120 nl_dump_line(p, " ematch "); 121 rtnl_ematch_tree_dump(b->b_ematch, p); 122 } else 123 nl_dump(p, "no options.\n"); 124 } 125 126 static int basic_get_opts(struct rtnl_cls *cls, struct nl_msg *msg) 127 { 128 struct rtnl_basic *b = rtnl_cls_data(cls); 129 130 if (!(b->b_mask & BASIC_ATTR_CLASSID)) 131 return -NLE_MISSING_ATTR; 132 133 NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_classid); 134 135 return 0; 136 137 nla_put_failure: 138 return -NLE_NOMEM; 139 } 140 141 /** 142 * @name Attribute Modifications 143 * @{ 144 */ 145 146 int rtnl_basic_set_classid(struct rtnl_cls *cls, uint32_t classid) 147 { 148 struct rtnl_basic *b = rtnl_cls_data(cls); 149 150 b->b_classid = classid; 151 b->b_mask |= BASIC_ATTR_CLASSID; 152 153 return 0; 154 } 155 156 uint32_t rtnl_basic_get_classid(struct rtnl_cls *cls) 157 { 158 struct rtnl_basic *b = rtnl_cls_data(cls); 159 160 return b->b_classid; 161 } 162 163 int rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree) 164 { 165 struct rtnl_basic *b = rtnl_cls_data(cls); 166 167 if (b->b_ematch) { 168 rtnl_ematch_tree_free(b->b_ematch); 169 b->b_mask &= ~BASIC_ATTR_EMATCH; 170 } 171 172 b->b_ematch = tree; 173 174 if (tree) 175 b->b_mask |= BASIC_ATTR_EMATCH; 176 177 return 0; 178 } 179 180 struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls) 181 { 182 struct rtnl_basic *b = rtnl_cls_data(cls); 183 return b->b_ematch; 184 } 185 186 /** @} */ 187 188 static struct rtnl_cls_ops basic_ops = { 189 .co_kind = "basic", 190 .co_size = sizeof(struct rtnl_basic), 191 .co_msg_parser = basic_msg_parser, 192 .co_clone = basic_clone, 193 .co_free_data = basic_free_data, 194 .co_get_opts = basic_get_opts, 195 .co_dump = { 196 [NL_DUMP_LINE] = basic_dump_line, 197 [NL_DUMP_DETAILS] = basic_dump_details, 198 }, 199 }; 200 201 static void __init basic_init(void) 202 { 203 rtnl_cls_register(&basic_ops); 204 } 205 206 static void __exit basic_exit(void) 207 { 208 rtnl_cls_unregister(&basic_ops); 209 } 210 211 /** @} */ 212