Commit graph

1081 commits

Author SHA1 Message Date
Beniamino Galvani
df72cad107 device: add NMDevicePPP
The new device type represents a PPP interface, and will implement the
activation of new-style PPPoE connections, i.e. the ones that don't
claim the parent device.
2017-08-05 08:03:15 +02:00
Beniamino Galvani
d5c2c3f6d7 platform: add nm_platform_link_set_name()
We'll need it to rename the new PPP interface to a given name.
2017-08-05 08:03:15 +02:00
Thomas Haller
d373855e98 platform: extend API for adding routes
Via the flags of the RTM_NEWROUTE netlink message, kernel and iproute2
support various variants to add a route.

 - ip route add
 - ip route change
 - ip route replace
 - ip route prepend
 - ip route append
 - ip route test

Previously, our nm_platform_ip4_route_add() function was basically
`ip route replace`. In the future, we should rather user `ip route
append` instead.

Anyway, expose the netlink message flags in the API. This allows to
use the various forms, and makes it also more apparent to the user that
they even exist.
2017-08-03 18:51:57 +02:00
Thomas Haller
75dc0fdd27 platform,libnm: cleanup handling of TOS for routes
- kernel ignores rtm_tos for IPv6 routes. While iproute2 accepts it,
  let libnm reject TOS attribute for routes as well.

- move the tos field from NMPlatformIPRoute to NMPlatformIP4Route.

- the tos field is part of the weak-id of an IPv4 route. Meaning,
  `ip route add` can add routes that only differ by their TOS.
2017-08-03 18:51:57 +02:00
Thomas Haller
9be9cab646 core: implement NMIP4Config's and NMIP6Config's route equality based on nm_platform_ipx_route_cmp()
There are various notions of how to compare routes. Collect them all
in nm_platform_ip4_route_cmp(), nm_platform_ip4_route_hash(),
nm_platform_ip6_route_cmp(), and nm_platform_ip6_route_hash().

This way, we have them side-by-side, which makes the differences more
discoverable.
2017-08-03 18:51:35 +02:00
Thomas Haller
7141a3b87a platform: cleanup handling metric paramters for non-exclusive routes 2017-08-03 18:33:00 +02:00
Thomas Haller
93fd03277f platform: cleanup handling locks for non-exclusive routes 2017-08-03 18:33:00 +02:00
Thomas Haller
19a709069a platform: print lock paramters of route
It is valid to set "lock" for a property with numeric value 0.

    # ip route append 192.168.7.0/24 dev bond0 window lock 0
    # ip route append 192.168.7.0/24 dev bond0 window 0
    # ip route append 192.168.7.0/24 dev bond0 window lock 10
    # ip route append 192.168.7.0/24 dev bond0 window 10
    # ip -4 -d route show dev bond0
    unicast 192.168.7.0/24 proto boot scope link linkdown
    unicast 192.168.7.0/24 proto boot scope link linkdown
    unicast 192.168.7.0/24 proto boot scope link linkdown window lock 10
    unicast 192.168.7.0/24 proto boot scope link linkdown window 10

Our to-string methods should accurately print the content of
the routes. Note that iproute2 fails to do so too.
2017-08-03 18:33:00 +02:00
Thomas Haller
bf348cde69 platform: cleanup handling "window" for non-exclusive routes 2017-08-03 18:33:00 +02:00
Thomas Haller
8fc669c02a platform: use route src/src_plen when deleting IPv6 route 2017-08-03 18:33:00 +02:00
Thomas Haller
415e00d086 platform: use route pref_src when deleting IP route 2017-08-03 18:32:59 +02:00
Thomas Haller
8e4c5b173f platform: use route mss when deleting IP route
The mss (advmss, RTA_METRICS.RTAX_ADVMSS) is in a way part of
the ID for IPv4 routes. That is, you can add multiple IPv4 routes, that
only differ by mss.

On the other hand, that is not the case for IPv6. Two IPv6 routes
that only differ by mss are considered the same.

Another issue is, that you cannot selectively delete an IPv4 route based
on the mss:

    ip netns del x
    ip netns add x
    IP() {
      ip netns exec x ip "$@"
    }

    IP link add type veth
    IP link set veth0 name v
    IP link set veth1 up
    IP link set v up

    IP route append 192.168.7.0/24 dev v advmss 6
    IP route append 192.168.7.0/24 dev v advmss 7

    IP -d route show dev v

    IP route delete 192.168.7.0/24 dev v advmss 7

    IP -d route show dev v

It seems for deleting routes, kernel ignores mss (which doesn't really
matter for IPv6, but does so for IPv4).
2017-08-03 18:32:59 +02:00
Thomas Haller
88da13f0b2 platform: use correct gateway for deleting route
Routes may only differ by their gateway. When deleting
a route, we must specify the exact gateway to delete.
2017-08-03 18:32:59 +02:00
Thomas Haller
a041e431da platform: use correct scope for deleting IPv4 route
Refactor _nl_msg_new_route() to obtain the route scope (rtm_scope)
from the NMPObject, instead of a separate argument.

