GENEVE (Generic Network Virtualization Encapsulation) is a network
tunneling protocol that provides a flexible encapsulation format for
overlay networks. It uses UDP as the transport protocol and supports
variable-length metadata in the tunnel header.
This patch adds GENEVE tunnel to NM's platform layer:
- Add platform API functions (nm_platform_link_geneve_add,
nm_platform_link_get_lnk_geneve)
- Netlink message parsing for the following attributes:
* IFLA_GENEVE_ID - VNI (Virtual Network Identifier)
IPv4 and IPv6 remote
* IFLA_GENEVE_REMOTE
* IFLA_GENEVE_REMOTE6
TTL, TOS, and DF flags
* IFLA_GENEVE_TTL
* IFLA_GENEVE_TOS
* IFLA_GENEVE_DF
UDP destination port
* IFLA_GENEVE_PORT
- Add test cases for GENEVE tunnel creation and detection with two test
modes covering IPv4 and IPv6.
The implementation tries to follow the same patterns as other tunnel
types (GRE, VXLAN, etc.) and integrates with the existing platform
abstraction layer.
(cherry picked from commit 29c8bbe21a)
(cherry picked from commit b071b0fafa)
Add a function to compare two arrays of NMPlatformBridgeVlan. It will
be used in the next commit to compare the VLANs from platform to the
ones we want to set.
To compare in a performant way, the vlans need to be normalized (no
duplicated VLANS, ranges into their minimal expression...). Add the
function nmp_utils_bridge_vlan_normalize.
Co-authored-by: Íñigo Huguet <ihuguet@redhat.com>
It's not used. It's better to use SOCK_NONBLOCK flag for socket(), as we do.
Also, the implementation that blindly calls F_SETFL without merging the
existing flags from F_GETFL is just wrong. Drop it altogether.
We put all these structs inside the tagged union NMPObject.
Also, in a sense NMPlatformObject is the base "type" of all
these structs, meaning, it should be able to up and downcast.
Ensure the alignment matches.
This helps to avoid "-Wcast-align" warnings when trying to cast
a (NMPlatformObject*) to another (NMPlatformXXX *) type. Something
we commonly do.
We will extend IPv4 routes with the list of next hops. This field will
be heap allocated and be part of the NMPObjectIP4Route object, while
also being part of the identity. To support the ID operator that checks
fields of the NMPObject, add a "for_id" argument to the hash/cmp hooks.
Also, a function that sets cmd_obj_{hash_update,cmp}() MUST not set
cmd_plobj_id_{hashupdate,cmp}(), as it would have overlapping
functionality. Therefore, the objects that define
cmd_obj_{hash_update,cmp}() need to fully implement the ID comparison.
Add a len argument to nlmsg_alloc() and nlmsg_alloc_simple(). After
that, nlmsg_alloc_size() can be dropped. Also, rename
nlmsg_alloc_simple() to nlmsg_alloc_new().
- replace "s_flags" field by explicit boolean fields.
- "s_msg_peek" now is simplified. Previously, we would default
to peek, unless the user caller nl_socket_disable_msg_peek()
or set nl_socket_set_msg_buf_size(). Simplify that. We now
default to peek, unless NL_SOCKET_FLAGS_DISABLE_MSG_PEEK is set.
We have no callers that call nl_socket_set_msg_buf_size(),
so we can simplify that logic and just enable peeking by default.
- keep "s_auto_ack" field, although it is always TRUE and there
is no API to toggle that. However, it is kept as a self-documenting
thing, so we would know the relevant places where auto-ack matters.
- drop nl_socket_disable_msg_peek(). We have no caller of this function
and we can set peeking in nl_socket_new(). We also don't need to
change it after creation of the socket.
Create and use new nl_socket_new().
nl_socket_alloc() really does nothing but allocating the struct and
initializing the fd to -1. In all cases, we want to call nl_connect()
right after.
Combine the two. Then we also cannot have a "struct nl_sock" without a
valid fd. This means several error checks can be dropped.
Note that former nl_connect() did several things at once. Maybe, for
more flexibility one would need to tweak what should be done there.
For now that is not necessary. In any case, if we need more flexibility,
then we would control what nl_connect() (now nl_socket_new()) does, and not
the split between nl_socket_alloc() and nl_connect().
gcc-12.0.1-0.8.fc36 is annoying with false positives.
It's related to g_error() and its `for(;;) ;`.
For example:
../src/libnm-glib-aux/nm-shared-utils.c: In function 'nm_utils_parse_inaddr_bin_full':
../src/libnm-glib-aux/nm-shared-utils.c:1145:26: error: dangling pointer to 'error' may be used [-Werror=dangling-pointer=]
1145 | error->message);
| ^~
/usr/include/glib-2.0/glib/gmessages.h:343:32: note: in definition of macro 'g_error'
343 | __VA_ARGS__); \
| ^~~~~~~~~~~
../src/libnm-glib-aux/nm-shared-utils.c:1133:31: note: 'error' declared here
1133 | gs_free_error GError *error = NULL;
| ^~~~~
/usr/include/glib-2.0/glib/gmessages.h:341:25: error: dangling pointer to 'addrbin' may be used [-Werror=dangling-pointer=]
341 | g_log (G_LOG_DOMAIN, \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
342 | G_LOG_LEVEL_ERROR, \
| ~~~~~~~~~~~~~~~~~~~~~~~
343 | __VA_ARGS__); \
| ~~~~~~~~~~~~
../src/libnm-glib-aux/nm-shared-utils.c:1141:13: note: in expansion of macro 'g_error'
1141 | g_error("unexpected assertion failure: could parse \"%s\" as %s, but not accepted by "
| ^~~~~~~
../src/libnm-glib-aux/nm-shared-utils.c:1112:14: note: 'addrbin' declared here
1112 | NMIPAddr addrbin;
| ^~~~~~~
I think the warning could potentially be useful and prevent real bugs.
So don't disable it altogether, but go through the effort to suppress it
at the places where it currently happens.
Note that NM_PRAGMA_WARNING_DISABLE_DANGLING_POINTER macro only expands
to suppressing the warning with __GNUC__ equal to 12. The purpose is to
only suppress the warning where we know we want to. Hopefully other gcc
versions don't have this problem.
I guess, we could also write a NM_COMPILER_WARNING() check in
"m4/compiler_options.m4", to disable the warning if we detect it. But
that seems too cumbersome.
"nm-test-utils.h" is a header-only, helper library for our unit tests.
It was somewhat unmotivated in "shared/nm-utils", because all tests use
it, but it was not part of a "module".
Move it to "src/libnm-glib-aux/". It fits there very well. They both
have (only) a dependency on glib.