Previously, we would only once read the initial hardware address during
device realization.
When a device activates, NetworkManager always sets the MAC address as configured
in the cloned-mac-address setting -- or, if unspecified -- it falls back
to use the permanent hardware-address instead.
Later, when deactivating the device, the MAC address is reset to the
"inital MAC address".
This patch changes, that the "initial MAC address" is re-read every time
before activating the device, contrary to reading it once in the
beginning.
This allows for a user to first start NetworkManager and later change the
MAC address of the device. When activating the device, NM will reset the
MAC address for the time the device is active. But when disconnecting,
it resets to the user-changed value, not the value when NM was started.
https://bugzilla.gnome.org/show_bug.cgi?id=708820
The current MAC address is part of NMPlatformLink in the platform cache.
When it changes, we must update the device's current value.
Also, the MAC address of NMDeviceEthernet is exposed on D-Bus. That
property should show the currently configured MAC address, not a state
that was read some time in the past.
Also, nm_device_hw_addr_set() compares the current MAC address before
resetting it. If that field is out-of-date, nm_device_hw_addr_set() will
behave wrongly.
NMDeviceEthernet had some special handling in link_changed() that would
re-read the MAC addresses and possibly bring up the interface. Move that
code to the parent device.
hw-addr is a constuct-only property. We should not do complex stuff in the property
setter before the object is sufficiently initialized. For example, the logging
macros access nm_device_get_iface(), which might be unset at that early
point.
Instead, initialize hw_addr and hw_addr_len later, at the end of the constructor()
function.
Also, ensure that @hw_addr_len is zero iff @hw_addr is unset.
Also, ensure that we always log a message when changing/setting the
hardware address -- except when clearing it during unrealize. It's
implicit that unrealize clears the hardware address.
Also, give all related logging messages a "hw-addr:" prefix.
Accessing the platform cache might anytime yield unexpected results.
E.g. the link could be gone, or the ifindex could even be replaced
by a different interface (yes, that can happen when moving links
between network namespaces).
It's not clear how to handle such a case at runtime. It seems wrong to
me to just error out. Still, such case might happen under normal
conditions, so it's wrong to just warn and proceed.
There was no leak here, because we would only call
nm_device_update_initial_hw_address() when @initial_hw_addr is unset.
However, still clear it to make it more robust against later changes.
The Network_ID for generating RFC 7217 stable privacy IPv6 addresses
is by default the UUID of the connection.
Alternatively, prefer "connection.stable-id" as Network_ID to generate
the stable addresses. This allows to configure a set of connections that
all use the same Network_ID for generating stable addresses.
Note that the stable-id and the UUID do no overlap, that is two
connections
[connection]
uuid=uuid1
stable-id=
and
[connection]
uuid=uuid2
stable-id=uuid1
generate distinct addresses.
For changing the hardware address, we must bring the device down. When doing
that, IP addressing is lost and it must be re-configured after bringing the
device up again.
We already do something similar in device_link_changed(), but that might
not be sufficient, because device_link_changed() is run on an idle
handler, thus, while changing the hardware address it has no chance to
run (or notice that the device was shortly down).
https://bugzilla.redhat.com/show_bug.cgi?id=1309899
Instead of accessing the singleton getter nm_settings_get(), obtain
the settings instance from the device instance itself via
nm_device_get_settings().
Currently NM proceeds with the activation of a device just after the
IPv6 configuration is applied. Server applications will bind to IPv6
addresses as soon as NM signals the presence of network connectivity,
but since the addresses are still tentative the bind will fail. There
are a couple of solutions to this.
Linux kernel supports "optimistic DAD", which is a modification of
Neighbor Discovery and SLAAC processes that allows addresses to be
used (under certain contraints) while kernel is performing DAD on
them. However it is not feasible to let NM enable optimistic DAD for
the devices it controls for the following reasons:
- it is not guaranteed to be always available since it can be turned
off at compile time
- RFC 4429 states that it should not be used for manually entered
addresses
- it works only with autoconf addresses generated by kernel
Therefore, use a different approach and handle this in NM by waiting
that the kernel completes DAD before continuing activation. We build a
list of addresses that are tentative just after the new configuration
is applied and then we asynchronously wait a platform address-change
event where all NM-configured addresses become non-tentative.
A similar solution has been adopted also by other network managing
tools:
https://anonscm.debian.org/cgit/collab-maint/ifupdown.git/commit/?id=ec357a5d6cb5fa8b0004c727d7cc48253c59eb0f8012cd3919https://bugzilla.redhat.com/show_bug.cgi?id=1243958
Fall back to system default value for ipvx.dns-priority when it's zero
in the setting. For VPNs the default value is 50; for other
connections is 100, but it depends also on the content of
[connection*] sections in NetworkManager.conf.
This is especially important, because changing MTU takes the
link down for a moment. Taking a link down deletes IP routes and
IPv6 addresses. Thus, when the link comes up again, we must restore
them.
Otherwise, we don't call merge_and_apply() until the next DHCP lease
(or possibly never in case of static addressing).
https://bugzilla.redhat.com/show_bug.cgi?id=1309899
nm_device_set_ip4_config() is called during cleanup and
from ip4_config_merge_and_apply(). The latter, has several
call sites.
It's not easy to track whether we called set_ip4_config with
or without commit (and if we call it without commit, we might
not see a logging line at all).
(same for nm_device_set_ip6_config()/ip6_config_merge_and_apply()).
We would subscribe to config-changed signal during object-realize,
however only unsubscribe during dispose().
Avoid multiple subscributions, and unsubscribe also when unrealizing
the device.
Also, always subscribe to the signal, even without capability
NM_DEVICE_CAP_CARRIER_DETECT. In the next commit, we will re-read
capabilities later on, so just always subscribe.
Contrary to gboolean, bool is only one byte in size.
Due to alignment and ordering of the fields, this saves
merely 16 bytes per NMDevicePrivate struct (on x86_64),
still.
Also, bool is coerced by the compiler to be strictly FALSE or
TRUE -- contrary to gboolean, which can be any integer.
Thus, for bool type, "g_assert (NM_IN_SET (value, FALSE, TRUE));"
never fails. That is desirable as well.
While not a large win, it seems favorable to use bool type for
fields of a struct.
When the IP status is IP_DONE and a DHCP transaction succeeds the
'dhcp4' and 'dhcp6' pending actions must be removed. Without this, a
temporary link loss just after the activation would cause a DHCP
restart and those actions would remain set, blocking the startup.
https://bugzilla.redhat.com/show_bug.cgi?id=1330893
Once we start with dispose, we certainly don't want to process any platform
events for the device anymore.
Previously, we disconnect those handlers only later during dispose, so it's
not clear that we would not receive a device_ipx_changed signal after _cleanup_generic_pre().
Fix this possible (or actual) bug.
Since commit a47c13a7a2, update_ip4_config() re-schedules
itself in case activate_stage5_ip4_config_commit is pending. Thus, there is no need to
cancel any queued queued_ip4_config_id.
Also as that does not properly fix the issue unlike a47c13a7a.
update_ip4_config() and update_ip6_config() are called from nm_device_capture_initial_config().
At that point, we don't expect any activation-source scheduled, thus the "if" should not
not be hit anyway.
So, this patch should actually make no difference, but it seems clearer
to me. Also, because it would be a bug to re-schedule the idle handler
that is already pending, but from inspecting nm_device_capture_initial_config()
it is not immediately clear that this cannot be the case.