Change nm_platform_link_get() to return the cached NMPlatformLink
instance. Now what all our implementations (fake and linux) have such a
cache internal object, let's just expose it directly.
Note that the lifetime of the exposed link object is possibly quite
short. A caller must copy the returned value if he intends to preserve
it for later.
Also add nm_platform_link_get_by_ifname() and modify nm_platform_link_get_by_address()
to return the instance.
Certain functions, such as nm_platform_link_get_name(),
nm_platform_link_get_ifindex(), etc. are solely implemented based
on looking at the returned NMPlatformLink object. No longer implement
them as virtual functions but instead implement them in the base class
(nm-platform.c).
This removes code and eliminates the redundancy of the exposed
NMPlatformLink instance and the nm_platform_link_get_*() accessors.
Thereby also fix a bug in NMFakePlatform that tracked the link address
in a separate "address" field, instead of using "link.addr". That was
a case where the redundancy actually led to a bug in fake platform.
Also remove some stub implementations in NMFakePlatform that just
bail out. Instead allow for a missing virtual functions and perform
the "default" action in the accessor.
An example for that is nm_platform_link_get_permanent_address().
Later remove nm_platform_get_error() and signal errors via return
error codes.
Also, fix nm_platform_infiniband_partition_add() and
nm_platform_vlan_add() to check the type of the existing link
and fail with WRONG_TYPE otherwise.
After hiding the udi field, there are no more users of NMRefString.
Remove the code by explitly reverting the patch so that in case of a future
need, we can find and resurrect NMRefString.
This reverts commit 430658b17a.
Switch platform caching implementation. Instead of caching libnl
objects, cache our own types.
Don't remove yet the now obsolete functions.
Advantage:
* Performance
- as we now cache our native NMPlatformObject instances, we no longer
have to convert libnl objects every time we access the platform
cache.
- for most cases, access is now O(1) because we can lookup the object
in a hash table. Note that ip4_address_get_all() still has to
create a copy of the result (O(n)), but as the caller is about to
use those elements, he cannot do better then O(n) anyway.
* We cache our own native types and have full control over them. We
cannot extend the libnl objects, which has many short-commings:
- _rtnl_addr_hack_lifetimes_rel_to_abs() to convert the timestamps
to absolute values (and back).
- hack_empty_master_iff_lower_up() would modify the internal flag,
but it looses the original value. That means, we can only hack
the state before putting a link into the cache, but we cannot revert
that change, when a slave in the cache changes state.
That was previously solved by always refetching the master when
a slave changed. Now we can re-evaluate the connected state
(DELAYED_ACTION_TYPE_MASTER_CONNECTED).
- we implement functions like equality, to-string as most suitable
for us. Before we needed hacks like nm_nl_object_diff(),
nm_nl_cache_search(), route_search_cache().
- we can extend our objects with exactly those properties we care,
and possibly additional properties that are not representable in
the libnl objects.
- we no longer cache RTM_F_CLONED routes and they get rejected early
on as we receive them.
- In the future, maybe it'd be interesting the make platform objects
immutable (and ref-counted) and expose them directly.
* Previous implementation did not order the refresh of objects but
called check_cache_items(). Now, those actions are delayed and
combined in an attempt to reduce the overall number of reloads.
Realize how expensive a check_cache_items() for addresses and routes
was: it would iterate all addresses/routes and call refresh_object().
The latter obtains a full dump of *all* objects again, and ignores
all but the needle.
Note that we probably still schedule some delayed actions that
are not needed.
Later we can optimize that further (related bug bgo #747985).
While some of these points could also have been implemented with
caching of libnl objects, that would have become hard to maintain.
https://bugzilla.gnome.org/show_bug.cgi?id=747981
A class to do efficient lookup for multiple values based on a key.
The values are opaque pointers (void*). These values can be
associated with keys. The keys are an opaque type NMMultiIndexId
with arbitrary hash/equal functions.
Think of the keys being a set of buckets. A value can be associated with multiple
keys, just like with a regular GHashTable (i.e. it can be in multiple buckets).
But one key can also be associated with multiple values (i.e. one bucket can contain
multiple values). Hence the name "multi".
One bucket can only either contain a value or not. It cannot contain the same
value multiple times.
This is implemented as a hash of hashes with the outer keys being
NMMultiIndexId. The inner hashes are the "buckets".
This class will be used as an efficient lookup index to find all values
that belong to a certain key (bucket). Later we will ask for example
"Which IP4-Addresses are associated with a certain ifindex" and
efficiently retrieve the cached result list.
NMRefString is a simple, refcounted, immutable string. Increasing/decreasing
the refcount does not affect const-ness.
It can be used just like a regular 'const char *' pointer. The only
difference is that you need special alloc/free functions.
Cache the scope as part of the NMPlatformIP4Route and
no longer read it from libnl object when needed. Later
there will be no more libnl objects around, and we need
to scope when deleting an IPv4 route.
warning: function declaration isn’t a prototype [-Wstrict-prototypes]
In C function() and function(void) are two different prototypes (as opposed to
C++).
function() accepts an arbitrary number of arguments
function(void) accepts zero arguments
Add support for a new section [connection] in NetworkManager.conf.
If the connection leaves an option at "unknown"/"default", we can
support overwriting the value from global configuration.
We also support other sections that are named with "connection"
as a prefix, such as [connection2], [connection-wifi]. This is
to support multiple default values that can be applied depending
on the used device.
I think this has great potential. Only downside is that when
the user looks at a connection value, it will see that it is
unspecified. But the actually used value depends on the device
type and might not be obvious.
https://bugzilla.gnome.org/show_bug.cgi?id=695383https://bugzilla.redhat.com/show_bug.cgi?id=1164677
Up to now, this code was correct. Later we will add another field
to NMPlatformIP4Route which causes the test to operate on
uninitialized data.
Instead of explicitly initializing the field, just clear the whole
struct.
We do the same for the original MAC address.
A device enslaved to a bond it inherits the bond's MAC address. When
NetworkManager tries to assume a connection the generated cloned-mac property
causes a mismatch with the connection that originally brought up the device,
causing the generated connection to be used instead:
NetworkManager[14190]: <debug> [1424355817.112154] [NetworkManagerUtils.c:1641]
nm_utils_match_connection(): Connection 'eth2' differs from candidate
'bond-slave-eth2' in 802-3-ethernet.cloned-mac-address
https://bugzilla.gnome.org/show_bug.cgi?id=744812
nm_ethernet_address_is_valid() did not check whether @addr was a valid
address in the first place. It only checked whether the address was not
equal to a few notorious MAC addresses.
At the same time, be more forgiving and accept %NULL as argument.
This fixes an assertion nm_ap_match_in_hash().
Most nm_platform_*() functions operate on the platform
singleton nm_platform_get(). That made sense because the
NMPlatform instance was mainly to hook fake platform for
testing.
While the implicit argument saved some typing, I think explicit is
better. Especially, because NMPlatform could become a more usable
object then just a hook for testing.
With this change, NMPlatform instances can be used individually, not
only as a singleton instance.
Before this change, the constructor of NMLinuxPlatform could not
call any nm_platform_*() functions because the singleton was not
yet initialized. We could only instantiate an incomplete instance,
register it via nm_platform_setup(), and then complete initialization
via singleton->setup().
With this change, we can create and fully initialize NMPlatform instances
before/without setting them up them as singleton.
Also, currently there is no clear distinction between functions
that operate on the NMPlatform instance, and functions that can
be used stand-alone (e.g. nm_platform_ip4_address_to_string()).
The latter can not be mocked for testing. With this change, the
distinction becomes obvious. That is also useful because it becomes
clearer which functions make use of the platform cache and which not.
Inside nm-linux-platform.c, continue the pattern that the
self instance is named @platform. That makes sense because
its type is NMPlatform, and not NMLinuxPlatform what we
would expect from a paramter named @self.
This is a major diff that causes some pain when rebasing. Try
to rebase to the parent commit of this commit as a first step.
Then rebase on top of this commit using merge-strategy "ours".
Refactor the implementation of nm_route_manager_ip4_route_sync()
and nm_route_manager_ip6_route_sync().
- merge the implementations for IPv4 and IPv6.
- pre-sort the routes and iterate them in a way that we don't
need to lookup a route in other lists. Do this by iterating
two sorted lists at a time in a merge-sort way.
The runtime complexity of sync is now O(n*ln(n)).
- previously, the algorithm would merge routes it found in platform
to priv->ipx_routes. That was wrong, because then we loose the
information which routes we wanted to configure internally and which
are present externally.
Instead, priv->ipx_routes now contains all the routes that were
explicitly configured via sync(). Hence, it knows what should be
configured (@ipx_routes) and can compare to what is configured
(@plat_routes).
https://bugzilla.gnome.org/show_bug.cgi?id=740064
Tests that use g_assert_expect_message() must initialize with
nmtst_init_assert_logging().
Otherwise, the caller can change the logging level via
NMTST_DEBUG=log-level=DEBUG,log-domains=DEFAULT
which breaks the assertions.
nmtst_init_assert_logging() allows the caller to turn of
checking of assertions via
NMTST_DEBUG=log-level=DEBUG,log-domains=DEFAULT,no-expect-message
Also, don't use g_message() in platform tests otherwise the test fail
because nmtst now sets g_log_set_always_fatal().
Before, when having a test with nmtst_init_assert_logging(),
the caller was expected to setup logging separately according
to the log level that the test asserts against.
Since 5e74891b58, the logging
level can be reset via NMTST_DEBUG also for tests that
assert logging. In this case, it would be useful, if the test
would not overwrite the logging level that is set externally
via NMTST_DEBUG.
Instead, let the test pass the logging configuration to
nmtst_init_assert_logging(), and nmtst will setup logging
-- either according to NMTST_DEBUG or as passed in.
This way, setting the log level works also for no-expect-message
tests:
NMTST_DEBUG="debug,no-expect-message,log-level=TRACE" $TEST
There's no udev running in containers, it only starts if /sys is writable. If a
hardware device is added to the container's namespace NM would not announce it.
This also removes the software link special case -- the software links will now
wait for udev initialization (in case udev is there) as well. There's no reason
to treat them differently anymore. This makes it possible to use udev properties
of the software links.
https://bugzilla.gnome.org/show_bug.cgi?id=740526
No functional change, a cosmetic thing for now.
We want it set before any routes are added and ensure routes have a valid
ifindex before we pass it to the platform.
In a future NMRouteManager will need to look up the route for a device in
its cache thus we'll need to make sure routes passed to the it have an
appropriate ifindex set.
No functional change, a cosmetic thing for now.
We want it set before any routes are added and ensure routes have a valid
ifindex before we pass it to the platform.
In a future NMRouteManager will need to look up the route for a device in
its cache thus we'll need to make sure routes passed to the it have an
appropriate ifindex set.
There are currently three device spec properties: 'main.ignore-carrier',
'main.no-auto-default' and 'keyfile.unmanaged-devices'.
The first two, called g_key_file_parse_value_as_string() to split
the string into individual device specs. This uses ',' as separator
and supports escaping using '\\'.
'keyfile.unmanaged-devices' is split using ',' or ';' as separator
without supporting escaping.
Add a new function nm_match_spec_split(), to unify these two behaviors
and support both formats. That is, both previous formats are mostly
supported, but obviously there are some behavioral changes if the string
contains one of '\\', ',', or ';'.
nm_match_spec_split() is copied from glibs g_key_file_parse_value_as_string()
and adjusted.
Extend nm_match_spec_*() to support an "except:" prefix to negate
the result of a match. "except:" only works when followed by
an exact match type, for example "except:interface-name:vboxnet0",
but not "except:vboxnet0".
A matching "except:" spec always wins, regardless of other positive
matchings.
This includes several changes how to match device specs:
- matching the interface name is no longer case-insenstive as
interface names themselves are case-sensitive.
- Now we skip patterns that start with "mac:" or "s390-subchannels:"
for comparing interface names. Previously a spec "mac:1" would have
matched an interface named "mac:1", now it doesn't.
To match such an interface, you would have to specify
"interface-name:mac:1".
- previously, a pattern "a" would have matched an interface
named "interface-name:a", now it doesn't. Since valid interface
name (in the kernel) can be at most 15 characters long, this is
however no problem.
- if the spec has the prefix "interface-name:", we support
simple globbing using GPatternSpec. Globbing without exact
spec type will still not match "vboxnet*" -- with the exception
of "*".
You can disable globbing by putting an '=' immediately
after the ':'.
(a) "interface-name:em1" | matches "em1"
(b) "interface-name:em*" | matches "em", "em1", "em2", etc.
(c) "interface-name:em\*" | matches "em\", "em\1", etc.
(d) "interface-name:=em*" | matches "em*"
(e) "em*" | matches "em*"
We don't need the bus for the tests and the manager may warn when it
is not available.
$ (cd src/tests/config/; env -i DBUS_SYSTEM_BUS_ADDRESS=meow ./test-config)
/config/parse-error: OK
/config/no-auto-default: NetworkManager-Message: <info> Could not connect to the system bus; only the private D-Bus socket will be available.
/bin/sh: line 5: 29997 Trace/breakpoint trap ${dir}$tst
FAIL: test-config
This reverts commit 6994454461 for the
most part. It's not sufficient to disable logging warnings. Creating
a DBus Manager might affect the system in undesired ways.