aboutsummaryrefslogtreecommitdiffstats
path: root/package/libnl-tiny/src/include/netlink/object-api.h
blob: 8a44fe90129fa4b119eb5ec143682428aa12dfdd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#
# drivers/scsi/aic7xxx/Makefile
#
# Makefile for the Linux aic7xxx SCSI driver.
#

O_TARGET := aic7xxx_drv.o

list-multi	:= aic7xxx.o aic79xx.o

obj-$(CONFIG_SCSI_AIC7XXX)	+= aic7xxx.o
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_SCSI_AIC79XX)	+= aic79xx.o
endif

EXTRA_CFLAGS += -I$(TOPDIR)/drivers/scsi -Werror
#EXTRA_CFLAGS += -g

# Platform Specific Files
obj-aic7xxx = aic7xxx_osm.o aic7xxx_proc.o

# Core Files
obj-aic7xxx += aic7xxx_core.o aic7xxx_93cx6.o
ifeq ($(CONFIG_AIC7XXX_REG_PRETTY_PRINT),y)
obj-aic7xxx += aic7xxx_reg_print.o
endif

#EISA Specific Files
AIC7XXX_EISA_ARCH = $(filter i386 alpha xen,$(ARCH))
ifneq ($(AIC7XXX_EISA_ARCH),)
obj-aic7xxx += aic7770.o
# Platform Specific EISA Files
obj-aic7xxx += aic7770_osm.o
endif

#PCI Specific Files
ifeq ($(CONFIG_PCI),y)
obj-aic7xxx += aic7xxx_pci.o
# Platform Specific PCI Files
obj-aic7xxx += aic7xxx_osm_pci.o
endif

# Platform Specific U320 Files
obj-aic79xx = aic79xx_osm.o aic79xx_proc.o aic79xx_osm_pci.o
# Core Files
obj-aic79xx += aic79xx_core.o aic79xx_pci.o
ifeq ($(CONFIG_AIC79XX_REG_PRETTY_PRINT),y)
obj-aic79xx += aic79xx_reg_print.o
endif