That way, when deleting an IPv4 route, we don't pick the first route
that matches (RT_SCOPE_NOWHERE), but use the actual scope of the route
that we want to delete. That matters, if there are more then one
otherwise identical routes that only differ by their scope.

For kernel, the scope of IPv6 routes is always global
(RT_SCOPE_UNIVERSE).

Also, during ip4_route_add() initialize the intermediate @obj to have
the values as we expect them after adding the route. That is necessary
to use it in _nl_msg_new_route(). But also nicer for consistency.

Also, move the scope_inv field in NMPlatformIP4Route to let the other
in_addr_t fields life side by side.
2017-08-03 18:32:59 +02:00
Thomas Haller
5a422af0d1 platform: use proper rt_source of route for add and delete
_nl_msg_new_route() should not get extra arguments, but instead
use all parameters from the NMPObject argument. This will allow
during nm_platform_ip_route_delete() to pick the exact route
that should be deleted.

Also, in ip4_route_add()/ip6_route_add(), keep the stack-allocated
@obj object consistent with what we expect to add. That is, set
the rt_source argument to the value of what the route will have
after kernel adds it. That might be necessary, because
do_add_addrroute() searches the cache for @obj.
2017-08-03 18:32:59 +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
Thomas Haller
8d03caf599 shared: cleanup NM_CMP_*() macros 2017-07-31 15:13:31 +02:00
Thomas Haller
b9fd352eca shared: move NM_CMP_*() helper macros to shared header 2017-07-31 15:13:31 +02:00
Thomas Haller
c8f3cd51ac platform/trivial: rename cmp helper macros 2017-07-31 15:13:31 +02:00
Beniamino Galvani
3bd5a83eff platform: fix failed assertion with cloned route
platform-linux: event-notification: NEWROUTE, seq 5: fd02::2/128 via fd01::1 dev 17 metric 0 mss 0 rt-src rt-unspec src ::/0 cloned mtu 1400
NetworkManager:ERROR:src/platform/nmp-object.h:614:ASSERT_nmp_cache_ops: assertion failed: (obj_old || obj_new)

Fixes: 9440eefb6d
2017-07-31 09:51:45 +02:00
Beniamino Galvani
1dd4fec550 platform: fix IPv4 secondary address detection
If the subnet index was built without the @full_index flag, secondary
addresses are not present in the hash table.

Fixes: 5fcca9ba3e
2017-07-27 16:44:27 +02:00
Beniamino Galvani
5414239988 platform: fix IPv4 address lookup in nm_platform_ip4_address_sync()
Fixes: 5fcca9ba3e
2017-07-26 17:27:05 +02:00
Thomas Haller
459e76bdfe platform: consolidate debug logging during link-add
Don't log both in NMPlatform and NMLinuxPlatform.
Also, log all provided arguments.
2017-07-25 15:20:30 +02:00
Beniamino Galvani
81b2d77795 platform: nmp-object: fix memory leak
Fixes: 9440eefb6d
2017-07-25 09:03:54 +02:00
Thomas Haller
2861c59116 platform: pass full route object to platform delete function
Contrary to addresses, routes have no ID. When deleting a route,
you cannot just specify certain properties like network/plen,metric.

Well, actually you can specify only certain properties, but then kernel
will treat unspecified properties as wildcard and delete the first matching
route. That is not something we want, because we need to be in control which
exact route shall be deleted.

Also, rtm_tos *must* match. Even if we like the wildcard behavior,
we would need to pass TOS to nm_platform_ip4_route_delete() to be
able to delete routes with non-zero TOS. So, while certain properties
may be omitted, some must not. See how test_ip4_route_options() was
broken.

For NetworkManager it only makes ever sense to call delete on a route,
if the route is already fully known. Which means, we only delete routes
that we have already in the platform cache (otherwise, how would we know
that there is something to delete). Because of that, no longer have separate
IPv4 and IPv6 functions. Instead, have nm_platform_ip_route_delete() which
accepts a full NMPObject from the platform cache.

The code in core doesn't jet make use of this new functionality. It will
in the future.

At least, it fixes deleting routes with differing TOS.
2017-07-25 06:44:12 +02:00
Thomas Haller
5b09f7151b platform: fix return value for do_delete_object()
The return value for the delete methods checks whether the object
is actually deleted. That is questionable behavior, because if the netlink
request succeeds, there is little point in checking with the platform cache.
As it is, it is racy.

Anyway, the previous value was totally wrong.

But it also uncovers another platform bug, which currently breaks
route tests. Will be fixed next.
2017-07-25 06:44:12 +02:00
Thomas Haller
5fcca9ba3e platform: refactor nm_platform_ip4_address_sync()
To reuse array of NMPObject instances instead of creating
a GArray clone.

