2 * lib/route/link/api.c Link Info API
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
9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
14 * @defgroup link_API Link Modules API
15 * @brief API for modules implementing specific link types/semantics.
17 * @par 1) Registering/Unregistering a new link info type
19 * static struct rtnl_link_info_ops vlan_info_ops = {
21 * .io_alloc = vlan_alloc,
22 * .io_parse = vlan_parse,
23 * .io_dump[NL_DUMP_BRIEF] = vlan_dump_brief,
24 * .io_dump[NL_DUMP_FULL] = vlan_dump_full,
25 * .io_free = vlan_free,
28 * static void __init vlan_init(void)
30 * rtnl_link_register_info(&vlan_info_ops);
33 * static void __exit vlan_exit(void)
35 * rtnl_link_unregister_info(&vlan_info_ops);
42 #include <netlink-private/netlink.h>
43 #include <netlink/netlink.h>
44 #include <netlink/utils.h>
45 #include <netlink/route/link.h>
46 #include <netlink-private/route/link/api.h>
48 static NL_LIST_HEAD(info_ops);
50 /* lock protecting info_ops and af_ops */
51 static NL_RW_LOCK(info_lock);
53 static struct rtnl_link_info_ops *__rtnl_link_info_ops_lookup(const char *name)
55 struct rtnl_link_info_ops *ops;
57 nl_list_for_each_entry(ops, &info_ops, io_list)
58 if (!strcmp(ops->io_name, name))
65 * @name Link Info Modules
70 * Return operations of a specific link info type
71 * @arg name Name of link info type.
73 * @note The returned pointer must be given back using rtnl_link_info_ops_put()
75 * @return Pointer to operations or NULL if unavailable.
77 struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *name)
79 struct rtnl_link_info_ops *ops;
81 nl_write_lock(&info_lock);
82 if ((ops = __rtnl_link_info_ops_lookup(name)))
84 nl_write_unlock(&info_lock);
90 * Give back reference to a set of operations.
91 * @arg ops Link info operations.
93 void rtnl_link_info_ops_put(struct rtnl_link_info_ops *ops)
100 * Register operations for a link info type
101 * @arg ops Link info operations
103 * This function must be called by modules implementing a specific link
104 * info type. It will make the operations implemented by the module
105 * available for everyone else.
107 * @return 0 on success or a negative error code.
108 * @return -NLE_INVAL Link info name not specified.
109 * @return -NLE_EXIST Operations for address family already registered.
111 int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
115 if (ops->io_name == NULL)
118 nl_write_lock(&info_lock);
119 if (__rtnl_link_info_ops_lookup(ops->io_name)) {
124 NL_DBG(1, "Registered link info operations %s\n", ops->io_name);
126 nl_list_add_tail(&ops->io_list, &info_ops);
128 nl_write_unlock(&info_lock);
134 * Unregister operations for a link info type
135 * @arg ops Link info operations
137 * This function must be called if a module implementing a specific link
138 * info type is unloaded or becomes unavailable. It must provide a
139 * set of operations which have previously been registered using
140 * rtnl_link_register_info().
142 * @return 0 on success or a negative error code
143 * @return _NLE_OPNOTSUPP Link info operations not registered.
144 * @return -NLE_BUSY Link info operations still in use.
146 int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
148 struct rtnl_link_info_ops *t;
149 int err = -NLE_OPNOTSUPP;
151 nl_write_lock(&info_lock);
153 nl_list_for_each_entry(t, &info_ops, io_list) {
155 if (t->io_refcnt > 0) {
160 nl_list_del(&t->io_list);
162 NL_DBG(1, "Unregistered link info operations %s\n",
170 nl_write_unlock(&info_lock);
178 * @name Link Address Family Modules
182 static struct rtnl_link_af_ops *af_ops[AF_MAX];
185 * Return operations of a specific link address family
186 * @arg family Address family
188 * @note The returned pointer must be given back using rtnl_link_af_ops_put()
190 * @return Pointer to operations or NULL if unavailable.
192 struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(const unsigned int family)
194 if (family == AF_UNSPEC || family >= AF_MAX)
197 nl_write_lock(&info_lock);
199 af_ops[family]->ao_refcnt++;
200 nl_write_unlock(&info_lock);
202 return af_ops[family];
206 * Give back reference to a set of operations.
207 * @arg ops Address family operations.
209 void rtnl_link_af_ops_put(struct rtnl_link_af_ops *ops)
216 * Allocate and return data buffer for link address family modules
217 * @arg link Link object
218 * @arg ops Address family operations
220 * This function must be called by link address family modules in all
221 * cases where the API does not provide the data buffer as argument
222 * already. This typically includes set functions the module provides.
223 * Calling this function is strictly required to ensure proper allocation
224 * of the buffer upon first use. Link objects will NOT proactively
225 * allocate a data buffer for each registered link address family.
227 * @return Pointer to data buffer or NULL on error.
229 void *rtnl_link_af_alloc(struct rtnl_link *link,
230 const struct rtnl_link_af_ops *ops)
237 family = ops->ao_family;
239 if (!link->l_af_data[family]) {
243 link->l_af_data[family] = ops->ao_alloc(link);
244 if (!link->l_af_data[family])
248 return link->l_af_data[family];
252 * Return data buffer for link address family modules
253 * @arg link Link object
254 * @arg ops Address family operations
256 * This function returns a pointer to the data buffer for the specified link
257 * address family module or NULL if the buffer was not allocated yet. This
258 * function is typically used by get functions of modules which are not
259 * interested in having the data buffer allocated if no values have been set
262 * @return Pointer to data buffer or NULL on error.
264 void *rtnl_link_af_data(const struct rtnl_link *link,
265 const struct rtnl_link_af_ops *ops)
270 return link->l_af_data[ops->ao_family];
274 * Register operations for a link address family
275 * @arg ops Address family operations
277 * This function must be called by modules implementing a specific link
278 * address family. It will make the operations implemented by the module
279 * available for everyone else.
281 * @return 0 on success or a negative error code.
282 * @return -NLE_INVAL Address family is out of range (0..AF_MAX)
283 * @return -NLE_EXIST Operations for address family already registered.
285 int rtnl_link_af_register(struct rtnl_link_af_ops *ops)
289 if (ops->ao_family == AF_UNSPEC || ops->ao_family >= AF_MAX)
292 nl_write_lock(&info_lock);
293 if (af_ops[ops->ao_family]) {
299 af_ops[ops->ao_family] = ops;
301 NL_DBG(1, "Registered link address family operations %u\n",
305 nl_write_unlock(&info_lock);
311 * Unregister operations for a link address family
312 * @arg ops Address family operations
314 * This function must be called if a module implementing a specific link
315 * address family is unloaded or becomes unavailable. It must provide a
316 * set of operations which have previously been registered using
317 * rtnl_link_af_register().
319 * @return 0 on success or a negative error code
320 * @return -NLE_INVAL ops is NULL
321 * @return -NLE_OBJ_NOTFOUND Address family operations not registered.
322 * @return -NLE_BUSY Address family operations still in use.
324 int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops)
326 int err = -NLE_INVAL;
331 nl_write_lock(&info_lock);
332 if (!af_ops[ops->ao_family]) {
333 err = -NLE_OBJ_NOTFOUND;
337 if (ops->ao_refcnt > 0) {
342 af_ops[ops->ao_family] = NULL;
344 NL_DBG(1, "Unregistered link address family operations %u\n",
348 nl_write_unlock(&info_lock);
354 * Compare af data for a link address family
355 * @arg a Link object a
356 * @arg b Link object b
357 * @arg family af data family
359 * This function will compare af_data between two links
360 * a and b of family given by arg family
362 * @return 0 if address family specific data matches or is not present
363 * or != 0 if it mismatches.
365 int rtnl_link_af_data_compare(struct rtnl_link *a, struct rtnl_link *b,
368 struct rtnl_link_af_ops *af_ops;
371 if (!a->l_af_data[family] && !b->l_af_data[family])
374 if (!a->l_af_data[family] || !b->l_af_data[family])
377 af_ops = rtnl_link_af_ops_lookup(family);
381 if (af_ops->ao_compare == NULL) {
386 ret = af_ops->ao_compare(a, b, family, ~0, 0);
389 rtnl_link_af_ops_put(af_ops);