Previously, we might have a pending action 'waiting-for-supplicant'
registered, although the device was not waiting:
<info> [1549611177.5815] device (wlan0): supplicant interface state: starting -> ready
<debug> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): P2P: Releasing WPA supplicant interfaces.
<debug> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): P2P: WPA supplicant management interface changed to /fi/w1/wpa_supplicant1/Interfaces/1.
<trace> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): remove_pending_action (0): 'waiting-for-supplicant' not pending (expected)
<debug> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): constructed (NMDeviceWifiP2P)
<debug> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): add_pending_action (1): 'waiting-for-supplicant'
The previous commit already fixed this bug by dropping the constructor
property for NM_DEVICE_WIFI_P2P_MGMT_IFACE.
Still, refactor handling of pending actions to keep track of whether we
have a pending action registered.
We already have a setter function nm_device_wifi_p2p_set_mgmt_iface()
as we may need to change the mgmt-iface later on. Use that to set the
supplicant interface instead of a constructor property.
That makes the object creation simpler, because nothing noteworthy
happens, until the very last statement in constructed() to add the
pending action.
Use the NM_ERRNO_NATIVE() macro that asserts that these errno numbers are
indeed positive. Using the macro also serves as a documentation of what
the meaning of these numbers is.
That is often not obvious, whether we have an nm_errno(), an nm_errno_native()
(from <errno.h>), or another error number (e.g. WaitForNlResponseResult). This
situation already improved by merging netlink error codes (nle),
NMPlatformError enum and <errno.h> as nm_errno(). But we still must
always be careful about not to mix error codes from different
domains or transform them appropriately (like nm_errno_from_native()).
Using strtol() correctly proves to be hard.
Usually, we want to also check that the end pointer is points to the end
of the string. Othewise, we silently accept trailing garbage.
When the logging level is DEBUG or TRACE, we keep all the sysctl
values we read in a cache to log how they change. Currently there is
no limit on the size of this cache and it can take a large amount of
memory.
Implement a LRU cache where the oldest entries are deleted to make
space for new ones.
https://github.com/NetworkManager/NetworkManager/pull/294
nm_ip_route_get_prefix() and plen are guint type, hence the following
is not correct:
plen = nm_ip_route_get_prefix (route1);
r = plen - nm_ip_route_get_prefix (route2);
if (r)
return r > 0 ? 1 : -1;
Use the macro, it gets subtle cases like this right.
Fixes: b32bb36c61
The right way is IN6_ADDR_INIT_ANY.
While at it, don't initialize multiple variables in the same line.
../src/devices/nm-device-ip-tunnel.c:153:29: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
struct in6_addr local6 = { 0 }, remote6 = { 0 };
^
{}
NMIPAddr contains an unnamed union. We have to either explicitly
initialize one field, or omit it.
../shared/nm-utils/nm-shared-utils.c:38:36: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
const NMIPAddr nm_ip_addr_zero = { 0 };
^
{}
The cast is bogus and leads to a compiler warning:
[424/583] Compiling C object src/devices/wifi/914a32e@@nm-device-plugin-wifi@sha/nm-device-iwd.c.o.
In file included from ../shared/nm-default.h:293,
from ../src/devices/wifi/nm-device-iwd.c:21:
../src/devices/wifi/nm-device-iwd.c: In function ‘nm_device_iwd_set_dbus_object’:
../src/devices/wifi/nm-device-iwd.c:2404:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
if (!nm_g_object_ref_set ((GObject **) &priv->dbus_obj, (GObject *) object))
../shared/nm-utils/nm-macros-internal.h:1048:13: note: in definition of macro ‘nm_g_object_ref_set’
typeof (*(pp)) *const _pp = (pp); \
^~
The test should check the behavior with "const typeof(a)" in a macro,
where "a" itself is const. For that we don't need a double const
declaration of v2.
Also, that fixes an actual compiler warning:
../src/tests/test-general.c: In function ‘test_duplicate_decl_specifier’:
../src/tests/test-general.c:1669:8: warning: duplicate ‘const’ declaration specifier [-Wduplicate-decl-specifier]
const const int v2 = 3;
^~~~~
For static functions inside a module, the compiler determines on its own
whether to inline the function.
Also, "inline" was used at some places that don't immediatly look like
candidates for inlining. It was most likely a copy&paste error.
When SAE key managmenet is used, the supplicant can still use the "psk"
property. Only when the pass phrase doesn't conform to WPA-PSK
limitations, the sae_password must be used.
Like also done for autotools, create and use intermediate libraries
from "shared/nm-utils/".
Also, replace "shared_dep" by "shared_nm_utils_base_dep". We don't
need super fine-grained selection of what we link. We can always
link in "shared/libnm-utils-base.a", and let the linker throw away
unsed parts.
NMPNetns instances are immutable, hence they can be easily shared
between threads. All we need, is that the stack of namespaces is
thread-local.
Also note that NMPNetns uses almost no other API, except some bits from
"shared/nm-utils/" and nm-logging. These parts are already supposed to
be thread-safe.
The only complications is that when the thread exits, we need to
destroy the NMPNetns instances. That is especially important because
they hold file descriptors. This is accomplished using pthread's
thread-specific data. An alternative would be C11 threads' tss_create(),
but not all systems that we run against support that yet. This means,
we need to link with pthreads, but we already do that anyway.
Note that glib also requires pthreads. So, we don't get an additional
dependency here.
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
Instead of having two functions nm_logging_set_syslog_identifier()
and nm_logging_set_prefix(), merge them.
They must both be called at earliest point and together. No point
in giving them the appearance that they could be called any time.
This variable has other requirements for multi-threaded access (it will
only be accessible from the main-thread). Move it to a separate global
variable to make that clearer.
The distinction between only reading static data and modifying it,
is important when making nm-logging thread-safe.
This change should make it easier to find the places where we modify
data.