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:
parent
183e86913a
commit
2fbab02ba8
2 changed files with 150 additions and 39 deletions
189
doc/core.txt
189
doc/core.txt
|
@ -7,7 +7,7 @@
|
|||
Netlink Library (libnl)
|
||||
=======================
|
||||
Thomas Graf <tgraf@suug.ch>
|
||||
3.2, Sep 13 2011:
|
||||
3.2, May 9 2011:
|
||||
:numbered:
|
||||
|
||||
== Introduction
|
||||
|
@ -59,32 +59,47 @@ The low level APIs are described in:
|
|||
|
||||
=== 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
|
||||
a specific version of libnl is available on the system. The example
|
||||
below also shows how to retrieve the +CFLAGS+ and linking dependencies
|
||||
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]
|
||||
----
|
||||
PKG_CHECK_MODULES(LIBNL3, libnl-3.0 >= 3.1, [have_libnl3=yes], [have_libnl3=no])
|
||||
if (test "${have_libnl3}" = "yes"); then
|
||||
CFLAGS="$LIBNL3_CFLAGS"
|
||||
LIBS="$LIBNL3_LIBS"
|
||||
CFLAGS+="$LIBNL3_CFLAGS"
|
||||
LIBS+="$LIBNL3_LIBS"
|
||||
fi
|
||||
----
|
||||
|
||||
NOTE: The pkgconfig file is named +libnl-3.0.pc+ for historic reasons, it also
|
||||
covers library versions >= 3.1.
|
||||
|
||||
.Main Header
|
||||
.Header Files
|
||||
|
||||
The main header is `<netlink/netlink.h>`. Additional headers need to
|
||||
be included in your sources depending on the subsystems your program
|
||||
makes use of.
|
||||
The main header file is `<netlink/netlink.h>`. Additional headers may need to
|
||||
be included in your sources depending on the subsystems and components your
|
||||
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]
|
||||
-----
|
||||
#include <netlink/version.h>
|
||||
|
@ -94,7 +109,7 @@ makes use of.
|
|||
#endif
|
||||
-----
|
||||
|
||||
.Linking to libnl
|
||||
.Linking
|
||||
-----
|
||||
$ gcc myprogram.c -o myprogram $(pkgconfig --cflags --libs libnl-3.0)
|
||||
-----
|
||||
|
@ -120,13 +135,12 @@ $ NLDBG=2 ./myprogram
|
|||
| 4 | Even less important messages
|
||||
|===============================================================
|
||||
|
||||
.Debugging Netlink Messages
|
||||
.Debugging the Netlink Protocol
|
||||
|
||||
Often it is useful to peek into the stream of netlink messages
|
||||
exchanged with other sockets. Setting the environment variable
|
||||
+NLCB=debug+ will cause the debugging message handlers to be used
|
||||
causing the netlink messages exchanged to be printed to +stderr+ in a
|
||||
human readable format:
|
||||
It is often useful to peek into the stream of netlink messages exchanged
|
||||
with other sockets. Setting the environment variable +NLCB=debug+ will
|
||||
cause the debugging message handlers to be used which in turn print the
|
||||
netlink messages exchanged in a human readable format to to +stderr+:
|
||||
|
||||
-----
|
||||
$ 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
|
||||
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]]
|
||||
=== Message Format
|
||||
|
||||
|
@ -395,7 +495,7 @@ The following standard flags are defined
|
|||
#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_ACK` - ACK message requested, see <<core_msg_ack>>.
|
||||
- `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
|
||||
protocols.
|
||||
|
||||
[[core_seq_num]]
|
||||
=== Sequence Numbers
|
||||
|
||||
Netlink allows the use of sequence numbers to help relate replies to
|
||||
requests. It should be noted that unlike in protocols such as TCP
|
||||
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
|
||||
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
|
||||
<<core_sk_seq_num>> for more information on how to use sequence numbers.
|
||||
|
@ -469,16 +570,15 @@ See <<core_sk_multicast>>
|
|||
== Netlink Sockets
|
||||
|
||||
In order to use the netlink protocol, a netlink socket is required.
|
||||
Each socket defines a completely independent context for sending and
|
||||
receiving of messages. An application may use multiple sockets for the
|
||||
same netlink protocol, e.g. one socket to send requests and receive
|
||||
replies and another socket subscribed to a multicast group to receive
|
||||
notifications.
|
||||
Each socket defines an independent context for sending and receiving of
|
||||
messages. An application may make use multiple sockets, e.g. a socket to
|
||||
send requests and receive the replies and another socket subscribed to a
|
||||
multicast group to receive notifications.
|
||||
|
||||
=== Allocation & Freeing
|
||||
=== Socket structure (struct nl_sock)
|
||||
|
||||
The netlink socket and all its related attributes are represented by
|
||||
+struct nl_sock+.
|
||||
The netlink socket and all related attributes including the actual file
|
||||
descriptor are represented by +struct nl_sock+.
|
||||
|
||||
[source,c]
|
||||
--------
|
||||
|
@ -488,18 +588,22 @@ struct nl_sock *nl_socket_alloc(void)
|
|||
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]]
|
||||
=== Sequence Numbers
|
||||
|
||||
The library will automatically take care of sequence number handling
|
||||
for the application. A sequence number counter is stored in struct
|
||||
nl_sock which is meant to be used when sending messages which will
|
||||
produce a reply, error or any other message which needs to be
|
||||
related to the original message.
|
||||
for the application. A sequence number counter is stored in the
|
||||
socket structure which is used and incremented automatically when a
|
||||
message needs to be sent which is expected to generate a reply such as
|
||||
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()
|
||||
which will return the current value of the counter and increment it by
|
||||
one afterwards.
|
||||
Alternatively, the counter can be used directly via the function
|
||||
nl_socket_use_seq(). It will return the current value of the counter
|
||||
and increment it by one afterwards.
|
||||
|
||||
[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
|
||||
themselves though. When using nl_send_auto() the sequence number is
|
||||
filled out automatically and matched again on the receiving side. See
|
||||
<<core_send_recv>> for more information.
|
||||
filled in automatically and matched again when a reply is received. See
|
||||
section <<core_send_recv>> for more information.
|
||||
|
||||
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
|
||||
|
@ -524,6 +628,9 @@ used to receive notification messages.
|
|||
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]]
|
||||
=== 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
|
||||
bitmask which limited the number of groups per protocol family to 32.
|
||||
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]
|
||||
--------
|
||||
|
@ -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);
|
||||
--------
|
||||
|
||||
See section <<core_addressing>> for more information on port numbers.
|
||||
|
||||
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
|
||||
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);
|
||||
--------
|
||||
|
||||
See section <<core_addressing>> for more information on port numbers.
|
||||
|
||||
.File Descriptor
|
||||
|
||||
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);
|
||||
--------
|
||||
|
||||
NOTE: Processing of NETLINK_PKTINFO has not been implemented yet.
|
||||
CAUTION: Processing of NETLINK_PKTINFO has not been implemented yet.
|
||||
|
||||
[[core_send_recv]]
|
||||
== 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);
|
||||
--------
|
||||
|
||||
NOTE: Calling nlmsg_set_default_size() does not change the maximum
|
||||
message size of already allocated messages.
|
||||
CAUTION: Calling nlmsg_set_default_size() does not change the maximum
|
||||
message size of already allocated messages.
|
||||
|
||||
[source,c]
|
||||
--------
|
||||
|
|
BIN
doc/images/addressing.png
Normal file
BIN
doc/images/addressing.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Loading…
Add table
Reference in a new issue