If an L3Cfg try to register an ECMP route that we are tracking we must
mark it as needs_update because it means it could be dropped from
kernel. When merging them if the merged route didn't change we should
commit the route anyway because we know it needed update.
When adding a static route, kernel enforce that the gateway is
reachable. To solve this, NetworkManager generates onlink routes for
each static route. As ECMP routes does not follow the same logic than
singlehop routes, we need to add the onlink route for each hop of ECMP
routes once merged.
NML3Cfg will take ownership of the onlink route added and will purge it
when it is not needed anymore.
NML3Cfg and NMNetns are already strongly related and cooperate.
An NML3Cfg instance is created via NMNetns, which is necessary
because NMNetns ensures that there is only one NML3Cfg instance per
ifindex and it won't ever make sense to have multiple NML3Cfg instances
per namespace.
Note that NMNetns tracks additional information for each NML3Cfg.
Previously, in a pointless attempt to separate code, it did so
by putting that information in another struct (L3CfgData).
But as the classes are strongly related, there really is no
reason why we cannot just attach this information to NML3Cfg
directly. Sure, we want that code has low coupling, high cohesion
but that doesn't mean we gain anything by putting data that is
strongly related to the NML3Cfg to another struct L3CfgData.
The advantage is we save some redundant data and an additional
L3CfgData. But the bigger reason is that with this change, it
will be possible to access the NMNetns specific data directly from
an NML3Cfg instance, without another dictionary lookup. Currently
such a lookup is never used, but it will be.
Basically, NML3Cfg and NMNetns shares some state. It is now in the
"internal_netns" field of the NML3Cfg instead of L3CfgData.
src/core/devices/nm-lldp-listener.c:911: check_after_deref:
Null-checking "self" suggests that it may be null, but it has already been dereferenced on all paths leading to the check.
Fixes: 04e72b6b4d ('lldp: use new libnm-lldp instead of systemd's sd_lldp_rx')
Older versions of iproute2 don't support the fwmark option. Remove it.
Fixes: 1cf8df2f35 ('platform: support VTI tunnels')
Fixes: b669a3ae46 ('platform: support VTI6 tunnels')
With multi-connect enabled, this can cause infinite retries to autoconnect,
see [1].
That has bad consequences for example in initrd, where
nm-wait-online-initrd.service would wait up to one hour before failing
and blocking boot.
This reverts commit 1656d82045.
[1] https://bugzilla.redhat.com/show_bug.cgi?id=2039734#c5
Fixes: 1656d82045 ('policy: track the autoconnect retries in devices for multi-connect')
Previously, we only set the "default-duid" line in the lease file. That
means, if the lease already contained a matching entry with a
"dhcp6.client-id" option, it was not honored. That is wrong.
If the profile has "ipv6.dhcp-duid" set, then we must use it and get
rid of those options from the lease.
It's easy to reproduce:
PROFILE=eth1
nmcli connection down "$PROFILE"
rm -f /var/lib/NetworkManager/*lease
nmcli connection modify "$PROFILE" ipv6.dhcp-duid "aa:bb:cc:dd:00:00:11"
nmcli connection up "$PROFILE"
# Verify the expected duid in /var/lib/NetworkManager/*lease and "/run/NetworkManager/devices/$IFINDEX"
nmcli connection modify "$PROFILE" ipv6.dhcp-duid "aa:bb:cc:dd:00:00:22"
nmcli connection up "$PROFILE"
# Check the DUID again.
Splitting by any of "\r\n" and then joining the lines with "\n"
leads to double-newlines. That's certainly wrong.
Maybe we shouldn't care about "\r", I don't know why this was done. But
handle it differently.
Of course, the old "priv->effective_client_id" and the new
"client_id" instances are truly separate, that is, they don't
share data, and destroying "priv->effective_client_id" before
taking a reference on "client_id" causes no problem.
It's still a code smell. It makes the function unnecessarily unsafe
under (very unusual) circumstances.
The point of using this trivial helper function is to have one function
that is related to the construction of the options dictionary, that we
can search for.
It answers the question, where do we create a option hash (at `git grep
nm_dhcp_option_create_options_dict`).
The "lease" mode is unusual, because it means to prefer the DUID
configuration from the DHCP plugin over the explicit configuration in
NetworkManager. It is only for the DHCPv6 DUID and not for the IPv4
client-id. It also is only special for the "dhclient" plugin, because
with the internal plugin, this always corresponds to a generated, stable
DUID.
Commit 58287cbcc0 ('core: rework IP configuration in NetworkManager
using layer 3 configuration') broke this. The commit refactored the code
to track the effective-client-id separately. Previously, the client-id which
was read from the dhclient lease, was overwriting NMDhcpClient.client_id. But
with the refactor, it broke because nm_dhcp_client_get_effective_client_id()
was never called.
Fix that.
Fixes: 58287cbcc0 ('core: rework IP configuration in NetworkManager using layer 3 configuration')
Note that there are no callers of nm_dhcp_client_get_effective_client_id(),
hence calling the setter had no effect. This is a bug, that we will fix
later.
But before fixing the bug, change how this works. Drop the get_duid() hook.
It's only confusing and backward.
We will keep the nm_dhcp_client_[gs]et_effective_client_id() functions.
They will be used later.
The "effective-client-id" is handled wrongly. Step 1 to clean this up.
Note that NMDhcpClientPrivate.effective_client_id is only ever get/set
via the nm_dhcp_client_[gs]et_effective_client_id() functions.
Note that only a NMDhcpDhclient instance ever calls
nm_dhcp_client_set_effective_client_id().
Hence, for NMDhcpSystemd the effective-client-id is really just the DUID
from the config. Clean this up by not calling nm_dhcp_client_get_effective_client_id()
but use the config directly. There is no change in behavior here.
The current implementation only checks that a device with name equal
to veth.peer exists and it has a parent device; it doesn't check that
its parent is actually the device we want to create. So for example,
if the profile specifies interface-name A and peer B, while in
platform we have a veth pair {B,C}, we'll skip the interface creation
and the device will remain without a ifindex, leading to a crash
later. Fix this by adding the missing check.
While at it, don't implement the check by inspecting NMDevices but
look directly at the platform cache; that seems more robust because
devices are often updated from platform events via idle handlers and
so the information there could be outdated.
Fixes: 07e0ab48d1 ('veth: drop iface peer check during create_and_realize()')
https://bugzilla.redhat.com/show_bug.cgi?id=2129829
G_TYPE_CHECK_INSTANCE_CAST() can trigger a "-Wcast-align":
src/core/devices/nm-device-macvlan.c: In function 'parent_changed_notify':
/usr/include/glib-2.0/gobject/gtype.h:2421:42: error: cast increases required alignment of target type [-Werror=cast-align]
2421 | # define _G_TYPE_CIC(ip, gt, ct) ((ct*) ip)
| ^
/usr/include/glib-2.0/gobject/gtype.h:501:66: note: in expansion of macro '_G_TYPE_CIC'
501 | #define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_G_TYPE_CIC ((instance), (g_type), c_type))
| ^~~~~~~~~~~
src/core/devices/nm-device-macvlan.h:13:6: note: in expansion of macro 'G_TYPE_CHECK_INSTANCE_CAST'
13 | (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_MACVLAN, NMDeviceMacvlan))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
Avoid that by using _NM_G_TYPE_CHECK_INSTANCE_CAST().
This can only be done for our internal usages. The public headers
of libnm are not changed.
For MACsec interfaces, kernel announces the parent ifindex in the
generic IFLA_LINK netlink attribute, which we save in
NMPlatformLink.parent. There is no need to have a dedicate member in
NMPlatformLnkMacsec.
The dedicate member was never set and during a restart of
NetworkManager the parent of the MACsec device could be unset leading
to a failed assertion:
act_stage2_config: assertion 'parent' failed
Fixes: 85103656e9 ('platform: add support for macsec links')
https://bugzilla.redhat.com/show_bug.cgi?id=2122564https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1481
When ovs plugin not installed, we got this error on dbus
org.freedesktop.NetworkManager.Failed
It should be `org.freedesktop.NetworkManager.MissingPlugin`.
Signed-off-by: Gris Ge <fge@redhat.com>
Reapply() is supposed to make sure that the system (the interface)
is configured as indicated by the applied-connection. That means,
it will remove/add configuration to make the system match the requested
configuration.
Add a flag "preserve-external-ip" which relaxes this. During reapply,
IP addresses/routes that exist on the interface and which are not known
(or added) by NetworkManager will be left alone.
This will be used by nm-cloud-setup, so that it can reconfigure the
interface in a less destructive way, which does not conflict with
external `ip addr/route` calls.
Note that the previous commit just adds "VersionInfo" and the
possibility to expose capabilities (patch-level). This is not used
for the new reapply flag, because, while we might backport the
reapply flag, we won't backport the "VersionInfo" property. Exposing
new capabilities via the "VersionInfo" property will only become useful
in the future, where we can backport a capability to older NM versions
(but those that have "VersionInfo" too).
Changing an error code is an API change. But, so far no flags existed,
so it's unlikely that somebody would send invalid flags or care about
the return code.
This exposes NM_VERSION as number (contrary to the "Version", which is a
string). That is in particular useful, because the number can be
compared with <> due to the encoding of the version.
While at it, don't make it a single number. Expose an array of numbers,
where the following numbers are a bitfield of capabilities.
Note that before commit 3c67a1ec5e ('cli: remove version check against
NM'), we used to parse the "Version" string to detect the version. As
such, the information that "VersionInfo" exposes now, was already
(somewhat) available, you just had to parse the string. The main benefit of
"VersionInfo" is that it can expose capabilities (patched behavior) in
in a lightweight bitfield. To include the numerical version there is
just useful on top.
Currently no additional capabilities are exposed. The idea is of course
to have a place in the future, where we can expose additional
capabilities. Adding a capability flag is most useful for behavior that we
backport to older branches. Otherwise, we could just check the daemon version
alone. But since we only add "VersionInfo" property only now, we cannot backport
any capability further than this, because the "VersionInfo" property itself
won't be backported. As such, this will only be useful in the future by having
a place where we can add (and backport) capabilities.
Note that there is some overlap with the existing "Capability" property
and NMCapability enum. The difference is that adding a capability via "VersionInfo"
is only one bit, and thus cheaper. Most importantly, having it cheaper means
the downsides of adding a capability flag is significantly removed. In
practice, we could live without capabilities for a long time, so they
must be very cheap for them to be worth to add. Another difference might be,
that we will want that the VersionInfo is about compile time defaults (e.g.
a certain patch/behavior that is in or not), while NM_CAPABILITY_TEAM depends on
whether the team plugin is loaded at runtime.
The warning "-Wcast-align=strict" seems useful and will be enabled
next. Fix places that currently cause the warning by using the
new macro NM_CAST_ALIGN(). This macro also nm_assert()s that the alignment
is correct.
GArray.data is a char pointer. Most of the time we track other data in
a GArray. Casting that pointer can trigger "-Wcast-align=strict"
warnings.
Avoid them. Most of the time, instead use the nm_g_array*() helpers,
which also assert that the expected element size is correct.
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.