Commit graph

100 commits

Author SHA1 Message Date
Thomas Haller
5c42cdb287 all: use _nm_utils_ip4_*() utils functions 2017-09-05 18:44:04 +02:00
Thomas Haller
17f0c19473 platform: fix updating object in nmp_cache_update_netlink_route()
_idxcache_update() may remove @entry_old or it may update @entry_old
in-place.

We must assign @out_obj_old before and not touch @entry_old after
_idxcache_update().

Fixes: cdd8c65799
2017-08-18 11:32:29 +02:00
Thomas Haller
94560e4ad2 platform: cleanup nmp_lookup_init_route_visible() lookup helper
nmp_lookup_init_route_visible() was originally named this way, to only return routes
that are nmp_object_is_visible(). However, all routes are visible (as long as they are
nmp_object_is_alive()). Hence, this is a historic misnomer.

Also, passing @only_default FALSE is identical to the
nmp_lookup_init_addrroute() lookup.

So, rename the function to indicate it is a lookup for default routes
only. Also, get rid of the unsupported ifindex argument for which there
is no index.
2017-08-12 16:04:28 +02:00
Thomas Haller
cdd8c65799 platform: fix cache to use kernel's notion for equality of routes
Until now, NetworkManager's platform cache for routes used the quadruple
network/plen,metric,ifindex for equaliy. That is not kernel's
understanding of how routes behave. For example, with `ip route append`
you can add two IPv4 routes that only differ by their gateway. To
the previous form of platform cache, these two routes would wrongly
look identical, as the cache could not contain both routes. This also
easily leads to cache-inconsistencies.

Now that we have NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID, fix the route's
compare operator to match kernel's.

Well, not entirely. Kernel understands more properties for routes then
NetworkManager. Some of these properties may also be part of the ID according
to kernel. To NetworkManager such routes would still look identical as
they only differ in a property that is not understood. This can still
cause cache-inconsistencies. The only fix here is to add support for
all these properties in NetworkManager as well. However, it's less serious,
because with this commit we support several of the more important properties.
See also the related bug rh#1337855 for kernel.

Another difficulty is that `ip route replace` and `ip route change`
changes an existing route. The replaced route has the same
NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID, but differ in the actual
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID:

    # ip -d -4 route show dev v
    # ip monitor route &
    # ip route add 192.168.5.0/24 dev v
    192.168.5.0/24 dev v scope link
    # ip route change 192.168.5.0/24 dev v scope 10
    192.168.5.0/24 dev v scope 10
    # ip -d -4 route show dev v
    unicast 192.168.5.0/24 proto boot scope 10

Note that we only got one RTM_NEWROUTE message, although from NMPCache's
point of view, a new route (with a particular ID) was added and another
route (with a different ID) was deleted. The cumbersome workaround is,
to keep an ordered list of the routes, and figure out which route was
replaced in response to an RTM_NEWROUTE. In absence of bugs, this should
work fine. However, as we only rely on events, we might wrongly
introduce a cache-inconsistancy as well. See the related bug rh#1337860.

Also drop nm_platform_ip4_route_get() and the like. The ID of routes
is complex, so it makes little sense to look up a route directly.
2017-08-12 16:04:28 +02:00
Thomas Haller
94c025452b platform: preserve order of objects during dump
NMPCache can preserve the order of the objects. Until now, the order
was however arbitrary. Soon we will require to preserve the order of
routes.

During a dump, force appending new objects at the end. That ensures,
correct ordering during the dump.

Note that we track objects in several distrinct indexes. Those partition the
set of all objects. Outside a dump when receiving events about new objects (e.g.
RTM_NEWROUTE), it is very unclear at which place the new object should be sorted.
It is especially unclear, as an object might move from one partition (of
an index) to another.
In general, a deterministic order will only be useful in one particular
instance: the NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION index for routes.
In this case, we will ensure a particular order of the routes.
2017-08-12 16:02:11 +02:00
Thomas Haller
3e1914e4fc platform: cleanup lookup API for objects in NMPCache 2017-08-12 16:02:11 +02:00
Thomas Haller
5331d4d63e platform: fix code comment for nmp_cache_remove_netlink() 2017-08-12 16:02:11 +02:00
Thomas Haller
1fcc3c8c39 platform: add nmp_object_id_cmp() function
We already had a nmp_object_id_equal() function. Generally, an equal() function
is more useful then a cmp() function.

