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
189
doc/core.txt
189
doc/core.txt
|
@ -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]
|
||||||
--------
|
--------
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Reference in New Issue