If the IP configuration requires slaves/ports, starting IP configuration
before the master device has a carrier (which means at least one slave
or port has a carrier and the device is initialized) is pointless, and
will just take longer or fail. Recent kernels have cleaned up carrier
handling on bridge/bond devices and the carrier is now a reliable
indication of whether or not the master device is ready to send/receive
traffic. Thus, if we don't have a carrier, obviously no IP configuration
that depends on connectivity is going to work.
Less confusing in the logs to see the change logged before listeners
have a chance to emit other log messages that may depend on the new
carrier state.
It's not very helpful to deactivate a slave of a bond or a bridge
port because the carrier is lost. Carrier failures are normal
operation when using various bonding failover modes. For bridge
ports, it's probably not very helpful either. Given that the
masters are all virtual interfaces and have been explicitly
configured and started by a user, the configuration should
generally be left alone unless explicitly deactivated or changed.
Broken by e7caad20c9.
Admittedly, GObject is opaque in this area. But here's the
equivalent concepts in C++:
*_GET_CLASS (object)->function(object):
- call youngest implementation of virtual function; checks current
object for implementation and calls it, if not overridden by the
child, walks up the inheritance chain and calls parent,
grandparent, etc. C++ equivalent is calling foo::function().
*_CLASS (object_parent_class)->function(object):
- call named parent class implementation, *not* including current
object. C++ equivalent is calling ParentClass::function().
Using _GET_CLASS()->function() inside the child implementation of
function() recursively calls the child implementation of function()
and overflows the call stack.
The code flow is actually somewhat simpler this way since the
subclasses don't have to ask NMDeviceWired for the address
every time. Plus then NMDeviceWired doesn't have to know
anything about its subclasses in the constructor.
Instead of using a mix of netlink and SIOCGIFHWADDR and doing it
in every device, create a utility function for this and have
everywhere else call that.
The idea was copied from gtk, but it's only used there in cases where
the method's wrapper function and default implementation would
otherwise have the same name, which never happens in NM because our
method implementations aren't prefixed with the type name, so it's
just noise here.
Buggy kernel drivers sometimes default the carrier to ON when they
are capable of link-detection but the carrier is actually off, and
they quickly switch the carrier OFF when they determine actual
carrier state (cdc-ether, for example).
The initial carrier ON event would trigger a queued state change
from UNAVAILABLE to DISCONNECTED, which may auto-activate the
device. But before that state change happens, if a carrier OFF
event comes in, that queued state was not getting cleared and
the device would transition to DISCONNECTED even though the
carrier was off.
To ensure that never happens, and that we don't enter states that
aren't valid when the carrier is off, we need to clear any queued
state changes that wouldn't be valid in the new carrier state.
Carrier checking can be synchronous, like when bringing up the device.
If the carrier changes as a result of the sync carrier state checking,
the code might change state. Unfortunately brining up a device
happens in response to a state change already, and we can't change
state from within handlers for the device state change signal, so
we need to queue up the new state change that results from a
carrier change.
Virtual devices that we might create when their slave is started
(like bonds) have a virtual carrier that often isn't set on when
until the device is brought up. The device is brought up during
creation, but the initial carrier check happens before the device
is up, so the initial carrier state from the constructor isn't
quite accurate in some cases.
Since we want to use virtual interfaces that we create right after
we create them, we want them to be available too, and that usually
requires the carrier to be on. So recheck the carrier right after
bringing the interface up, so that the carrier state is accurate
immediately after the device is created.
Speed is gotten via ethtool on 'carrier on' event. If there is a more suitable
netlink event we should use it instead. Nonetheless, it appears to be working
fine with carrier change, because interface speed change does emit carrier offi
and on events.
Wired connections acting as bonding slave will have their ip4
config disabled. Allow such connections to reassume devices.
Signed-off-by: Thomas Graf <tgraf@redhat.com>