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 
28 static struct nl_cache_ops rtnl_class_ops;
29 
30 static 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 
61 errout_free:
62  rtnl_class_put(class);
63 errout:
64  return err;
65 }
66 
67 static 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 
84 static 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;
108 errout:
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  */
128 struct 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  */
148 int 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  */
184 struct nl_cache * rtnl_class_alloc_cache(struct nl_handle *handle, int ifindex)
185 {
186  struct nl_cache * cache;
187 
188  cache = nl_cache_alloc(&rtnl_class_ops);
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 
204 static 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 
219 static void __init class_init(void)
220 {
221  nl_cache_mngt_register(&rtnl_class_ops);
222 }
223 
224 static void __exit class_exit(void)
225 {
226  nl_cache_mngt_unregister(&rtnl_class_ops);
227 }
228 
229 /** @} */
Class operations.
Definition: class-modules.h:25
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
uint16_t nlmsg_type
Message type (content type)
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:261
struct rtnl_class_ops * rtnl_class_lookup_ops(struct rtnl_class *class)
Lookup class operations for a class object.
Definition: class_api.c:91
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
Definition: nl.c:801
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
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
Definition: msg.c:656
Netlink message header.
int rtnl_class_add(struct nl_handle *handle, struct rtnl_class *class, int flags)
Add a new class.
Definition: class.c:148
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
void nl_cache_free(struct nl_cache *cache)
Free a cache.
Definition: cache.c:277
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:226
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
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
#define NLM_F_CREATE
Create config object if it doesn't already exist.
#define NLM_F_DUMP
Dump all entries.
Cache Operations.
Definition: cache-api.h:163
Netlink socket address.
Definition: netlink-kernel.h:8
int(* co_msg_parser)(struct rtnl_class *)
TCA_OPTIONS message parser.
Definition: class-modules.h:46
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 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
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate an empty cache.
Definition: cache.c:170