This speeds up the initial object tree load significantly. Also, it
reduces the object management complexity by shifting the duties to
GDBusObjectManager.
The lifetime of all NMObjects is now managed by the NMClient via the
object manager. The NMClient creates the NMObjects for GDBus objects,
triggers the initialization and serves as an object registry (replaces
the nm-cache).
The ObjectManager uses the o.fd.DBus.ObjectManager API to learn of the
object creation, removal and property changes. It takes care of the
property changes so that we don't have to and lets us always see a
consistent object state. Thus at the time we learn of a new object we
already know its properties.
The NMObject unfortunately can't be made synchronously initializable as
the NMRemoteConnection's settings are not managed with standard
o.fd.DBus Properties and ObjectManager APIs and thus are not known to
the ObjectManager. Thus most of the asynchronous object property
changing code in nm-object.c is preserved. The objects notify the
properties that reference them of their initialization in from their
init_finish() methods, thus the asynchronously created objects are not
allowed to fail creation (or the dependees would wait forever). Not a
problem -- if a connection can't get its Settings, it's either invisible
or being removed (presumably we'd learn of the removal from the object
manager soon).
The NMObjects can't be created by the object manager itself, since we
can't determine the resulting object type in proxy_type() yet (we can't
tell from the name and can't access the interface list). Therefore the
GDBusObject is coupled with a NMObject later on.
Lastly, now that all the objects are managed by the object manager, the
NMRemoteSettings and NMManager go away when the daemon is stopped. The
complexity of dealing with calls to NMClient that would require any of
the resources that these objects manage (connection or device lists,
etc.) had to be moved to NMClient. The bright side is that his allows
for removal all of the daemon presence tracking from NMObject.
The assumption is not too useful to the library user anyway -- it could easily
be that there's some other link to the object in the object tree.
More importantly, when the objects are managed by the object manager,
we don't destroy the object until we see it actually removed on the
D-Bus. That makes more sense anyway.
Don't let a later property update finish than the sooner one.
This wouldn't happen most of time, apart from a special case when the
latter update of a object array property is to an empty list.
In that case the latter update would complete sooner and when the
earlier update finishes the list would contain objects which are
supposed to be gone already.
It is a bit fragile not to clone the string because we depend on
nm_ip6_config_get_search(priv->ip6_config) to be stable.
In practice, it's no problem. Saves an additional strdup and the
effort to cleanup the memory afterwards.
We already use several GCC extenions, like typeof() and
__attribute__((cleanup)). They are too convinient to miss
and every supported compiler must support these.
Currently, gcc and clang does. Maybe other compilers would
support that too, but who knows, nobody seems to test that.
We also already use stdbool.h (C99) and the imported systemd
code is mostly gnu99 too (it's not clear to me, because I don't
find it precisely documented. Certainly it makes use of C99 features
too).
C99/gnu99 has some nice improvements that we no longer should miss
out. For example "flexible array members" or "variable declaration
in init-part of for loop".
It doesn't mean we have to use every obscure (badly supported?)
feature, it means we don't have to forgo features that are well
supported. C99 is 17 years old, I mean, really...
If somebody comes along and ports NM to non-gcc/clang, we can address
bugs about unsupported language features as they surface.
But let's not restrict us to some hypothetical compiler (or language
specification).
Also, NetworkManager is not ported on environment beside Linux.
We don't have to be so considerate about the required build environment.
Gcc is probably the most portable compiler out there. I doubt porting
NetworkManager to *BSD fails due to missing gnu99 features. And if that
causes issues, we should fix them after they happen in practice.
- only record @now timestamp if we actually need it.
- use gint32 for @now. It seems wrong that NMNDiscDNSServer
uses guint32 for the timestamp. We keep
nm_utils_get_monotonic_timestamp_s() as gint32 for a reason.
- ensure the arrays are initialized to zero. E.g.
ndisc_addr->dad_counter was uninitalized.
- set the size for arrays outside the loop
- use g_array_unref(). I think that is usually better. It makes
only a difference when somebody else holds a reference to the
array. And in that case, it usually seems better not to clear
the array, just release your refrence.
You cannot assume that we are always able to lookup a corresponding
lnk object. In fact, there is no guarantee that link->ifindex still
exists in the platform cache at all.
The compiler warns us when we don't specify all enum values
in a switch(), provided that default: is missing.
Make use of that to get a warning when we add a new tunnel mode.
When an IP-tunnel connection with mode different from the implemented
ones was activated, an assertion failed in tunnel_mode_to_link_type().
Instead we should return NM_LINK_TYPE_UNKNOWN there and fail the
activation.
The policy listens to signals from shared devices that need subnets and
requesting devices that provide prefixes. Whenever a subnet is needed,
policy tries to obtain a subnets from all of default6 device's prefixes.
When it fails to get any, it asks for more prefixes.
This way we make it possible for the delegating router to either
provide us with a /64 for each of our shared interfaces, or provide a
larger prefix that we could subnet.
The policy also updates the shared device's DNS information to keep it in sync
with the best requesting device changes.
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.
Utilizes RFC 3633 prefix option in role of requesting router to ask the
delegating router for prefixes. In future we'll be able to use the
addresses from those prefixes on ipv6.method=shared connections.
It will make sense to log the options even if we're not creating an
ip6_config (e.g. we got a prefix option, not an address).
Also, guard it with a logging enable conditional. That way we save
precious microseconds so that we'll feel less guilty about the demise of
mankind and universe.
This esentially causes us to announce the prefixes of the addresses we
own and the DNS configuration.
Currently the only way to get the IPv6 configuration on such device is
manual setting in the connection. This will change with IPv6 prefix
delegation.
IPv4 already allows setting an address, reusing its prefix for the network
it shares connection with. Additionally, for IPv6, the NDP can also share
the DNS configuration.
The ndisc config can now be changed by NMDevice as well when the NDisc
is in ROUTER mode. But what we're really interested in is when we
receive a new one from the outside.