NMIP4Config, NMIP6Config, and NMPlatform shall share one
NMDedupMultiIndex instance.
For that, pass an NMDedupMultiIndex instance to NMPlatform and NMNetns.
NMNetns than passes it on to NMDevice, NMDhcpClient, NMIP4Config and NMIP6Config.
So currently NMNetns is the access point to the shared NMDedupMultiIndex
instance, and it gets it from it's NMPlatform instance.
The NMDedupMultiIndex instance is really a singleton, we don't want
multiple instances of it. However, for testing, instead of adding a
singleton instance, pass the instance explicitly around.
Currently, device types like Bond hack around ignore-carrier
setting, as they always want to ignore-carrier.
Prepare so that also for such master types, we rely and honor the
ignore-carrier setting better. In the next commit, bond, bridge and
team devices they will get ignore-carrier turned on by default.
For externally managed interfaces, we create an in-memory connection
and keep the device with sys-iface-state=external.
When the user actively modifies the connection, we persist it to
storage. But we also must take over managing the device.
One problem is that nm_device_reapply() errors out if the device
is still activating. It's unclear how to reapply the connection
while the device is in the process of activation. So, if the user
modifies the created connection very quickly, reapplying the settings
will fail.
https://bugzilla.redhat.com/show_bug.cgi?id=1462223
Don't log in a function that basically just inspects state, without
mutating it. Instead, pass the reason why a connection could not be
generated to the caller so that we have one sensible log message.
Originally 850c977 "device: track system interface state in NMDevice",
intended that a connection can only be assumed initially when seeing
a device for the first time. Assuming a connection later was to be
prevented by setting device's sys-iface-state to MANAGED.
That changed too much in behavior, because we used to assume external
connections also when they are activated later on. So this was attempted
to get fixed by
- acf1067 nm-manager: try assuming connections on managed devices
- b6b7d90 manager: avoid generating in memory connections during startup for managed devices
It's probably just wrong to prevent assuming connections based on the
sys-iface-state. So drop the check for sys-iface-state from
recheck_assume_connection(). Now, we can assume anytime on managed,
disconnected interfaces, like previously.
Btw, note that priv->startup is totally wrong to check there, because
priv->startup has the sole purpose of tracking startup-complete property.
Startup, as far as NMManager is concerned, is platform_query_devices().
However, the problem is that we only assume connections (contrary to
doing external activation) when we have a connection-uuid from the state
file or with guess-assume during startup.
When assuming a master device, it can fail with
(nm-bond): ignoring generated connection (IPv6LL-only and not in master-slave relationship)
thus, for internal reason the device cannot be assumed yet.
Fix that by attatching the assume-state to the device, so that on multiple
recheck_assume_connection() calls we still try to assume. Whenever we try
to assume the connection and it fails due to external reasons (like, the connection
no longer matching), we clear the assume state, so that we only try as
long as there are internal reasons why assuming fails.
https://bugzilla.redhat.com/show_bug.cgi?id=1452062
The state file should only be read initially when NM starts, that is:
during NMManager's platform_query_devices().
At all later points, for example when a software device gets destroyed
and re-realized, the state file is clearly no longer relevant.
Hence, pass the set-nm-owned flag from NMManager to realize_start_setup().
This is very much the same as with the NM_UNMANAGED_FLAG_USER_EXPLICT flag,
which we also read from the state-file.
The plugins may use stuff from core, but not the other way around.
Including "bluetooth/nm-bluez-common.h" is wrong.
The UUID argument is always "nap" in the NAP case. We don't need
the flexibility that it might be anything else. Just drop it.
As far as NMDevice is concerned, it anyway wouldn't (or shouldn't
know what the uuid is. It says register, and NMBluez5Manager should
figure out the details.
We'll use this to let the devices know they can retry autoactivation
because some component became available without actually having any
data that would be useful for that device.
Adjust the comment.
Don't give the subclass the ability to override the parents
behavior. The parent implementation is not intended to allow
for that. Instead, restrict the flexibility of how the virtual
function integrates with the larger picture. That means, the
virtual function is only called at one place, and there is only
one implementation in NMDeviceEthernet (and it doesn't really
matter whether the implementation chains up the parent implementation
or not).
Before, setting a device to unmanaged causes it to go down and clear
the interface state.
It may be useful to instruct NetworkManager not to touch the device
anymore but leave the current state up. Changing behavior for
nmcli device set "$DEV" managed no
To get the previous behavior, one has to first disconnect the interface
via
nmcli device disconnect "$DEV"
nmcli device set "$DEV" managed no
Note that non-permanent addresses like from DHCP will eventually time
out because NetworkManager stops the DHCP client. When instructing
NetworkManager to let go of the device, you have to take it over in
any way you see fit.
https://bugzilla.redhat.com/show_bug.cgi?id=1371433
(cherry picked from commit 9e8218f99a)
This also ensures that we own a reference to the
NMPlatform, NMRouteManager and NMDefaultRouteManager
instances. See bug rh#1440089 where we might access
the singleton getter after destroing the singleton
instance of NMRouteManager. This is prevented by
keeping a reference to those instances -- indirectly
via the netns instance.
Later, we may add support for multiple namespaces. Then it might
make sense to swap the NMNetns instance of a device when moving
the device between namespaces.
Also, drop the use of singelton instances.
https://bugzilla.redhat.com/show_bug.cgi?id=1440089
(cherry picked from commit c48a19b7c6)
This moves tracking of connectivity to NMDevice and makes the NMManager
negotiate the best of known connectivity states of devices. The NMConnectivity
singleton handles its own configuration and scheduling of the permission
checks, but otherwise greatly simplifies it.
This will be useful to determine correct metrics for multiple default routes
depending on actual internet connectivity.
The per-device connection checks is not yet exposed on the D-Bus, since they
probably should be per-address-family as well.
When deciding whether to touch a device we sometimes look at whether
the active connection is external/assumed. In many cases however,
there is no active connection around (e.g. while moving the device
from state unmanaged to disconnected before assuming).
So in most cases we instead look at the device-state-reason to decide
whether to touch the interface (see nm_device_state_reason_check()).
Often it's desirable to have no state and passing data as function
arguments. However, the state reason has to be passed along several hops
(e.g. a queued state change). Or a change to a master/slave can affect
the slave/master, where we pass on the state reason. Or an intermediate
event might invalidate a previous state reason. Passing the state
whether to touch a device or not as a state-reason is cumbersome
and limited.
Instead, the device should be aware of whats going on. Add a
sys-iface-state with:
- SYS_IFACE_STATE_EXTERNAL: meaning, NM should not touch it
- SYS_IFACE_STATE_ASSUME: meaning, NM is gracefully taking over
- SYS_IFACE_STATE_MANAGED: meaning, the device is managed by NM
- SYS_IFACE_STATE_REMOVED: the device no longer exists
This replaces most checks of nm_device_state_reason_check() and
nm_active_connection_get_activation_type() by instead looking at
the sys-iface-state of the device.
This patch probably has still issues, but the previous behavior was
not very clear either. We will need to identify those issues in future
tests and tweak the behavior. At least, now there is one flag that
describes how to behave.
nm_device_uses_assumed_connection() basically called
nm_active_connection_get_assumed() on the device.
Rename those functions to be closer to the activation-type
flags.
The concepts of "assume", "external", and "assume_or_external"
will make sense with the following commits.
Scenario:
Have a connection with DHCPv4 and a default-route. When externally
removing the default route (`ip route delete 0.0.0.0/0`) and issuing
`nmcli device reapply $IF`, the default route was not restored.
That was because when externally removing the default route,
we would remove the gateway from priv->con_ip4_config (see
update_ip4_config()). Later, when reapplying the connection,
the IP method doesn't actually change. So we would not restart
DHCP and thus there is no gateway around to add the default route.
The default route would only be restored after receiving a DHCP lease
in the far future.
Fix that, by always restarting the IP method.
Add two new methods can_reapply_change() and reapply_connection() to
the device class. In this way device subclasses can declare that they
support the changes in a given setting and take care of reapplying it.
The state-change of a device has a reason argument, which is mostly for information
only.
There are many places in code that are the source of a state-reason.
Mostly these are calls to:
- nm_device_state_changed()
- nm_device_queue_state()
- nm_device_queue_recheck_available()
- nm_device_set_unmanaged_by_*()
- nm_device_master_release_one_slave()
- nm_device_ip_method_failed()
- nm_modem_emit_prepare_result()
- nm_modem_emit_ppp_failed()
- nm_manager_deactivate_connection()
- NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_*);
However, there are a few places in code that look at the reason
to decide how to proceed. I think this is a bad pattern, because
cause and effect are decoupled and it gets hard to understand where
a certain reason is set and what consequences that has.
Add a nop-function nm_device_state_reason_check() to mark all uses
of the device state reason that derive decisions from it. That is,
highlight the "effect" part.
This argument is only relevant when the NMActStageReturn argument
indicates NM_ACT_STAGE_RETURN_FAILURE. In all other cases it is ignored.
Rename the argument to make the meaning clearer. The argument is passed
through several layers of code, it isn't obvious that this argument only
matters for the failure case. Also, the distinct name makes it easier
to distinguish from other uses of the "reason" name.
While at it, do some drive-by cleanup:
- use g_return_*() instead of g_assert() to have a more graceful
assertion.
- functions like dhcp4_start() don't need to return a failure reason.
Most callers don't care, and the caller who does can determine the
proper reason.
- allow omitting the out-argument via NM_SET_OUT().
Use the per-connection authentication timeout for 802.1X Ethernet,
MACsec and Wi-Fi connections. In case the value is not defined, fall
back to the global one.
It allows derived classes to override the autoconnect-allowed
state.
We already have
- NM_DEVICE_AUTOCONNECT property, which is two parts:
- NMDevicePrivate::autoconnect_user, which is settable via
D-Bus by the use, to allow the device to autoconnect.
- NMDevicePrivate::autoconnect_intern, which is set by
internal decision.
- NM_DEVICE_AUTOCONNECT_ALLOWED signal, where other devices can
subscribe to block autoconnect. Currently that is only used
by NMDeviceOlpcMesh.
These two make up for nm_device_autoconnect_allowed().
Add another way to allow derived classes to disable autoconnect
temporarily. This could also be achieved by having the device
subscribe to NM_DEVICE_AUTOCONNECT_ALLOWED of self, or by adding
a signal slot. But a plain function pointer seems easier.
The NMDevice's autoconnect property is settable via D-Bus and is is
also modified by internal decision, like when no PIN is available.
Certain internal actions cause clearing the internal autoconnect flag,
but they should not override the user desicion.
For example, when NM awaks from sleep it would reenable autoconnect,
but it should not reenable it for devices where the user explicitly
said that autoconnect is to be disabled.
Similarly, activating a device alone is not yet an instruction to
re-enable autoconnect. If the user consciously disables autoconnect,
it should stay enabled. On the other hand, activating a device should
reenable autoconnect if it was blocked by internal decision.
We need to track these two flags separately, and set them accordingly.
Previously, we would have different functions like
- nm_match_spec_device_type()
- nm_match_spec_hwaddr()
- nm_match_spec_s390_subchannels()
- nm_match_spec_interface_name()
which all would handle one type of match-spec.
So, to get the overall result whether the arguments
match or not, nm_device_spec_match_list() had to stich
them together and iterate the list multiple times.
Refactor the code to have one nm_match_spec_device()
function that gets all relevant paramters.
The upside is:
- the logic how to evaluate the match-spec is all at one place
(match_device_eval()) instead of spread over multiple
functions.
- It requires iterating the list at most twice. Twice, because
we do a fast pre-search for "*".
One downside could be, that we have to pass all 4 arguments
for the evaluation, even if the might no be needed. That is,
because "nm-core-utils.c" shall be independend from NMDevice, it
cannot receive a device instance to get the parameters as needed.
As we would add new match-types, the argument list would grow.
However, all arguments are cached and fetching them from the
device's private data is very cheap.
(cherry picked from commit b957403efd)
Instead of overwriting ip4_config_pre_commit(), add a new function
get_mtu().
This also adds a default value in case there is no user-configuration.
This will allow us later to reset a default MTU based on the device
type.
The only implementations were there for tracking the parent device.
That is now donw via nm_device_parent_*(), parent_changed_notify()
and _parent_notify_changed().
Multiple subclasses have a parent/link interface (NMDeviceIPTunnel,
NMDeviceVlan). Tracking the parent interface properly is midly
complicated to get right. So, instead of repeating it in each
subclass, track it in the parent device.
Most implementations of realize_start_notify() do the same
for link_changed().
Let NMDevice's base implementation of realize_start_notify() call
link_changed() -- which by default does notthing. This allows subclasses
to only overwrite link_changed().
There's two parts of the configuration involved: the subnet addresses
and the DNS information.
For the addressing, the shared (downlink) device signals the policy needs for a
/64 subnet. When it gets one, it merges it into the autoconf configuration and
forwards to the NDisc. When more prefixes are needed, the (uplink) device asks
the DHCP manager and eventually signals delegation (reception) of a prefix.
The NMDevice only provides the mechanism, the actual subnetting needs to
be done by the NMPolicy.
For the DNS configuration, the shared device just copies it from
whichever device the policy deems suitable.
Before the link is initialized, that is before UDEV completed
initializing the device, we should not evaluate the user-settings
unmanaged flags.
The reason is, that evaluating it likely involves looking at the
permanent MAC address, which might use the wrong fake MAC address
(before UDEV set the right one). Also, it might use the wrong ifname
to lookup the permanent MAC address via ethtool.
The permanent MAC address of an NMDevice shall not change as
long as the device is realized. That is, we read it only once
and don't change it afterwards.
There are two issues that this commit tries to mitigate:
(1) users are advised to use UDEV to rename interfaces. As we lookup
the permenent MAC address using ethtool (which uses the interface
name), there is a race where we could read the permanent MAC
address using the wrong interface name. We should wait until
UDEV finished initializing the device and until the interface
name is stable (see rh#1388286).
This commit still cannot avoid the race of ethtool entirely. It only
tries to avoid ethtool until UDEV has done its work. That is, until we
expect the interface name no longer to change.
(2) some device types, don't have a permanent MAC address so we fall
back to use the currently set address (fake). Again, users are advised
to use UDEV to configure the MAC addresses on such software devices.
Thus, we should not get the fake MAC address until UDEV initialized
the device.
This patch actually doesn't solve the problem at all yet.
The reason is that a regular caller of nm_device_get_permanent_hw_address() can
not afford to wait until UDEV settled. Thus, any user who requests the
permanent MAC address before the link is initialized, runs into the
problems above.
In a next step, we shall revisit such calls to nm_device_get_permanent_hw_address()
and delay them until the link is initialized.
On devices that have no real permanent hardware address (as returned
by ethtool), we take the current MAC address of the device.
Currently, NM is a bit flaky about whether to accept such fake permanent
addresses for settings like keyfile.unmanaged-devices or the per-
connection property ethernet.mac-address. Probably, we should allow
using fake addresses there in general.
However, that leads to problems because NetworkManager itself changes
the current MAC address of such devices. For example when
configuing
keyfile.unmanaged-device=22:33:44:55:66:77
and later activating a connection with
ethernet.cloned-mac-address=22:33:44:55:66:77
we have a strange situation after restart and the device becomes
unmanaged.
We are going to avoid that, by remembering the fake permanent address
in the device state file.
This only matters:
- for devices that don't have a real permanent address (veth)
- if the user or NetworkManager itself changed the MAC address
of the device
- after a restart of NetworkManager, without reboot. A reboot
clears the device state for /var/run/NetworkManager.
src: Fixes in nm-device.c and nm-vpn-connection.c to update PacRunner
at the right place and moment. When a device goes up PacRunner is
configured with the Device IPxConfigs and Proxy Config. When it goes
down the same configuration is removed from PacRunner.
ifcfg-rh: Fixed to read and write proxy settings to the ifcfg network
scripts.
No need for the setter/getter of this property.
Immutable properties are so much nicer. Remove the setter and
ensure that the nm_plugin_missing property is only set during
object construction.
brcmfmac and possibly other drivers don't change the MAC address
right away, but instead the result is delayed. That is problematic
because we cannot continue activation before the MAC address is
settled.
Add a hack to workaround the issue by waiting until the MAC address
changed.
The previous attempt to workaround this was less intrusive: we would
just refresh the link once and check the result. But that turns out
not to be sufficent for all cases. Now, wait and poll.
https://bugzilla.gnome.org/show_bug.cgi?id=770456https://bugzilla.redhat.com/show_bug.cgi?id=1374023