There is however a serious issue currently: when NetworkManager creates
virtual devices, it starts from an unrealized NMDevice, creates the
netdev device, realizes the device, and transitions through states
UNMANAGED and DISCONNECTED. Thereby, the state of NMDevice gets cleared
again. That means, if the profile has "connection.stable-id=${RANDOM}"
and "ethernet.cloned-mac-address=stable", then we will first set a
random MAC address when creating the device. Then, the NMDevice
transitions through UNMANAGED state, forgets the MAC address it
generated and creates a new MAC address in stage 1. This should be
fixed by better handling unrealized devices. It also affects all
software devices that set the MAC address upon creation of the
interfaces (as they all should).
In several cases, the layer 2 and layer 3 type are very similar, also from
kernel's point of view. For example, "gre"/"gretap" and "ip6tnl"/"ip6gre"/"ip6gretap"
and "macvlan"/"macvtap".
While it makes sense that these have different NMLinkType types
(NM_LINK_TYPE_MACV{LAN,TAP}) and different NMPObject types
(NMPObjectLnkMacv{lan,tap}), it makes less sense that they have
different NMPlatformLnk* structs.
Remove the NMPlatformLnkMacvtap typedef. A typedef does not make things simpler,
but is rather confusing. Because several API that we would usually have, does
not exist for the typedef (e.g. there is no nm_platform_lnk_macvtap_to_string()).
Note that we also don't have such a typedef for NMPlatformLnkIp6Tnl
and NMPlatformLnkGre, which has the same ambiguity between the link type
and the struct with the data.
IP tunnels honor ethernet.cloned-mac-address. That is a MAC address of 6 bytes (ETH_ALEN).
Note that for example for gre tunnels, kernel exposes an address 00:00:00:00. Hence, trying
to set ethernet.cloned-mac-address with an gre tunnel leads to an assertion failure.
Instead, report and log a regular error.
The 'retracted' event is emitted when the client receives a NAK in the
rebooting, requesting, renewing or rebinding state, while 'expired'
means that the client wasn't able to renew the lease before expiry.
In both cases the old lease is no longer valid and n-dhcp4 keep trying
to get a lease, so the two events should be handlded in the same way.
Note that the systemd client doesn't have a 'retracted' event and
considers all NAKs as 'expired' events.
Don't build the same sources multiple times. The test code should
statically link against the tested code, just like the device plugin
that uses the code in production.
Oddly enough, valgrind was not complaining about this leak...
Fixes: 87b2d783b6 ('core: accept 'ssids':aay option in RequestScan() dictionary parameter')
Previously NetworkManager would wrongly add a broadcast address for the
network prefix that would collide with the IP address of the host on
the other end of the point-to-point link thus exhausting the IP address
space of the /31 network and preventing communication between the two
nodes.
Configuring a /31 address before this commit:
IP addr -> 10.0.0.0/31, broadcast addr -> 10.0.0.1
If 10.0.0.1 is configured as a broadcast address the communication
with host 10.0.0.1 will not be able to take place.
Configuring a /31 address after this commit:
IP addr -> 10.0.0.0/31, no broadcast address
Thus 10.0.0.0/31 and 10.0.0.1/31 are able to correctly communicate.
See RFC-3021. https://tools.ietf.org/html/rfc3021https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/295https://bugzilla.redhat.com/show_bug.cgi?id=1764986
Keyfile support was initially added under GPL-2.0+ license as part of
core. It was moved to "libnm-core" in commit 59eb5312a5 ('keyfile: merge
branch 'th/libnm-keyfile-bgo744699'').
"libnm-core" is statically linked with by core and "libnm". In
the former case under terms of GPL-2.0+ (good) and in the latter case
under terms of LGPL-2.1+ (bad).
In fact, to this day, "libnm" doesn't actually use the code. The linker
will probably remove all the GPL-2.0+ symbols when compiled with
gc-sections or LTO. Still, linking them together in the first place
makes "libnm" only available under GPL code (despite the code
not actually being used).
Instead, move the GPL code to a separate static library
"shared/nm-keyfile/libnm-keyfile.la" and only link it to the part
that actually uses the code (and which is GPL licensed too).
This fixes the license violation.
Eventually, it would be very useful to be able to expose keyfile
handling via "libnm". However that is not straight forward due to the
licensing conflict.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/381
We don't need a separate "GSList *chains" to track the NMAuthChain
requests for the agents. Every agent should only have one auth-chain in
fly at any time. We can attach that NMAuthChain to the secret-agent.
Also, fix a race where:
1) A secret agent registers. We would start an auth-chain check, but not
yet track the secret agent.
2) Then the secret agent unregisters. The unregistration request will fail,
because the secret agent is not yet in the list of fully registered agents.
The same happens if the secret agent disconnects at this point.
agent_disconnect_cb() would not find the secret agent to remove.
3) afterwards, authentication completes and we register the
secret-agent, although we should not.
There is also another race: if we get authority_changed_cb() we would
not restart the authentication for the secret-agent that is still
registering. Hence, we don't know whether the result once it completes
would already contain the latest state.
Don't access the singleton getter here. Pass the agent-manager argument
instead to maybe_remove_agent_on_error().
Also, don't lookup the agent by name. We already know, whether the agent
is still tracked or not. Look at agent->agent_lst.
nm_agent_manager_get_agent_by_user() would only return the first
matching secret agent for the user. This way, we might miss an agent
that has permissions.
Instead, add nm_agent_manager_has_agent_with_permission() and search
all agents.
There was literally only one place where we would make use of
O(1) lookup of secret-agents: during removal.
In all other cases (which are the common cases) we had to iterate the
known agents. CList is more efficient and more convenient to use when
the main mode of operation is iterating.
Also note that handling secret agents inevitably scales linear with
the number of agents. That is, because for every check we will have
to sort the list of agents and send requests to them. It would be
very complicated (and probably less efficient for reasonable numbers
of secret agents) to avoid O(n).
NMAgentManager and NMSecretAgent work closely together. In particular,
the NMAgentManager creates and tracks the NMSecretAgents and controls
it.
Move NMSecretAgent struct to the header, so that some fields may become
accessible to NMAgentManager. In particular, we will track secret agents
with a CList, and this CList element can be embedded in the
NMSecretAgent structure.
Move it to shared as it's useful for clients as well.
Move and rename nm_dbus_manager_new_auth_subject_from_context() and
nm_dbus_manager_new_auth_subject_from_message() in nm-dbus-manager.c
as they're needed there.
If we know the address used previously, also tell the client to start
from the init-reboot phase, so that it will start with a DHCP request
instead of a discover.
We call svFindFirstNumberedKey() to check whether we have any NETMASK
set. Since commit 9085c5c3a9 ('ifcfg-rh: rename
svFindFirstKeyWithPrefix() to svFindFirstNumberedKey() for finding
NETMASK') that function would no longer find the "NETMASK" without
number.
Fix that, by letting nms_ifcfg_rh_utils_is_numbered_tag() return TRUE
for the tag itself. This also makes more sense, because it matches our
common understanding what numbered tags are.
Adjust the other callers that don't want this behavior to explicitly
check.
Fixes: 9085c5c3a9 ('ifcfg-rh: rename svFindFirstKeyWithPrefix() to svFindFirstNumberedKey() for finding NETMASK')
Previously, setting or getting a variable required to scan all lines.
Note that frequently we would look up variables that didn't actually
exist, which we could only determine after searching the entire list.
Also, since we needed to handle having the same variable specified
multiple times (where the last occurrence wins), we always had to search
all keys and couldn't stop when finding the first key. Well, technically
we could have searched in reverse order for the getter, but that wasn't
done. For the setter we wanted to delete all but the last occurrences,
so to find them, we really had to search them all.
We want to support profiles with hundreds or thousands of addresses and routes.
This does not scale well.
Add an hash table to find the variables in constant time.
Test this commit and the parent commit:
$ git clean -fdx &&
CFLAGS=-O2 ./autogen.sh --with-more-asserts=0 &&
./tools/run-nm-test.sh -m src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh &&
perf stat -r 50 -B src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh 1>/dev/null
Before:
Performance counter stats for 'src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh' (50 runs):
330.94 msec task-clock:u # 0.961 CPUs utilized ( +- 0.33% )
0 context-switches:u # 0.000 K/sec
0 cpu-migrations:u # 0.000 K/sec
1,081 page-faults:u # 0.003 M/sec ( +- 0.07% )
1,035,923,116 cycles:u # 3.130 GHz ( +- 0.29% )
1,800,084,022 instructions:u # 1.74 insn per cycle ( +- 0.01% )
362,313,301 branches:u # 1094.784 M/sec ( +- 0.02% )
6,259,421 branch-misses:u # 1.73% of all branches ( +- 0.13% )
0.34454 +- 0.00116 seconds time elapsed ( +- 0.34% )
Now:
Performance counter stats for 'src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh' (50 runs):
329.78 msec task-clock:u # 0.962 CPUs utilized ( +- 0.39% )
0 context-switches:u # 0.000 K/sec
0 cpu-migrations:u # 0.000 K/sec
1,084 page-faults:u # 0.003 M/sec ( +- 0.05% )
1,036,130,698 cycles:u # 3.142 GHz ( +- 0.13% )
1,799,851,979 instructions:u # 1.74 insn per cycle ( +- 0.01% )
360,374,338 branches:u # 1092.756 M/sec ( +- 0.01% )
6,160,796 branch-misses:u # 1.71% of all branches ( +- 0.08% )
0.34287 +- 0.00133 seconds time elapsed ( +- 0.39% )
So, not much difference. But this is not surprising, because test-ifcfg-rh loads and
writes predominantly ifcfg files with few variables. The difference should be visible
when having large files.