However, implementing a cmp() function is about the same effort then implementing
an equal() function. Also, an equal function can be trivially implemented based on
a compare function, but not the other way around.

That means, it is little extra effort to have both an equal() function
and a cmp() function. Add nmp_object_id_cmp(). If only to be
consistent with other code, which also provides both.
2017-08-12 15:58:58 +02:00
Thomas Haller
b94e25e269 platform: drop duplicate cmd_obj_stackinit_id() virtual function
It can be implemented solely based on cmd_plobj_id_copy().
2017-08-03 18:32:59 +02:00
Thomas Haller
372f14a6ef platform: add compare functions for routes with different compare semantics
Routes are complicated.

`ip route add` and `ip route append` behaves differently with respect to
determine whether an existing route is idential or not.

Extend the cmp() and hash() functions to have a compare type, that
covers the different semantics.
2017-08-03 18:32:59 +02:00
Beniamino Galvani
81b2d77795 platform: nmp-object: fix memory leak
Fixes: 9440eefb6d
2017-07-25 09:03:54 +02:00
Thomas Haller
ac60b0ce60 platform: move link accessors to NMPlatform base class
and refactor NMFakePlatform to also track links via NMPCache.

For one, now NMFakePlatform also tests NMPCache, increasing the
coverage of what we care about.

Also, all our NMPlatform implementations now use NMPObject and NMPCache.
That means, we can expose those as part of the public API. Which is
great, because callers can keep a reference to the NMPObject object
and make use of generic functions like nmp_object_to_string().
2017-07-05 18:37:39 +02:00
Thomas Haller
8b3b148fda platform/trivial: rename cache-id-type indexes 2017-07-05 18:37:39 +02:00
Thomas Haller
17f02318ad platform: drop separate index for visible objects
Routes and addresses don't implement cmd_obj_is_visible(),
hence they are always visible, and NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY
is identical to NMP_CACHE_ID_TYPE_OBJECT_TYPE.

Only link objects can be alive but invisible. Still, drop the index
for looking up visible links entirely. Let callers do the filtering,
if they care.
2017-07-05 18:37:39 +02:00
Thomas Haller
beb0b9b1ad platform: reduce number of route indexes
Maintaining an index is expensive.Not so much in term of runtime, but
in term of memory.

Drop some indexes, and require the caller to use a more broad index (and
filter out unwanted elements).

Dropped:

 - can no longer lookup visible default-routes by ifindex.
   If you care about default-routes, lookup all and search for the
   desired ifindex. The overall number of default-routes is expected
   to be small.
   We drop NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_WITH_DEFAULT
   entirely.

 - no longer have a separate index for non-default routes. We
   expect that the most routes are non-default routes. So, don't
   have an index without default-routes, instead let the caller
   just lookup all routes, and reject default-routes themself.
   We keep NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_DEFAULT, but it
   now no longer tracks non-default routes.

This drops 1 out of 6 route indexes, and modifes another one, so
that we expect that there are almost no entires tracked by it.
2017-07-05 18:37:39 +02:00
Thomas Haller
28340588d9 core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.

With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.

- this saves an additional GSlice allocation for the NMDedupMultiBox.

- it is immediately known, whether an NMPObject is tracked by a
  certain NMDedupMultiIndex or not. This saves an additional hash
  lookup.

- previously, when all idx-types cease to reference an NMDedupMultiObj
  instance, it was removed. Now, a tracked objects stays in the
  NMDedupMultiIndex until it's last reference is deleted. This possibly
  extends the lifetime of the object and we may reuse it better.

- it is no longer possible to add one object to more then one
  NMDedupMultiIndex instance. As we anyway want to have only one
  instance to deduplicate the objects, this is fine.

- the ref-counting implementation is now part of NMDedupMultiObj.
  Previously, NMDedupMultiIndex could also track objects that were
  not ref-counted. Hoever, the object anyway *must* implement the
  NMDedupMultiObj API, so this flexibility is unneeded and was not
  used.

