cls_obj.c revision 5d92f9c03d85cefee5afe7f40d7ea69dfde4cf77
1/*
2 * lib/route/cls_api.c       Classifier Object
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) 2003-2006 Thomas Graf <tgraf@suug.ch>
10 */
11
12/**
13 * @ingroup cls
14 * @defgroup cls_obj Classifier Object
15 * @{
16 */
17
18#include <netlink-local.h>
19#include <netlink-tc.h>
20#include <netlink/netlink.h>
21#include <netlink/utils.h>
22#include <netlink/route/tc.h>
23#include <netlink/route/classifier.h>
24#include <netlink/route/classifier-modules.h>
25#include <netlink/route/link.h>
26
27/** @cond SKIP */
28#define CLS_ATTR_PRIO		(TCA_ATTR_MAX << 1)
29#define CLS_ATTR_PROTOCOL	(TCA_ATTR_MAX << 2)
30/** @endcond */
31
32static void cls_free_data(struct nl_object *obj)
33{
34	struct rtnl_cls *cls = (struct rtnl_cls *) obj;
35	struct rtnl_cls_ops *cops;
36
37	tca_free_data((struct rtnl_tca *) cls);
38
39	cops = rtnl_cls_lookup_ops(cls);
40	if (cops && cops->co_free_data)
41		cops->co_free_data(cls);
42}
43
44static int cls_clone(struct nl_object *_dst, struct nl_object *_src)
45{
46	struct rtnl_cls *dst = nl_object_priv(_dst);
47	struct rtnl_cls *src = nl_object_priv(_src);
48	struct rtnl_cls_ops *cops;
49	int err;
50
51	err = tca_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src);
52	if (err < 0)
53		goto errout;
54
55	cops = rtnl_cls_lookup_ops(src);
56	if (cops && cops->co_clone)
57		err = cops->co_clone(dst, src);
58errout:
59	return err;
60}
61
62static void cls_dump_line(struct nl_object *obj, struct nl_dump_params *p)
63{
64	char buf[32];
65	struct rtnl_cls *cls = (struct rtnl_cls *) obj;
66	struct rtnl_cls_ops *cops;
67
68	tca_dump_line((struct rtnl_tca *) cls, "cls", p);
69
70	nl_dump(p, " prio %u protocol %s", cls->c_prio,
71		nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf)));
72
73	cops = rtnl_cls_lookup_ops(cls);
74	if (cops && cops->co_dump[NL_DUMP_LINE])
75		cops->co_dump[NL_DUMP_LINE](cls, p);
76	nl_dump(p, "\n");
77}
78
79static void cls_dump_details(struct nl_object *obj, struct nl_dump_params *p)
80{
81	struct rtnl_cls *cls = (struct rtnl_cls *) obj;
82	struct rtnl_cls_ops *cops;
83
84	cls_dump_line(obj, p);
85	tca_dump_details((struct rtnl_tca *) cls, p);
86
87	cops = rtnl_cls_lookup_ops(cls);
88	if (cops && cops->co_dump[NL_DUMP_DETAILS])
89		cops->co_dump[NL_DUMP_DETAILS](cls, p);
90	else
91		nl_dump(p, "no options\n");
92}
93
94static void cls_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
95{
96	struct rtnl_cls *cls = (struct rtnl_cls *) obj;
97	struct rtnl_cls_ops *cops;
98
99	cls_dump_details(obj, p);
100	tca_dump_stats((struct rtnl_tca *) cls, p);
101	nl_dump(p, "\n");
102
103	cops = rtnl_cls_lookup_ops(cls);
104	if (cops && cops->co_dump[NL_DUMP_STATS])
105		cops->co_dump[NL_DUMP_STATS](cls, p);
106}
107
108/**
109 * @name Allocation/Freeing
110 * @{
111 */
112
113struct rtnl_cls *rtnl_cls_alloc(void)
114{
115	return (struct rtnl_cls *) nl_object_alloc(&cls_obj_ops);
116}
117
118void rtnl_cls_put(struct rtnl_cls *cls)
119{
120	nl_object_put((struct nl_object *) cls);
121}
122
123/** @} */
124
125
126/**
127 * @name Attributes
128 * @{
129 */
130
131void rtnl_cls_set_ifindex(struct rtnl_cls *f, int ifindex)
132{
133	tca_set_ifindex((struct rtnl_tca *) f, ifindex);
134}
135
136void rtnl_cls_set_handle(struct rtnl_cls *f, uint32_t handle)
137{
138	tca_set_handle((struct rtnl_tca *) f, handle);
139}
140
141void rtnl_cls_set_parent(struct rtnl_cls *f, uint32_t parent)
142{
143	tca_set_parent((struct rtnl_tca *) f, parent);
144}
145
146void rtnl_cls_set_kind(struct rtnl_cls *f, const char *kind)
147{
148	tca_set_kind((struct rtnl_tca *) f, kind);
149	f->c_ops = __rtnl_cls_lookup_ops(kind);
150}
151
152void rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio)
153{
154	cls->c_prio = prio;
155	cls->ce_mask |= CLS_ATTR_PRIO;
156}
157
158uint16_t rtnl_cls_get_prio(struct rtnl_cls *cls)
159{
160	if (cls->ce_mask & CLS_ATTR_PRIO)
161		return cls->c_prio;
162	else
163		return 0;
164}
165
166void rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol)
167{
168	cls->c_protocol = protocol;
169	cls->ce_mask |= CLS_ATTR_PROTOCOL;
170}
171
172uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls)
173{
174	if (cls->ce_mask & CLS_ATTR_PROTOCOL)
175		return cls->c_protocol;
176	else
177		return ETH_P_ALL;
178}
179
180/** @} */
181
182struct nl_object_ops cls_obj_ops = {
183	.oo_name		= "route/cls",
184	.oo_size		= sizeof(struct rtnl_cls),
185	.oo_free_data		= cls_free_data,
186	.oo_clone		= cls_clone,
187	.oo_dump = {
188	    [NL_DUMP_LINE]	= cls_dump_line,
189	    [NL_DUMP_DETAILS]	= cls_dump_details,
190	    [NL_DUMP_STATS]	= cls_dump_stats,
191	},
192	.oo_compare		= tca_compare,
193	.oo_id_attrs		= (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
194};
195
196/** @} */
197