Arguably, we currently only have one instance of NMPlatform,
NMRouteManager, NMDefaultRouteManager -- the one owned by the
NMNetns singleton.
Hence, all these instances we create with "log-with-ptr" set explicitly
to false.
In the future we want to support namespaces, and it will be be common to
have multiple instances. For that we have "log-with-ptr" so we are able
to disambiguiate the logging.
Change the default to TRUE because it makes more sense. It has currently
no effect as the default is never used.
(cherry picked from commit 41148caba8)
NMPlatform, NMRouteManager and NMDefaultRouteManager are singletons
instances. Users of those are for example NMDevice, which registers
to GObject signals of both NMPlatform and NMRouteManager.
Hence, as NMDevice:dispose() disconnects the signal handlers, it must
ensure that those singleton instances live longer then the NMDevice
instance. That is usually accomplished by having users of singleton
instances own a reference to those instances.
For NMDevice that effectively means that it shall own a reference to
several singletons.
NMPlatform, NMRouteManager, and NMDefaultRouteManager are all
per-namespace. In general it doesn't make sense to have more then
one instances of these per name space. Nnote that currently we don't
support multiple namespaces yet. If we will ever support multiple
namespaces, then a NMDevice would have a reference to all of these
manager instances. Hence, introduce a new class NMNetns which bundles
them together.
(cherry picked from commit 0af2f5c28b)
We should try to guarantee a stable activation order of connections
across reboots; this is required, for example, for bonds because they
get assigned the MAC address of the first device enslaved, and thus
changing the activation order of slaves means also changing the MAC
address of the bond. Since we activate connections in the order links
are discovered, having a stable sorting of links returned by platform
is enough.
The ifindex of interfaces can change between reboots as it depends on
the order in which kernel discover interfaces. Provided that the
system uses a mechanism to enforce persistent interface naming (as
udev rules or systemd-udevd predictable names), and that NM starts
after all interfaces have been announced by udev, using the interface
name instead of ifindex will guarantee a consistent order.
ip4_addr_subnets_is_secondary() should fill the list of addresses in
the same subnet also when returning FALSE, because
nm_platform_ip4_address_sync() uses it.
Fixes: 2f68a50041
The kernel already takes care of adding and updating temporary
addresses when an address with IFA_F_MANAGETEMPADDR flag is added or
updated; doing it also in nm_platform_ip6_address_sync() can overwrite
the changes done by kernel, especially because since commit
0a0bca9c7f ("ip6-config: sort addresses only when reading the
property value") there is no guarantee that temporary addresses are
before the public ones in the IPv6 configuration.
Still delete temporary addresses, but don't add or update them.
The ioctl APIs ethtool/mii require an interface ifname. That is inherrently
racy as interfaces can be renamed. This cannot be fixed, we can only
minimize the time between verifying the ifname and calling ioctl.
We already had problems with that when ethtool would access an interface
by name that didn't exists. See commit ab41c13b06 .
Checking for an existing interface only helps avoiding races when an interface
gets deleted. It does not help against renaming.
Go one step further, and instead of checking whether such an ifname
exists, try to get the ifname based on the ifindex immediately before
we need it.
This brings an additional overhead for each ethtool access.
nm_platform_ip4_address_sync() tries to apply the new configuration
with the minimum effort and doesn't delete addresses if they are
already present on the interface. This can break the ordering, as an
existing address would be promoted by kernel to primary, even if it
was last in our configuration.
Add some logic to ensure the correct order of addresses is always
enforced. This fixes situations like:
# nmcli connection add type ethernet ifname eth0 con-name t \
ipv4.method manual \
ipv4.addresses "1.1.1.1/24,1.1.1.2/24,1.1.1.5/24"
# nmcli connection up t
=> addresses are applied in the right order:
inet 1.1.1.1/24 brd 1.1.1.255 scope global eth0
inet 1.1.1.2/24 brd 1.1.1.255 scope global secondary eth0
inet 1.1.1.5/24 brd 1.1.1.255 scope global secondary eth0
# nmcli connection mod t ipv4.addresses "1.1.1.5/24,1.1.1.2/24,1.1.1.1/24"
# nmcli device reapply eth0
=> order is wrong:
inet 1.1.1.2/24 brd 1.1.1.255 scope global eth0
inet 1.1.1.5/24 brd 1.1.1.255 scope global secondary eth0
inet 1.1.1.1/24 brd 1.1.1.255 scope global secondary eth0
Co-Authored-By: Thomas Haller <thaller@redhat.com>
Added platform functions to retrieve device link mode status and to
switch from auto to manual link negotiation:
nm_platform_ethtool_get_link_settings
nm_platform_ethtool_set_link_settings
We only needed proper glib enum types for having properties
and signal arguments. These got all converted to plain int,
so no longer generate such an enum type.
Had to rename "nm-enum-types.h" because it works badly with
"libnm/nm-enum-types.h". Maybe I could fix that differently,
but duplicate names is anyway error prone.
Note that "nm-core-enum-types.h" is already taken too, so
"nm-src-enum-types.h" it is.
nm_platform_link_cmp() shall first compare the ifindex, otherwise
the sort-order first considers rather unimportant fields instead
of the primary key: the ifindex.
Fixes: a3185f22e55484b819859cb4cef8f54385dac1a9
Trying to set a property on a device that does not exist is not something
necessarily wrong. Don't print error/warning messages.
<trace> [1467707267.2887] device[0x55a74adbdaf0] (enp0s25): set-hw-addr: setting MAC address to 'AA:BB:CC:DD:EE:FF' (reset, unmanage)...
<debug> [1467707267.2887] platform: link: setting '(null)' (2) hardware address
<debug> [1467707267.2887] platform-linux: link: change 2: address: 68:F7:28:61:68:F7 (6 bytes)
<debug> [1467707267.2887] platform-linux: do-request-link: 2
<debug> [1467707267.2888] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 226
<debug> [1467707267.2888] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 227
<error> [1467707267.2888] platform-linux: do-change-link[2]: failure changing link: failure 19 (No such device)
<warn> [1467707267.2888] device (enp0s25): set-hw-addr: failed to reset MAC address to 68:F7:28:61:68:F7 (unmanage)
We don't need the token set in platform for our address mode generation,
but having it set makes it possible to correctly generate and assume
connections that use tokens.
The only user of platform who accesses this field is NMDevice,
when calling nm_platform_link_get_ipv6_token(). It cares more
about whether the token is all-zero or set to something.
Another use of inet6_token.is_valid was so that when we receive a
netlink message without IFLA_INET6_TOKEN attribute, that we don't
treat the value as zero, although it is just unknown. Fix that
instead in a better way by setting the value from the cache, if
IFLA_AF_SPEC doesn't provide it.
Also, when printing the token in nm_platform_link_to_string()
treat it as an IPv6 address (inet_ntop).
..., nm_platform_ip6_route_cmp(), nm_platform_ip4_address_cmp() and
nm_platform_ip6_address_cmp().
Compare those fields first, for which we expect that their properties
differ. E.g. usually, each route destination in a set is unique, thus by
comparing those fields first we shortcut some comparisons.
We handle cloned routes (that have rtm_flags RTM_F_CLONED) differently.
We used to mark such routes by hacking NMIPConfigSource to have a special
value. No longer do this, because it mixes different concepts.
Note that the rt_cloned filed fits into a hole in the aligment
of NMPlatformIPRoute. Thus there is almost no overhead to this
change.
The "source" field of NMPlatformIPRoute (now "rt_source") maps to the
protocol field of the route. The source of NMPlatformIPAddress (now
"addr_source") has no direct equivalent in the kernel.
As their use is different, they should have different names. Also,
the name "source" is used all over the place. Hence give the fields
a more distinct name.
This way, we get a defined order at startup.
Also, get rid of the logging statements. It was used for
debugging, but a "getter" really should not log the stuff it
is returning.