- a downside is, that NMPObject grows by one pointer size, even if
  it isn't tracked in the NMDedupMultiIndex. But we really want to
  put all objects into the index for sharing and deduplication. So
  this downside should be acceptable. Still, code like
  nmp_object_stackinit*() needs to handle a larger object.
2017-07-05 18:37:39 +02:00
Thomas Haller
55e66cc7e6 platform: implement hash function for NMPlatformLnk types 2017-07-05 18:37:39 +02:00
Thomas Haller
d2f856fb95 platform: fix nmp_object_hash() to include object type
NMPlatformLnkMacvtap is a typedef of NMPlatformLnkMacvlan, hence, their
plobj implementation is idential. nmp_object_equal() already correctly
compares the object type, so we should hash it too.
2017-07-05 18:37:39 +02:00
Thomas Haller
35502807b5 platform: merge NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION* index
In this case, not much is saved, because previously IPv4 and IPv6
routes had completely distinct indexes.
2017-07-05 18:37:38 +02:00
Thomas Haller
6324b779b2 platform: merge NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_*_DEFAULT indexes
Maintaining an index is expensive. We can merge indexes that
are strictly distinct, because one index can just partition the
objects into distinct sets.
2017-07-05 18:37:38 +02:00
Thomas Haller
9440eefb6d platform: use NMDedupMultiIndex for routes in NMPCache
Rework platform object cache to use NMDedupMultiIndex.

Already previously, NMPCache used NMMultiIndex and had thus
O(1) for most operations. What is new is:

- Contrary to NMMultiIndex, NMDedupMultiIndex preserves the order of
  the cached items. That is crucial to handle routes properly as kernel
  will replace the first matching route based on network/plen/metric
  properties. See related bug rh#1337855.
  Without tracking the order of routes as they are exposed
  by kernel, we cannot properly maintain the route cache.

- All NMPObject instances are now treated immutable, refcounted
  and get de-duplicated via NMDedupMultiIndex. This allows
  to have a global NMDedupMultiIndex that can be shared with
  NMIP4Config and NMRouteManager. It also allows to share the
  objects themselves.
  Immutable objects are so much nicer. We can get rid of the
  update pre-hook callback, which was required previously because
  we would mutate the object inplace. Now, we can just update
  the cache, and compare obj_old and obj_new after the fact.

- NMMultiIndex was treated as an internal of NMPCache. On the other
  hand, NMDedupMultiIndex exposes NMDedupMultiHeadEntry, which is
  basically an object that allows to iterate over all related
  objects. That means, we can now lookup objects in the cache
  and give the NMDedupMultiHeadEntry instance to the caller,
  which then can iterate the list on it's own -- without need
  for copying anything.
  Currently, at various places we still create copies of lookup
  results. That can be improved later.

The ability to share NMPObject instances should enable us to
significantly improve performance and scale with large number
of routes.

Of course there is a memory overhead of having an index for each list
entry. Each NMPObject may also require an NMDedupMultiEntry,
NMDedupMultiHeadEntry, and NMDedupMultiBox item, which are tracked
in a GHashTable. Optimally, one NMDedupMultiHeadEntry is the head
for multiple objects, and NMDedupMultiBox is able to deduplicate several
NMPObjects, so that there is a net saving.
Also, each object type has several indexes of type NMPCacheIdType.
So, worst case an NMPlatformIP4Route in the platform cache is tracked
by 8 NMPCacheIdType indexes, for each we require a NMDedupMultiEntry,
plus the shared NMDedupMultiHeadEntry. The NMDedupMultiBox instance
is shared between the 8 indexes (and possibly other).
2017-07-05 18:37:38 +02:00
Thomas Haller
3edf2bff3d platform: fix lookup of all routes unrestricted to an ifindex
Need to use the right NMPCacheIdType when looking up routes
across all ifindexes.

Fixes: 8f9dac01ac
2017-07-05 14:22:10 +02:00
Thomas Haller
8822c45453 platform: use NM_SET_OUT() macro 2017-07-05 14:22:10 +02:00
Thomas Haller
6d9c3eab38 platform: let NMPObject implement NMDedupIndexObj 2017-07-05 14:22:10 +02:00
Thomas Haller
b8bc80bcdb all: add base object type in "nm-obj.h"
Platform has it's own, simple implementation of object types:
NMPObject. Extract a base type and move it to "shared/nm-utils/nm-obj.h"
so it can be reused.