Also get rid of the nm_platform_ipx_address_get_all() functions.
2017-07-25 06:44:12 +02:00
Thomas Haller
22edeb5b69 core: track addresses for NMIP4Config/NMIP6Config via NMDedupMultiIndex
Reasons:

 - it adds an O(1) lookup index for accessing NMIPxConfig's addresses.
   Hence, operations like merge/intersect have now runtime O(n) instead
   of O(n^2).
   Arguably, we expect low numbers of addresses in general. For low
   numbers, the O(n^2) doesn't matter and quite likely in those cases
   the previous implementation was just fine -- maybe even faster.
   But the simple case works fine either way. It's important to scale
   well in the exceptional case.
 - the tracked objects can be shared between the various NMPI4Config,
   NMIP6Config instances with NMPlatform and everybody else.
 - the NMPObject can be treated generically, meaning it enables code to
   handle both IPv4 and IPv6, or addresses and routes. See for example
   _nm_ip_config_add_obj().
 - I want core to evolve to somewhere where we don't keep copies of
   NMPlatformIP4Address, et al. instances. Instead they shall all be
   shared. I hope this will reduce memory consumption (although tracking a
   reference consumes some memory too). Also, it shortcuts nmp_object_equal()
   when comparing the same object. Calling nmp_object_equal() on the
   identical objects would be a common case after the hash function
   pre-evaluates equality.
2017-07-25 06:44:12 +02:00
Thomas Haller
b2112ff471 platform: refactor NMPObject cast macros using _Generic()
This way, we also accept void pointers, while preserving constness.
2017-07-05 22:17:42 +02:00
Thomas Haller
06598700fe platform: refactor nm_platform_link_get_all() to return GPtrArray
Instead of doing a full clone, return a pointer array (with references
owned). The NMPlatformLink instances are now immutable.
2017-07-05 19:03:46 +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
71cf60e852 platform: refactor fake platform to use NMPCache for addresses
And move some code from NMLinuxPlatform to NMPlatform, where it belongs.

The advantage is that we reuse (and test!) the NMPCache implementation for
tracking addresses.

Also, we now always expose proper NMPObjects from both linux and fake
platform.

For example,

  obj = NMP_OBJECT_UP_CAST (nm_platform_ip4_address_get (...));

will work as expected. Also, the caller is now by NMPlatform API
allowed to take and keep a reference to the returned objects.
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
35f52aafc1 platform: drop nm_platform_ip6_route_get_all()
We no longer need a full clone of routes. The only remaining uses
are in test code. Rework it.
2017-07-05 18:37:39 +02:00
Thomas Haller
aeaa1b3b98 platform: refactor nm_dedup_multi_objs_to_ptr_array_head()
by moving the core functionality to "nm-dedup-multi.c".

As the ref-counting mechanism now is part of "nm-dedup-multi.c",
this works better and is reusable outside of platform.
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
667c50f5d9 core: avoid cloning platform routes but iterate the cache directly 2017-07-05 18:37:39 +02:00
Thomas Haller
c9cd6d9954 platform: track routes in NMFakePlatform via NMPCache
NMPlatform's cache should be directly accessible to the users,
at least the NMPLookup part and the fact that the cache contains
ref-counted, immutable NMPObjects.

This allows users to inspect the cache with zero overhead. Meaning,
they can obtain an NMDedupMultiHeadEntry and iterate the objects
themself. It also means, the are free to take and keep references
of the NMPObject instances (of course, without modifying them!).

NMFakePlatform will use the very same cache. The fake platform should
only differ when modifying the objects.

Another reason why this makes sense is because NMFakePlatform is for one
a test-stup but also tests behavior of platform itself. Using a separate
internal implementation for the caching is a pointless excecise, because
only the real NMPCache's implementation really matters for production.
So, either NMFakePlatform behaves idential, or it is buggy. Reuse it.

Port fake platform's tracking of routes to NMPCache and move duplicate
code from NMLinuxPlatform to the base class.

This commit only ports IP routes, eventually also addresses and links
should be tracked via the NMPCache instance.
2017-07-05 18:37:39 +02:00
Thomas Haller
16aefdd865 platform: expose index lookup for objects in public API 2017-07-05 18:37:39 +02:00
Thomas Haller
c5af191dbf platform: expose emit-signal function from platform
It will be used by NMFakePlatform too.
2017-07-05 18:37:39 +02:00
Thomas Haller
e160928b9e platform: move the NMPCache from linux platform to NMPlatform
We want to expose the NMPLookup and NMDedupMultiHeadEntry to the users
of NMPlatform, so that they can iterate the cache directly.

That means, NMPCache becames an integral part of NMPlatform's API
and must also be implemented by NMFakePlatform.
2017-07-05 18:37:39 +02:00
Thomas Haller
485551286c platform: add use-udev property for NMPlatform
We want to move the multi_idx from NMLinuxPlatform to NMPlatform,
so that it can be used by NMFakePlatform as well. For that, we need
to know whether NMPlatform will use udev or not. Add a constrctor
property.
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