dect
/
libnl
Archived
13
0
Fork 0

doc: add section about addressing

Adds a new section to netlink fundamentals explaining the common
addressing use cases and illustrates kernel->user, user->user,
and user->kernel communication.
This commit is contained in:
Thomas Graf 2012-05-09 15:02:40 +02:00
parent 183e86913a
commit 2fbab02ba8
2 changed files with 150 additions and 39 deletions

View File

@ -7,7 +7,7 @@
Netlink Library (libnl) Netlink Library (libnl)
======================= =======================
Thomas Graf <tgraf@suug.ch> Thomas Graf <tgraf@suug.ch>
3.2, Sep 13 2011: 3.2, May 9 2011:
:numbered: :numbered:
== Introduction == Introduction
@ -59,32 +59,47 @@ The low level APIs are described in:
=== Linking to this Library === Linking to this Library
.Checking the presence using autoconf .Checking the presence of the library using autoconf
Projects using autoconf may use +PKG_CHECK_MODULES()+ to check if Projects using autoconf may use +PKG_CHECK_MODULES()+ to check if
a specific version of libnl is available on the system. The example a specific version of libnl is available on the system. The example
below also shows how to retrieve the +CFLAGS+ and linking dependencies below also shows how to retrieve the +CFLAGS+ and linking dependencies
required to link against the library. required to link against the library.
The following example shows how to check for a specific version of libnl. If
found, it extends the `CFLAGS` and `LIBS` variable appropriately:
[source] [source]
---- ----
PKG_CHECK_MODULES(LIBNL3, libnl-3.0 >= 3.1, [have_libnl3=yes], [have_libnl3=no]) PKG_CHECK_MODULES(LIBNL3, libnl-3.0 >= 3.1, [have_libnl3=yes], [have_libnl3=no])
if (test "${have_libnl3}" = "yes"); then if (test "${have_libnl3}" = "yes"); then
CFLAGS="$LIBNL3_CFLAGS" CFLAGS+="$LIBNL3_CFLAGS"
LIBS="$LIBNL3_LIBS" LIBS+="$LIBNL3_LIBS"
fi fi
---- ----
NOTE: The pkgconfig file is named +libnl-3.0.pc+ for historic reasons, it also NOTE: The pkgconfig file is named +libnl-3.0.pc+ for historic reasons, it also
covers library versions >= 3.1. covers library versions >= 3.1.
.Main Header .Header Files
The main header is `<netlink/netlink.h>`. Additional headers need to The main header file is `<netlink/netlink.h>`. Additional headers may need to
be included in your sources depending on the subsystems your program be included in your sources depending on the subsystems and components your
makes use of. program makes use of.
[source,c]
-----
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/route/link.h>
-----
.Version Dependent Code
If your code wishes to be capable to link against multiple versions of libnl
you may have direct the compiler to only include portions on the code depending
on the version of libnl that it is compiled against.
.Version Checking
[source,c] [source,c]
----- -----
#include <netlink/version.h> #include <netlink/version.h>
@ -94,7 +109,7 @@ makes use of.
#endif #endif
----- -----
.Linking to libnl .Linking
----- -----
$ gcc myprogram.c -o myprogram $(pkgconfig --cflags --libs libnl-3.0) $ gcc myprogram.c -o myprogram $(pkgconfig --cflags --libs libnl-3.0)
----- -----
@ -120,13 +135,12 @@ $ NLDBG=2 ./myprogram
| 4 | Even less important messages | 4 | Even less important messages
|=============================================================== |===============================================================
.Debugging Netlink Messages .Debugging the Netlink Protocol
Often it is useful to peek into the stream of netlink messages It is often useful to peek into the stream of netlink messages exchanged
exchanged with other sockets. Setting the environment variable with other sockets. Setting the environment variable +NLCB=debug+ will
+NLCB=debug+ will cause the debugging message handlers to be used cause the debugging message handlers to be used which in turn print the
causing the netlink messages exchanged to be printed to +stderr+ in a netlink messages exchanged in a human readable format to to +stderr+:
human readable format:
----- -----
$ NLCB=debug ./myprogram $ NLCB=debug ./myprogram
@ -180,6 +194,92 @@ protocol uses its own protocol number (e.g. +NETLINK_ROUTE+,
port number, formerly referred to as PID, which uniquely identifies port number, formerly referred to as PID, which uniquely identifies
each peer. each peer.
[[core_addressing]]
=== Addressing
The netlink address (port) consists of a 32bit integer. Port 0 (zero)
is reserved for the kernel and refers to the kernel side socket of each
netlink protocol family. Other port numbers usually refer to user space
owned sockets, although this is not enforced.
NOTE: In the beginning, it was common practice to use the process
identifier (PID) as the local port number. This became unpractical
with the introduction of threaded netlink applications and
applications requiring multiple sockets. Therefore libnl generates
unique port numbers based on the process identifier and adds an
offset to it allowing for multiple sockets to be used. The initial
socket will still equal to the process identifier for backwards
compatibility reasons.
image:addressing.png["Addressing Example"]
The above figure illustrates three applications and the kernel side
exposing two kernel side sockets. It shows the common netlink use
cases:
* User space to kernel
* User space to user space
* Listening to kernel multicast notifications
.User Space to Kernel
The most common form of netlink usage is for a user space application
to send requests to the kernel and process the reply which is either
an error message or a success notification.
["mscgen"]
--------
msc {
App1,App2,Kernel;
App1=>Kernel [label="request (src=11, dst=0)"];
Kernel<=App1 [label="reply (src=0, dst=11)"];
...;
App2=>Kernel [label="request (src=21, dst=0)"];
Kernel<=App2 [label="reply (src=0, dst=21)"];
}
--------
.User Space to User Space
Netlink may also be used as an IPC mechanism to communicate between user
space applications directly. Communication is not limited to two peers,
any number of peers may communicate with each other and multicasting
capabilities allow to reach multiple peers with a single message.
In order for the sockets to be visible to each other, both sockets must
be created for the same netlink protocol family.
["mscgen"]
--------
msc {
App2,App3;
App2=>App3 [label="request (src=22, dst=31)"];
App2<=App3 [label="reply (src=31, dst=22)"];
...;
}
--------
.User space listening to kernel notifications
This form of netlink communication is typically found in user space
daemons that need to act on certain kernel events. Such daemons will
typically maintain a netlink socket subscribed to a multicast group that
is used by the kernel to notify interested user space parties about
specific events.
["mscgen"]
--------
msc {
Kernel,App3;
Kernel=>App3 [label="notification (src=0, group=foo)"];
...;
}
--------
Use of multicasting is preferred over direct addressing due to the
flexibility in exchanging the user space component at any time without
the kernel noticing.
[[core_msg_format]] [[core_msg_format]]
=== Message Format === Message Format
@ -395,7 +495,7 @@ The following standard flags are defined
#define NLM_F_ECHO 8 #define NLM_F_ECHO 8
-------- --------
- `NLM_F_REQUEST` - Message is a request, see <<core_msg_type>>. - `NLM_F_REQUEST` - Message is a request, see <<core_msg_types>>.
- `NLM_F_MULTI` - Multipart message, see <<core_multipart>> - `NLM_F_MULTI` - Multipart message, see <<core_multipart>>
- `NLM_F_ACK` - ACK message requested, see <<core_msg_ack>>. - `NLM_F_ACK` - ACK message requested, see <<core_msg_ack>>.
- `NLM_F_ECHO` - Request to echo the request. - `NLM_F_ECHO` - Request to echo the request.
@ -447,13 +547,14 @@ flags are mutually exclusive to the `GET` flags:
Behaviour of these flags may differ slightly between different netlink Behaviour of these flags may differ slightly between different netlink
protocols. protocols.
[[core_seq_num]]
=== Sequence Numbers === Sequence Numbers
Netlink allows the use of sequence numbers to help relate replies to Netlink allows the use of sequence numbers to help relate replies to
requests. It should be noted that unlike in protocols such as TCP requests. It should be noted that unlike in protocols such as TCP
there is no strict enforcment of the sequence number. The sole purpose there is no strict enforcment of the sequence number. The sole purpose
of sequence numbers is to assist a sender in relating replies to the of sequence numbers is to assist a sender in relating replies to the
corresponding requests. See <<core_msg_type>> for more information. corresponding requests. See <<core_msg_types>> for more information.
Sequence numbers are managed on a per socket basis, see Sequence numbers are managed on a per socket basis, see
<<core_sk_seq_num>> for more information on how to use sequence numbers. <<core_sk_seq_num>> for more information on how to use sequence numbers.
@ -469,16 +570,15 @@ See <<core_sk_multicast>>
== Netlink Sockets == Netlink Sockets
In order to use the netlink protocol, a netlink socket is required. In order to use the netlink protocol, a netlink socket is required.
Each socket defines a completely independent context for sending and Each socket defines an independent context for sending and receiving of
receiving of messages. An application may use multiple sockets for the messages. An application may make use multiple sockets, e.g. a socket to
same netlink protocol, e.g. one socket to send requests and receive send requests and receive the replies and another socket subscribed to a
replies and another socket subscribed to a multicast group to receive multicast group to receive notifications.
notifications.
=== Allocation & Freeing === Socket structure (struct nl_sock)
The netlink socket and all its related attributes are represented by The netlink socket and all related attributes including the actual file
+struct nl_sock+. descriptor are represented by +struct nl_sock+.
[source,c] [source,c]
-------- --------
@ -488,18 +588,22 @@ struct nl_sock *nl_socket_alloc(void)
void nl_socket_free(struct nl_sock *sk) void nl_socket_free(struct nl_sock *sk)
-------- --------
The application must allocate an instance of +struct nl_sock+ for each
netlink socket it wishes to use.
[[core_sk_seq_num]] [[core_sk_seq_num]]
=== Sequence Numbers === Sequence Numbers
The library will automatically take care of sequence number handling The library will automatically take care of sequence number handling
for the application. A sequence number counter is stored in struct for the application. A sequence number counter is stored in the
nl_sock which is meant to be used when sending messages which will socket structure which is used and incremented automatically when a
produce a reply, error or any other message which needs to be message needs to be sent which is expected to generate a reply such as
related to the original message. an error or any other message type that needs to be related to the
original message.
The counter can be used directly with the function nl_socket_use_seq() Alternatively, the counter can be used directly via the function
which will return the current value of the counter and increment it by nl_socket_use_seq(). It will return the current value of the counter
one afterwards. and increment it by one afterwards.
[source,c] [source,c]
-------- --------
@ -510,8 +614,8 @@ unsigned int nl_socket_use_seq(struct nl_sock *sk);
Most applications will not want to deal with sequence number handling Most applications will not want to deal with sequence number handling
themselves though. When using nl_send_auto() the sequence number is themselves though. When using nl_send_auto() the sequence number is
filled out automatically and matched again on the receiving side. See filled in automatically and matched again when a reply is received. See
<<core_send_recv>> for more information. section <<core_send_recv>> for more information.
This behaviour can and must be disabled if the netlink protocol This behaviour can and must be disabled if the netlink protocol
implemented does not use a request/reply model, e.g. when a socket is implemented does not use a request/reply model, e.g. when a socket is
@ -524,6 +628,9 @@ used to receive notification messages.
void nl_socket_disable_seq_check(struct nl_sock *sk); void nl_socket_disable_seq_check(struct nl_sock *sk);
-------- --------
For more information on the theory behind netlink sequence numbers,
see section <<core_seq_num>>.
[[core_sk_multicast]] [[core_sk_multicast]]
=== Multicast Group Subscriptions === Multicast Group Subscriptions
@ -535,7 +642,7 @@ commonly used to implement event notifications.
Prior to kernel 2.6.14 the group subscription was performed using a Prior to kernel 2.6.14 the group subscription was performed using a
bitmask which limited the number of groups per protocol family to 32. bitmask which limited the number of groups per protocol family to 32.
This outdated interface can still be accessed via the function This outdated interface can still be accessed via the function
nl_join_groups even though it is not recommended for new code. nl_join_groups() even though it is not recommended for new code.
[source,c] [source,c]
-------- --------
@ -663,6 +770,8 @@ uint32_t nl_socket_get_local_port(const struct nl_sock *sk);
void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port); void nl_socket_set_local_port(struct nl_sock *sk, uint32_t port);
-------- --------
See section <<core_addressing>> for more information on port numbers.
CAUTION: Overwriting the local port is possible but you have to ensure CAUTION: Overwriting the local port is possible but you have to ensure
that the provided value is unique and no other socket in any other that the provided value is unique and no other socket in any other
application is using the same value. application is using the same value.
@ -685,6 +794,8 @@ uint32_t nl_socket_get_peer_port(const struct nl_sock *sk);
void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port); void nl_socket_set_peer_port(struct nl_sock *sk, uint32_t port);
-------- --------
See section <<core_addressing>> for more information on port numbers.
.File Descriptor .File Descriptor
Netlink uses the BSD socket interface, therefore a file descriptor is Netlink uses the BSD socket interface, therefore a file descriptor is
@ -776,7 +887,7 @@ function can be used to enable/disable receival of packet information.
int nl_socket_recv_pktinfo(struct nl_sock *sk, int state); int nl_socket_recv_pktinfo(struct nl_sock *sk, int state);
-------- --------
NOTE: Processing of NETLINK_PKTINFO has not been implemented yet. CAUTION: Processing of NETLINK_PKTINFO has not been implemented yet.
[[core_send_recv]] [[core_send_recv]]
== Sending and Receiving of Messages / Data == Sending and Receiving of Messages / Data
@ -1350,8 +1461,8 @@ size for messages by calling nlmsg_set_default_size():
void nlmsg_set_default_size(size_t); void nlmsg_set_default_size(size_t);
-------- --------
NOTE: Calling nlmsg_set_default_size() does not change the maximum CAUTION: Calling nlmsg_set_default_size() does not change the maximum
message size of already allocated messages. message size of already allocated messages.
[source,c] [source,c]
-------- --------

BIN
doc/images/addressing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB