nm_netns_ip_route_ecmp_commit() returns the ECMP routes that didn't find
a merge-partner. It expects NML3Cfg to configure such routes in
platform.
Note that these routes have a positive "weight", which was used for
tracking the ECMP information in NML3Cfg and NMNetns.
But in kernel, single-hop routes don't have a weight. All routes in
NMPlatform will have a zero weight. While it somewhat works to call
nm_platform_ip_route_add() with a single-hop route of non-zero weight,
the result will be a different(!) route. This means for example that
nm_platform_ip_route_sync() will search the NMPlatform cache for whether
the routes exist, but in the cache single-hop routes with positive weight
never exist. Previously this happened and nm_platform_ip_route_sync()
would not delete those routes when it should.
The solution is that nm_netns_ip_route_ecmp_commit() does not tell
NML3Cfg to add a route, that cannot be added. Instead, it must first
normalize the weight to zero, to have a "regular" single-hop route.
Fixes: 5b5ce42682 ('nm-netns: track ECMP routes')
It wouldn't work otherwise. The object state is used to track routes
and compare them to what we find in platform.
A "metric_any" is useful at higher layers, to track a route where the
metric is decided by somebody else. But at the point when we add such an
object to the object-state, a fixed metric must be chosen.
Assert for that.
The hash/cmp functions were wrong with respect to IPv4 routes. Fix that.
- the weight was cast to a guint8, which is too small to hold all
values.
- NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID comparison would normalize a zero
weight to one
NM_CMP_DIRECT(NM_MAX(a->weight, 1u), NM_MAX(b->weight, 1u));
That was very wrong.
Clean this up. How the weight is handled, depends on the n_nexthops
parameter.
The remarkable thing is that upper layers find it useful to track IPv4
single-hop routes with a non-zero weight. Consequently, this is honored
by NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID which treats single-hop routes
different, if their weight differs. However, adding such a route in
kernel will not work. In kernel, single-hop routes have no weight. While
the route exists as distinct according to the implemented identity, it never
exists in kernel. Well, you can call nm_platform_ip_route_add() with such
a route, but the result will have a weight of zero (being a different
route). See also nm_platform_ip_route_normalize().
This works all mostly fine. The only thing to take care is that you
cannot look into the NMPlatform cache and ever find a IPv4 single-hop
route with a non-zero weight. If you preform such a lookup, realize that
such routes don't exist in platform. You can however normalize the
weight to zero first (nm_platform_ip_route_normalize()) and look for a
similar route with a zero weight.
Fixes: 1bbdecf5e1 ('platform: manage ECMP routes')
_nm_utils_dns_option_validate() allows specifying the address family,
and filters based on that. Note that all options are valid for IPv6,
but some are not valid for IPv4.
It's not obvious, that such filtering is only performed if
"option_descs" argument is provied. Otherwise, the "ipv6" argument is
ignored.
Regardless, it's also confusing to have a boolean "ipv6". When most
callers don't want a filtering based on the address family. They
actually don't want any filtering at all, as they don't pass an
"option_descs". At the same time passing a TRUE/FALSE "ipv6" is
redundant and ignored. It should be possible, to explicitly not select
an address family (as it's ignored anyway).
Instead, make the "gboolean ipv6" argument an "int addr_family".
Selecting AF_UNSPEC means clearly to accept any address family.
When connection down is explicitly called on the controller, the port
connection should also be deactivated with the reason user-requested,
otherwise any following connection update on the controller profile
will unblock the port connection and unnessarily make the port to
autoconnet again.
Fixes: 645a1bb0ef ('core: unblock autoconnect when master profile changes')
https://gitlab.freedesktop.org/NetworkManager/NetworkManager-ci/-/merge_requests/1568
Add a new "stable-ssid" mode that generates the MAC address based on the
Wi-Fi's SSID.
Note that this gives the same MAC address as setting
connection.stable-id="${NETWORK_SSID}"
wifi.cloned-mac-address="stable"
The difference is that changing the stable ID of a profile also affects
"ipv6.addr-gen-mode=stable-privacy" and other settings.
For Wi-Fi profiles, this will encode the SSID in the stable-id.
For other profiles, this encodes the connection UUID (but the SSID and
the UUID will always result in distinct stable IDs).
Also escape the SSID, so that the generated stable-id is always valid
UTF-8.
Comparing integers of different signedness gives often unexpected
results. Adjust usages of MIN()/MAX() to ensure that the arguments agree
in signedness.
nm_hash_siphash42() uses a randomized seed like nm_hash*(). In this case,
we want to always generate the same fake timestamp, based on the host-id.
In practice, it doesn't really matter, because this is only the fallback
path for something gone horribly wrong already.
Most profiles don't have "connection.permissions" set. Avoid resolving the
UID to the name via getpwuid() (in nm_auth_is_subject_in_acl()), until we
know that we require it.
I think GSource* is preferable, because it's more type-safe than the
guint numbers. Also, g_source_remove() only works with
g_main_context_default(), while g_source_detach() of a GSource pointer
works with any GMainContext (so it's more general, even if we in this
case only have sources attached to g_main_context_default()).
Handling GSource* pointers is possibly also faster, since it saves one
extra g_main_context_find_source_by_id() -- on the other hand, tracking
the pointer costs 8 bytes while tracking the guint only costs 4 bytes.
Whether it's faster is unproven, but possibly it is. In any case it's
not an argument against using pointers.
Anyway. Update another usage of source-ids to use GSource pointers.
This is also the pattern that "checkpatch.pl" suggests.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1774
Some Applications require to explicitly enable or disable EEE.
Therefore introduce EEE (Energy Efficient Ethernet) support with:
* ethtool.eee on/off
Unit test case included.
Signed-off-by: Johannes Zink <j.zink@pengutronix.de>
When creating default connections automatically, we check if udev has
set the NM_AUTO_DEFAULT_LINK_LOCAL_ONLY variable, and if so, we create
the connection with method=link-local. It was checked only for ethernet
connection type, which works fine because it's the only device type that
we create connections automatically for.
However, link-local connections are not specific to Ethernet, and if we
add auto-default connections for more devices in the future we should
honor this configuration too. Do it from nm-device, but only if the
device class has defined a "new_default_connection" method so the
behaviour is identical as the current one, but will be used by future
implementors of this method too.
See-also: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1780https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1779
We honored "NM_AUTO_DEFAULT_LINK_LOCAL_ONLY" udev property, for when we
generate a "Wired connection 1" (aka the "auto-default connection").
Systemd now also honors and may set ID_NET_AUTO_LINK_LOCAL_ONLY for
a similar purpose. Honore that too.
The NM specific variable still is preferred, also because "NM_AUTO_DEFAULT_LINK_LOCAL_ONLY"
is about something very NetworkManager specific (controlling "Wired connection 1").
Maybe one day, we should drop "data/90-nm-thunderbolt.rules" and only
rely on what systemd provides. But not yet.
See-also: https://github.com/systemd/systemd/pull/29767https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1413
If a ovs interface has the cloned-mac-address property set, we pass
the desired MAC to ovsdb when creating the db entry, and openvswitch
will eventually assign it to the interface.
Note that usually the link will not have the desired MAC when it's
created. Therefore, currently we also change the MAC via netlink
before proceeding with IP configuration. This is important to make
sure that ARP announcements, DHCP client-id, etc. will use the correct
MAC address.
This doesn't work when using the "netdev" (userspace) datapath, as the
attempts to change the MAC of the tun interface via netlink fail,
leading to an activation failure.
To properly handle both cases in the same way, adopt a different
strategy: now we don't set the MAC address explicitly via netlink but
we only wait until ovs does that.
The code to determine if we are using the netdev datapath is logically
separated from the code to start IP configuration; move it to its own
function to make the code easier to follow.
The deactivation can happen while we are waiting for the ifindex, and
it can happen via two code paths, depending on the state. For a
regular deactivation, method deactivate_async() is called. Otherwise,
if the device goes directly to UNMANAGED or UNAVAILABLE, deactivate()
is called. We need to make sure that signal and source handlers are
disconnected, so that they are not called at the wrong time.
Fixes: 99a6c6eda6 ('ovs, dpdk: fix creating ovs-interface when the ovs-bridge is netdev')
If the device is being disconnected for a user request, at the moment
the active connection goes to state DEACTIVATED through the following
transitions, independently of the reason for the disconnection:
- state: DEACTIVATING, reason: UNKNOWN
- state: DEACTIVATED, reason: DEVICE_DISCONNECTED
For VPNs, a disconnection is always user-initiated, and the active
connection states emitted are:
- state: DEACTIVATING, reason: USER_DISCONNECTED
- state: DEACTIVATED, reason: USER_DISCONNECTED
This difference poses problems for clients that want to handle device
and VPNs in the same way, especially because WireGuard is implemented
as a device, but is logically a VPN.
Let NMActRequest translate the USER_REQUESTED device state reason to
USER_DISCONNECTED active connection state reason, in case of
disconnection.
This is an API change, but the previous behavior of reporting generic
uninformative reasons seems a bug. See for example
nmc_activation_get_effective_state(), which inspects the AC state
reason and in case it's generic (DEVICE_DISCONNECTED), it considers
the device state instead.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1405
NMActiveConnection implements method device_state_changed() that
re-emits device state changes as convenience for subclasses. Add the
reason for the state change to the handler, as it will be used in the
next commit.
This reverts commit 05c31da4d9.
In the linked commit the callback was made repeating on the assumption
that forward progress would result in the callback getting canceled in
cb_data_complete. However, this assumption does not hold since a timeout
callback does not guarantee completion (or error out) of a request.
curl tweaked some internals in v8.4.0 and started giving 0 timeouts, and
a repeating callback is firing back-to-back without making any progress
in doing so.
Revert the change and make the callback non-repeating again.
Fixes: 05c31da4d9 ('connectivity: don't cancel curl timerfunction from timeout')
nm_strv_find_first() is useful (and used) to find the first index (if
any). I can thus also used to check for membership.
However, we also have nm_strv_contains(), which seems better for
readability, when we check for membership. Use it.
When IPv6 is disabled in kernel but ipv6.method is set to auto, NetworkManager repeatedly attempts
IPv6 configuration internally, resulting in unnecessary warning messages being output infinitely.
platform-linux: do-add-ip6-address[2: fe80::5054:ff:fe7c:4293]: failure 95 (Operation not supported)
ipv6ll[e898db403d9b5099,ifindex=2]: changed: no IPv6 link local address to retry after Duplicate Address Detection failures (back off)
platform-linux: do-add-ip6-address[2: fe80::5054:ff:fe7c:4293]: failure 95 (Operation not supported)
ipv6ll[e898db403d9b5099,ifindex=2]: changed: no IPv6 link local address to retry after Duplicate Address Detection failures (back off)
platform-linux: do-add-ip6-address[2: fe80::5054:ff:fe7c:4293]: failure 95 (Operation not supported)
ipv6ll[e898db403d9b5099,ifindex=2]: changed: no IPv6 link local address to retry after Duplicate Address Detection failures (back off)
To prevent this issue, let's disable IPv6 in NetworkManager when it is disabled in the kernel.
In order to do it in activate_stage3_ip_config() only once during activation,
the firewall initialization needed to be moved earlier. Otherwise, the IPv6 disablement could occur
twice during activation because activate_stage3_ip_config() is also executed from subsequent of fw_change_zone().
ethtool "channels" parameters can be used to configure multiple queues
for a NIC, which helps to improve performances. Until now, users had
to use dispatcher scripts to change those parameters. Introduce native
support in NetworkManager by adding the following properties:
- ethtool.channels-rx
- ethtool.channels-tx
- ethtool.channels-other
- ethtool.channels-combined
`_ethtool_*_reset()` functions already check that the state is not
NULL, no need to check it before. The only exception was for "feature"
settings, where the check was missing.
If the client-id has been set to "none", the DHCP client-id option
(option 61) mustn't be sent. Honor this when the dhclient plugin is
used.
If dhclient has been called with the -i option (Use a DUID with DHCPv4
clients), it will send a Client-ID even without setting one in dhclient.conf.
In this case, this option needs to be explicitly overwritten with:
send dhcp-client-identifier = "";
At least in RHEL 8, dhclient is launched with `-i` turned on by default.
The function merge_dhclient_config was called only once from
create_dhclient_config. The content of both of them is short and simple,
so moving the content from merge_dhclient_config to the caller
improves the readability and makes the functions call chain easier to
follow. Also, both functions takes a long list of arguments which are
almost the same, so we can avoid having to pass them over and over in a
long call chain.
Sending a client-id is not mandatory according to RFC2131. It is
mandatory according to RFC4361 that superseedes it.
Some weird DHCP servers conforming RFC2131 can get confused and break
existing DHCP leases if they start receiving a client-id when it was not
being previously received. Users that were using other DHCP client like
dhclient, but want to use NetworkManager's internal DHCP client, can
suffer this problem.
Add "none" as accepted value in ipv4.dhcp-client-id to specify that
client-id must not be sent. Note that this is generally not recommended
unless it's explicitly needed for some reason like the explained above.
Client-id is mandatory in DHCPv6.
This commit allow to set the "none" value and properly parse it in the
NMDhcpClientConfig struct. Next commits will modify the different DHCP
plugins to honor it.
If a commit is invoked without any change to the l3cd or to the ACD
data, in _l3cfg_update_combined_config() we skip calling
_l3_acd_data_add_all(), which should clear the dirty flag from ACDs.
Therefore, in case of such no-op commits the ACDs still marked as
dirty - but valid - are removed via:
_l3_commit()
_l3_acd_data_process_changes()
_l3_acd_data_prune()
_l3_acd_data_prune_one()
Invoking a l3cfg commit without any actual changes is allowed, see the
explanation in commit e773559d9d ('device: schedule an idle commit
when setting device's sys-iface-state').
The bug is visible by running test 'bond_addreses_restart_persistence'
with IPv4 ACD/DAD is enabled by default: after restart IPv6 completes
immediately, the devices becomes ACTIVATED, the sys-iface-state
transitions from ASSUME to MANAGED, a commit is done, and it
incorrectly prunes the ACD data. The result is that the IPv4 address
is never added again.
Fix this by doing the pruning only when we update the dirty flags.
This is a respin of commit ed565f9146 ('l3cfg: fix pruning of ACD
data') that was reverted because it was causing a crash. The crash was
caused by unconditionally clearing `acd_data_pruning_needed` in
_l3cfg_update_combined_config(), while we need to do it only when
actually committing the configuration.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1749
sysfs is deprecated and kernel will not add new bridge port options to
sysfs. Netlink is a stable API and therefore is the right method to
communicate with kernel in order to set the link options.