libnl 1.1.4
class.c
1/*
2 * lib/route/class.c Queueing Classes
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 tc
14 * @defgroup class Queueing Classes
15 * @{
16 */
17
18#include <netlink-local.h>
19#include <netlink-tc.h>
20#include <netlink/netlink.h>
21#include <netlink/route/tc.h>
22#include <netlink/route/class.h>
23#include <netlink/route/class-modules.h>
24#include <netlink/route/qdisc.h>
25#include <netlink/route/classifier.h>
26#include <netlink/utils.h>
27
28static struct nl_cache_ops rtnl_class_ops;
29
30static int class_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
31 struct nlmsghdr *n, struct nl_parser_param *pp)
32{
33 int err;
34 struct rtnl_class *class;
35 struct rtnl_class_ops *cops;
36
37 class = rtnl_class_alloc();
38 if (!class) {
39 err = nl_errno(ENOMEM);
40 goto errout;
41 }
42 class->ce_msgtype = n->nlmsg_type;
43
44 err = tca_msg_parser(n, (struct rtnl_tca *) class);
45 if (err < 0)
46 goto errout_free;
47
48 cops = rtnl_class_lookup_ops(class);
49 if (cops && cops->co_msg_parser) {
50 err = cops->co_msg_parser(class);
51 if (err < 0)
52 goto errout_free;
53 }
54
55 err = pp->pp_cb((struct nl_object *) class, pp);
56 if (err < 0)
57 goto errout_free;
58
59 err = P_ACCEPT;
60
61errout_free:
62 rtnl_class_put(class);
63errout:
64 return err;
65}
66
67static int class_request_update(struct nl_cache *cache,
68 struct nl_handle *handle)
69{
70 struct tcmsg tchdr = {
71 .tcm_family = AF_UNSPEC,
72 .tcm_ifindex = cache->c_iarg1,
73 };
74
75 return nl_send_simple(handle, RTM_GETTCLASS, NLM_F_DUMP, &tchdr,
76 sizeof(tchdr));
77}
78
79/**
80 * @name Addition/Modification
81 * @{
82 */
83
84static struct nl_msg *class_build(struct rtnl_class *class, int type, int flags)
85{
86 struct rtnl_class_ops *cops;
87 struct nl_msg *msg;
88 int err;
89
90 msg = tca_build_msg((struct rtnl_tca *) class, type, flags);
91 if (!msg)
92 goto errout;
93
94 cops = rtnl_class_lookup_ops(class);
95 if (cops && cops->co_get_opts) {
96 struct nl_msg *opts;
97
98 opts = cops->co_get_opts(class);
99 if (opts) {
100 err = nla_put_nested(msg, TCA_OPTIONS, opts);
101 nlmsg_free(opts);
102 if (err < 0)
103 goto errout;
104 }
105 }
106
107 return msg;
108errout:
109 nlmsg_free(msg);
110 return NULL;
111}
112
113/**
114 * Build a netlink message to add a new class
115 * @arg class class to add
116 * @arg flags additional netlink message flags
117 *
118 * Builds a new netlink message requesting an addition of a class.
119 * The netlink message header isn't fully equipped with all relevant
120 * fields and must be sent out via nl_send_auto_complete() or
121 * supplemented as needed.
122 *
123 * Common message flags
124 * - NLM_F_REPLACE - replace possibly existing classes
125 *
126 * @return New netlink message
127 */
128struct nl_msg *rtnl_class_build_add_request(struct rtnl_class *class, int flags)
129{
130 return class_build(class, RTM_NEWTCLASS, NLM_F_CREATE | flags);
131}
132
133/**
134 * Add a new class
135 * @arg handle netlink handle
136 * @arg class class to delete
137 * @arg flags additional netlink message flags
138 *
139 * Builds a netlink message by calling rtnl_qdisc_build_add_request(),
140 * sends the request to the kernel and waits for the next ACK to be
141 * received and thus blocks until the request has been processed.
142 *
143 * Common message flags
144 * - NLM_F_REPLACE - replace possibly existing classes
145 *
146 * @return 0 on success or a negative error code
147 */
148int rtnl_class_add(struct nl_handle *handle, struct rtnl_class *class,
149 int flags)
150{
151 struct nl_msg *msg;
152 int err;
153
154 msg = rtnl_class_build_add_request(class, flags);
155 if (!msg)
156 return nl_errno(ENOMEM);
157
158 err = nl_send_auto_complete(handle, msg);
159 nlmsg_free(msg);
160 if (err < 0)
161 return err;
162
163 return nl_wait_for_ack(handle);
164}
165
166/** @} */
167
168/**
169 * @name Cache Management
170 * @{
171 */
172
173/**
174 * Build a class cache including all classes attached to the specified interface
175 * @arg handle netlink handle
176 * @arg ifindex interface index of the link the classes are
177 * attached to.
178 *
179 * Allocates a new cache, initializes it properly and updates it to
180 * include all classes attached to the specified interface.
181 *
182 * @return The cache or NULL if an error has occured.
183 */
184struct nl_cache * rtnl_class_alloc_cache(struct nl_handle *handle, int ifindex)
185{
186 struct nl_cache * cache;
187
189 if (!cache)
190 return NULL;
191
192 cache->c_iarg1 = ifindex;
193
194 if (handle && nl_cache_refill(handle, cache) < 0) {
195 nl_cache_free(cache);
196 return NULL;
197 }
198
199 return cache;
200}
201
202/** @} */
203
204static struct nl_cache_ops rtnl_class_ops = {
205 .co_name = "route/class",
206 .co_hdrsize = sizeof(struct tcmsg),
207 .co_msgtypes = {
208 { RTM_NEWTCLASS, NL_ACT_NEW, "new" },
209 { RTM_DELTCLASS, NL_ACT_DEL, "del" },
210 { RTM_GETTCLASS, NL_ACT_GET, "get" },
211 END_OF_MSGTYPES_LIST,
212 },
213 .co_protocol = NETLINK_ROUTE,
214 .co_request_update = &class_request_update,
215 .co_msg_parser = &class_msg_parser,
216 .co_obj_ops = &class_obj_ops,
217};
218
219static void __init class_init(void)
220{
222}
223
224static void __exit class_exit(void)
225{
227}
228
229/** @} */
int nla_put_nested(struct nl_msg *n, int attrtype, struct nl_msg *nested)
Add a nested netlink attribute to a netlink message.
Definition: attr.c:535
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:261
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:226
void nl_cache_free(struct nl_cache *cache)
Free a cache.
Definition: cache.c:277
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate an empty cache.
Definition: cache.c:170
int nl_cache_refill(struct nl_handle *handle, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
Definition: cache.c:680
struct rtnl_class_ops * rtnl_class_lookup_ops(struct rtnl_class *class)
Lookup class operations for a class object.
Definition: class_api.c:91
struct nl_cache * rtnl_class_alloc_cache(struct nl_handle *handle, int ifindex)
Build a class cache including all classes attached to the specified interface.
Definition: class.c:184
int rtnl_class_add(struct nl_handle *handle, struct rtnl_class *class, int flags)
Add a new class.
Definition: class.c:148
struct nl_msg * rtnl_class_build_add_request(struct rtnl_class *class, int flags)
Build a netlink message to add a new class.
Definition: class.c:128
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
Definition: msg.c:656
#define NLM_F_CREATE
Create config object if it doesn't already exist.
#define NLM_F_DUMP
Dump all entries.
int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message and check & extend header values as needed.
Definition: nl.c:373
int nl_send_simple(struct nl_handle *handle, int type, int flags, void *buf, size_t size)
Send simple netlink message using nl_send_auto_complete()
Definition: nl.c:410
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
Definition: nl.c:801
Cache Operations.
Definition: cache-api.h:164
Netlink message header.
uint16_t nlmsg_type
Message type (content type)
Class operations.
Definition: class-modules.h:26
struct nl_msg *(* co_get_opts)(struct rtnl_class *)
Must return the contents supposed to be in TCA_OPTIONS.
Definition: class-modules.h:41
int(* co_msg_parser)(struct rtnl_class *)
TCA_OPTIONS message parser.
Definition: class-modules.h:46
Netlink socket address.
Definition: netlink-kernel.h:9