The base type is trival, but it allows us to implement other objects
which are compatible with NMPObjects. Currently there is no API for generic
NMObjBaseInst type, so compatible in this case only means, that they
can be used in the same context (see example below).
The only thing that you can do with a NMObjBaseInst is check it's
NMObjBaseClass.

Incidentally, NMObjBaseInst is also made compatible to GTypeInstance.
It means, an NMObjBaseInst is not necessarily a valid GTypeInstance (like NMPObject
is not), but it could be implemented as such.

For example, you could do:

    if (NMP_CLASS_IS_VALID ((NMPClass *) obj->klass)) {
        /* is an NMPObject */
    } else if (G_TYPE_CHECK_INSTANCE_TYPE (obj, NM_TYPE_SOMETHING)) {
        /* it a NMSometing GType */
    } else {
        /* something else? */
    }

The reason why NMPObject is not implemented as proper GTypeInstance is
because it would require us to register a GType (like
g_type_register_fundamental). However, then the NMPClass struct can
no longer be const and immutable memory. But we could.

NMObjBaseInst may or may not be a GTypeInstance. In a sense, it's
a base type of GTypeInstance and all our objects should be based
on it (optionally, they we may make them valid GTypes too).
2017-07-05 14:22:10 +02:00
Thomas Haller
3f76b5b7eb core: use NM_HASH_COMBINE() function 2017-07-05 14:22:10 +02:00
Thomas Haller
d1b951a7e5 platform: remove plen argument for IPv6 address ID
The prefix length is not part of the ID for IPv6 address. Remove
it from nmp_object_stackinit_id_ip6_address().
2017-05-27 11:38:38 +02:00
Beniamino Galvani
e6ff7f211d platform: fix double initialization
(cherry picked from commit 708ee92c29)
2017-05-08 15:05:01 +02:00
Thomas Haller
ae8d98391a platform: only consider net part of routes for route cache's ID
Routes with a non-zero host part are not allowed by kernel and
don't really exist. We didn't reject such routes in users configuration,
so various part of NM allow such routes. NM should silently strip
the host part.

Extend the cache's route ID to clear the host part too.