# Override our module desitnation
MOD_DESTDIR = $(shell cd .. && $(CONFIG_SHELL
/*
 * netlink/object-api.c		Object API
 *
 *	This library is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Lesser General Public
 *	License as published by the Free Software Foundation version 2.1
 *	of the License.
 *
 * Copyright (c) 2003-2007 Thomas Graf <tgraf@suug.ch>
 */

#ifndef NETLINK_OBJECT_API_H_
#define NETLINK_OBJECT_API_H_

#include <netlink/netlink.h>
#include <netlink/utils.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @ingroup object
 * @defgroup object_api Object API
 * @brief
 *
 * @par 1) Object Definition
 * @code
 * // Define your object starting with the common object header
 * struct my_obj {
 * 	NLHDR_COMMON
 * 	int		my_data;
 * };
 *
 * // Fill out the object operations structure
 * struct nl_object_ops my_ops = {
 * 	.oo_name	= "my_obj",
 * 	.oo_size	= sizeof(struct my_obj),
 * };
 *
 * // At this point the object can be allocated, you may want to provide a
 * // separate _alloc() function to ease allocting objects of this kind.
 * struct nl_object *obj = nl_object_alloc(&my_ops);
 *
 * // And release it again...
 * nl_object_put(obj);
 * @endcode
 *
 * @par 2) Allocating additional data
 * @code
 * // You may require to allocate additional data and store it inside
 * // object, f.e. assuming there is a field `ptr'.
 * struct my_obj {
 * 	NLHDR_COMMON
 * 	void *		ptr;
 * };
 *
 * // And at some point you may assign allocated data to this field:
 * my_obj->ptr = calloc(1, ...);
 *
 * // In order to not introduce any memory leaks you have to release
 * // this data again when the last reference is given back.
 * static void my_obj_free_data(struct nl_object *obj)
 * {
 * 	struct my_obj *my_obj = nl_object_priv(obj);
 *
 * 	free(my_obj->ptr);
 * }
 *
 * // Also when the object is cloned, you must ensure for your pointer
 * // stay valid even if one of the clones is freed by either making
 * // a clone as well or increase the reference count.
 * static int my_obj_clone(struct nl_object *src, struct nl_object *dst)
 * {
 * 	struct my_obj *my_src = nl_object_priv(src);
 * 	struct my_obj *my_dst = nl_object_priv(dst);
 *
 * 	if (src->ptr) {
 * 		dst->ptr = calloc(1, ...);
 * 		memcpy(dst->ptr, src->ptr, ...);
 * 	}
 * }
 *
 * struct nl_object_ops my_ops = {
 * 	...
 * 	.oo_free_data	= my_obj_free_data,
 * 	.oo_clone	= my_obj_clone,
 * };
 * @endcode
 *
 * @par 3) Object Dumping
 * @code
 * static int my_obj_dump_detailed(struct nl_object *obj,
 * 				   struct nl_dump_params *params)
 * {
 * 	struct my_obj *my_obj = nl_object_priv(obj);
 *
 * 	// It is absolutely essential to use nl_dump() when printing
 *	// any text to make sure the dumping parameters are respected.
 * 	nl_dump(params, "Obj Integer: %d\n", my_obj->my_int);
 *
 * 	// Before we can dump the next line, make sure to prefix
 *	// this line correctly.
 * 	nl_new_line(params);
 *
 * 	// You may also split a line into multiple nl_dump() calls.
 * 	nl_dump(params, "String: %s ", my_obj->my_string);
 * 	nl_dump(params, "String-2: %s\n", my_obj->another_string);
 * }
 *
 * struct nl_object_ops my_ops = {
 * 	...
 * 	.oo_dump[NL_DUMP_FULL]	= my_obj_dump_detailed,
 * };
 * @endcode
 *
 * @par 4) Object Attributes
 * @code
 * // The concept of object attributes is optional but can ease the typical
 * // case of objects that have optional attributes, e.g. a route may have a
 * // nexthop assigned but it is not required to.
 *
 * // The first step to define your object specific bitmask listing all
 * // attributes
 * #define MY_ATTR_FOO		(1<<0)
 * #define MY_ATTR_BAR		(1<<1)
 *
 * // When assigning an optional attribute to the object, make sure
 * // to mark its availability.
 * my_obj->foo = 123123;
 * my_obj->ce_mask |= MY_ATTR_FOO;
 *
 * // At any time you may use this mask to check for the availability
 * // of the attribute, e.g. while dumping
 * if (my_obj->ce_mask & MY_ATTR_FOO)
 * 	nl_dump(params, "foo %d ", my_obj->foo);
 *
 * // One of the big advantages of this concept is that it allows for
 * // standardized comparisons which make it trivial for caches to
 * // identify unique objects by use of unified comparison functions.
 * // In order for it to work, your object implementation must provide
 * // a comparison function and define a list of attributes which
 * // combined together make an object unique.
 *
 * static int my_obj_compare(struct nl_object *_a, struct nl_object *_b,
 * 			     uint32_t attrs, int flags)
 * {
 * 	struct my_obj *a = nl_object_priv(_a):
 * 	struct my_obj *b = nl_object_priv(_b):
 * 	int diff = 0;
 *
 * 	// We help ourselves in defining our own DIFF macro which will
 *	// call ATTR_DIFF() on both objects which will make sure to only
 *	// compare the attributes if required.
 * 	#define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR)
 *
 * 	// Call our own diff macro for each attribute to build a bitmask
 *	// representing the attributes which mismatch.
 * 	diff |= MY_DIFF(FOO, a->foo != b->foo)
 * 	diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar))
 *
 * 	return diff;
 * }
 *
 * // In order to identify identical objects with differing attributes
 * // you must specify the attributes required to uniquely identify
 * // your object. Make sure to not include too many attributes, this
 * // list is used when caches look for an old version of an object.
 * struct nl_object_ops my_ops = {
 * 	...
 * 	.oo_id_attrs		= MY_ATTR_FOO,
 * 	.oo_compare		= my_obj_compare,
 * };
 * @endcode
 * @{
 */

/**
 * Common Object Header
 *
 * This macro must be included as first member in every object
 * definition to allow objects to be cached.
 */
#define NLHDR_COMMON				\
	int			ce_refcnt;	\
	struct nl_object_ops *	ce_ops;		\
	struct nl_cache *	ce_cache;	\
	struct nl_list_head	ce_list;	\
	int			ce_msgtype;	\
	int			ce_flags;	\
	uint32_t		ce_mask;

/**
 * Return true if attribute is available in both objects
 * @arg A		an object
 * @arg B		another object
 * @arg ATTR		attribute bit
 *
 * @return True if the attribute is available, otherwise false is returned.
 */
#define AVAILABLE(A, B, ATTR)	(((A)->ce_mask & (B)->ce_mask) & (ATTR))

/**
 * Return true if attributes mismatch
 * @arg A		an object
 * @arg B		another object
 * @arg ATTR		attribute bit
 * @arg EXPR		Comparison expression
 *
 * This function will check if the attribute in question is available
 * in both objects, if not this will count as a mismatch.
 *
 * If available the function will execute the expression which must
 * return true if the attributes mismatch.
 *
 * @return True if the attribute mismatch, or false if they match.
 */
#define ATTR_MISMATCH(A, B, ATTR, EXPR)	(!AVAILABLE(A, B, ATTR) || (EXPR))

/**
 * Return attribute bit if attribute does not match
 * @arg LIST		list of attributes to be compared
 * @arg ATTR		attribute bit
 * @arg A		an object
 * @arg B		another object
 * @arg EXPR		Comparison expression
 *
 * This function will check if the attribute in question is available
 * in both objects, if not this will count as a mismatch.
 *
 * If available the function will execute the expression which must
 * return true if the attributes mismatch.
 *
 * In case the attributes mismatch, the attribute is returned, otherwise
 * 0 is returned.
 *
 * @code
 * diff |= ATTR_DIFF(attrs, MY_ATTR_FOO, a, b, a->foo != b->foo);
 * @endcode
 */
#define ATTR_DIFF(LIST, ATTR, A, B, EXPR) \
({	int diff = 0; \
	if (((LIST) & (ATTR)) && ATTR_MISMATCH(A, B, ATTR, EXPR)) \
		diff = ATTR; \
	diff; })

/**
 * Object Operations
 */
struct nl_object;
struct nl_object_ops
{
	/**
	 * Unique name of object type
	 *
	 * Must be in the form family/name, e.g. "route/addr"
	 */
	char *		oo_name;

	/** Size of object including its header */
	size_t		oo_size;

	/* List of attributes needed to uniquely identify the object */
	uint32_t	oo_id_attrs;

	/**
	 * Constructor function
	 *
	 * Will be called when a new object of this type is allocated.
	 * Can be used to initialize members such as lists etc.
	 */
	void  (*oo_constructor)(struct nl_object *);

	/**
	 * Destructor function
	 *
	 * Will be called when an object is freed. Must free all
	 * resources which may have been allocated as part of this
	 * object.
	 */
	void  (*oo_free_data)(struct nl_object *);

	/**
	 * Cloning function
	 *
	 * Will be called when an object needs to be cloned. Please
	 * note that the generic object code will make an exact
	 * copy of the object first, therefore you only need to take
	 * care of members which require reference counting etc.
	 *
	 * May return a negative error code to abort cloning.
	 */
	int  (*oo_clone)(struct nl_object *, struct nl_object *);

	/**
	 * Dumping functions
	 *
	 * Will be called when an object is dumped. The implementations
	 * have to use nl_dump(), nl_dump_line(), and nl_new_line() to
	 * dump objects.
	 *
	 * The functions must return the number of lines printed.
	 */
	void (*oo_dump[NL_DUMP_MAX+1])(struct nl_object *,
				       struct nl_dump_params *);

	/**
	 * Comparison function
	 *
	 * Will be called when two objects of the same type are
	 * compared. It takes the two objects in question, an object
	 * specific bitmask defining which attributes should be
	 * compared and flags to control the behaviour.
	 *
	 * The function must return a bitmask with the relevant bit
	 * set for each attribute that mismatches.
	 */
	int   (*oo_compare)(struct nl_object *, struct nl_object *,
			    uint32_t, int);


	char *(*oo_attrs2str)(int, char *, size_t);
};

/** @} */

#ifdef __cplusplus
}
#endif

#endif