basic.c revision ef858fb492dfe98e3ae194264fbc73649cf8493a
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