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@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 33struct 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 45static 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 52static int basic_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src) 53{ 54 return -NLE_OPNOTSUPP; 55} 56 57static 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 64static 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 99static 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 114static 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 126static 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 137nla_put_failure: 138 return -NLE_NOMEM; 139} 140 141/** 142 * @name Attribute Modifications 143 * @{ 144 */ 145 146int 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 156uint32_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 163int 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 180struct 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 188static 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 201static void __init basic_init(void) 202{ 203 rtnl_cls_register(&basic_ops); 204} 205 206static void __exit basic_exit(void) 207{ 208 rtnl_cls_unregister(&basic_ops); 209} 210 211/** @} */ 212