Note that NM's handling of routes is fundamentally flawed, as
for kernels routes don't have an "id" (or rather: all properties
of a route are part of it's ID, not only the family,ifindex,
network/plen and metric tuple (see related bug rh#1337855).

(cherry picked from commit 57b0dce083)
2017-04-15 00:37:22 +02:00
Lubomir Rintel
ed552c732c logging: log device and connection along with the message 2017-03-24 12:42:09 +01:00
Thomas Haller
8ddc3e308c platform: remove debug logging messages from "nmp-object.c" 2017-03-23 11:55:34 +01:00
Thomas Haller
e32839838e udev: drop libgudev in favor of libudev
libgudev is just a wrapper around libudev. We can
use libudev directly and drop the dependency for
libgudev.
2017-03-22 12:41:06 +01:00
Thomas Haller
74f62d21ce platform/tests: add test code to initialize NMPCacheId with bogus data 2017-03-09 15:50:20 +01:00
Thomas Haller
f0e295d3d7 platform: filter out invisible links for cache lookup by name
Fixes: ad1d74d142
2017-03-09 15:12:43 +01:00
Thomas Haller
2972fd55bf platform/trivial: remove obsolete code comment 2017-03-09 14:57:00 +01:00
Beniamino Galvani
85103656e9 platform: add support for macsec links
Add support for a new macsec link type and its netlink attributes to
the platform code.
2017-01-16 17:37:14 +01:00
Thomas Haller
f8227029fe platform: avoid one memset() in nmp_cache_id_init()
We end up calling nmp_cache_id_init_*() a lot to initialize stack-allocated
cache-ids to lookup the NMMultiIndex. There is no need to memset() it to
zero, because all relevant fields are supposed to be set explicitly.
2017-01-16 17:20:35 +01:00
Thomas Haller
953afd681a core: use nm_offsetofend() macro 2017-01-16 17:20:35 +01:00
Thomas Haller
d32fb8158b platform: avoid copying arguments for nmp_utils_ethtool_get_driver_info()
We call nmp_utils_ethtool_get_driver_info() twice when receiving a
netlink message, but we don't need a clone of the string values.
Instead, expose a data structure that should be stack allocated
by the caller.
2016-12-13 11:26:59 +01:00
Thomas Haller
3641178508 platform: lookup ifname for ethtool/mii ioctl immediately before use
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.
2016-12-13 11:26:59 +01:00
Thomas Haller
ce2d1f062b platform: don't use static temporary cache_id
This only saves some typing at a few places. In general, avoid
static variables, so drop it in favor of a stack-allocated
cache_id.
2016-12-01 10:57:35 +01:00
Thomas Haller
3ceaef90fe core: remove unnecessary includes to netlink/route library
We no longer use libnl-route-3 library in NetworkManager. Remove the
unnecessary includes.
2016-10-07 21:37:17 +02:00
Thomas Haller
a83eb773ce all: modify line separator comments to be 80 chars wide
sed 's#^/\*\{5\}\*\+/$#/*****************************************************************************/#' $(git grep -l '\*\{5\}' | grep '\.[hc]$') -i
2016-10-03 12:01:15 +02:00
Thomas Haller
6c4447520d platform: disable debug logging for NMPObject ref-couting
These logging lines are already disabled by default as _LOGt()
is a NOP unless configured --with-more-logging.

However, the logging is still very verbose also for debug-builds
and currently there are no known issues there. Disable the logging
statements (but leave them in so they can easily be enabled).

(cherry picked from commit 4cb845558e)
2016-08-22 18:37:04 +02:00
Thomas Haller
e26fcce0f8 platform: refactor marking cloned routes in platform
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.
2016-04-28 12:53:21 +02:00
Thomas Haller
6bf022359f core/trivial: rename "source" field of addresses and routes
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.
2016-04-28 12:53:21 +02:00
Thomas Haller
f8b2cadfc1 platform: ensure cache consistency for routes by workaround missing kernel event
Consider:

  unshare -n
  ip link add d0 type dummy
  ip link add d1 type dummy
  ip link set d0 up
  ip link set d1 up
  ip addr add 192.168.100.5/24 dev d0
  ip addr add 192.168.101.5/24 dev d1

  ip route add 192.168.200.0/24 via 192.168.100.1
  ip monitor &
  ip route change 192.168.200.0/24 via 192.168.101.1
  #prints 192.168.200.0/24 via 192.168.101.1 dev d1
  ip route show
  #192.168.100.0/24 dev d0  proto kernel  scope link  src 192.168.100.5
  #192.168.101.0/24 dev d1  proto kernel  scope link  src 192.168.101.5
  #192.168.200.0/24 via 192.168.101.1 dev d1

Note that `ip route change` replaced the exising route. "Replaced" in this
case means: the previous route on device "d0" got removed and a new route
on "d1" was added. However, kernel only sent one RTM_NEWROUTE event, no
RTM_DELROUTE that notifies about this change.

We need to workaround that by re-synching the routes when we receive a
RTM_NEWROUTE notification.
2016-04-11 11:32:48 +02:00
Thomas Haller
44768f0311 platform: change @plen field of NMPlatformIPxAddress to type guint8
On netlink layer, this field is uint8_t/uchar.

A larger (signed) plen makes no sense. Adjust the signatures
to have only guint8.
2016-04-11 11:26:36 +02:00
Thomas Haller
14ee5dd2f8 platform: change @plen field of NMPlatformIPxRoute to type guint8
On netlink layer, this field is uint8_t/uchar.

A larger (signed) plen makes no sense. Adjust the signatures
to have only guint8.
2016-04-11 11:26:36 +02:00
Thomas Haller
b1e3deaf2f nmp-object: refactor handling of NMPCacheId to consider only relevant part of union
NMPCacheId is a union with fields for all known NMPCacheIdTypes.
Up to now, we always cloned the entire union, computed the hash
over all (possibly unset) fields and used memcmp() unanimously.

That was ok, because NMPCacheId was 16 bytes in total and cache-id
types that consumed less bytes didn't have a large overhead.

Next, we will add a new cache id type which increases the size of
NMPCacheId to 24 bytes. So, while possibly only a fraction of the
instances is that large, they would all have to pay that price.

Change that to consider and clone only those parts of the id
that are actually used.
2016-04-11 11:26:36 +02:00