NetworkManager/src/libnm-platform
Thomas Haller 3416b00988
platform: don't put certain rtm_protocol routes in the platform cache
We need to support systems where there are hundereds of thousand routes
(e.g. BGP software).

For that, we will ignore routes that have a rtm_protocol value which was
certainly not created by NetworkManager. Before we had a BPF filer to
filter them out, but that had issues and is removed for now. Still,
don't put those routes in the platform cache and ignore them early.

Note that we still deserialize the RTM_NEWROUTE message to a NMPObject,
and don't shortcut earlier. The reason is that we should still call
delayed_action_refresh_all_in_progress() and handle the RTM_GETROUTE
response, even if the route has a different protocol. So we error out
later, shortly before putting the object in the cache. This means we
will malloc() a NMPObject and initialize it, but that is probably cheap,
compared to the first problem that the process already had to wake up
and read the netlink socket.

This restores the effective behavior of the BPF filter, albeit with a
higher overhead, as the route is rejected later. The important part for
now is that we stick to the behavior of not caching certain routes of a
certain protocol. If that can in the future be optimized (e.g. by a new
BPF filter), then we should do that. But for now that would be only a
future performance improvement, which requires new profiling first and
that has not the highest priority. Note that not caching certain routes
already should reduce the largest part of the overhead that those routes
brings. Whether this form is sufficient to reach the expected
performance goals, needs to be measured in the future.
2022-01-20 10:30:34 +01:00
..
tests platform: clear all BASE types when setting advertised modes for ethernet autoneg 2021-09-06 10:07:15 +02:00
wifi format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
wpan format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
meson.build platform: move more platform code to src/libnm-platform/ 2021-03-05 11:27:16 +01:00
nm-linux-platform.c platform: don't put certain rtm_protocol routes in the platform cache 2022-01-20 10:30:34 +01:00
nm-linux-platform.h platform: allow disabling caching of tc objects 2021-09-20 13:27:16 +02:00
nm-netlink.c Revert "platform: add bpf filter to ignore routes from routing daemons" 2022-01-20 10:30:30 +01:00
nm-netlink.h Revert "platform: add bpf filter to ignore routes from routing daemons" 2022-01-20 10:30:30 +01:00
nm-platform-private.h format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
nm-platform-utils.c format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
nm-platform-utils.h format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
nm-platform.c core: set force-commit flag for generated routes 2022-01-12 15:01:42 +01:00
nm-platform.h core: set force-commit flag for generated routes 2022-01-12 15:01:42 +01:00
nmp-base.h ethtool: Introducing PAUSE support 2021-05-12 18:04:46 +02:00
nmp-netns.c format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
nmp-netns.h build: move "shared/nm-platform" to "src/libnm-platform" 2021-02-24 12:48:17 +01:00
nmp-object.c format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
nmp-object.h format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
nmp-rules-manager.c format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
nmp-rules-manager.h format: reformat source tree with clang-format 13.0 2021-11-29 09:31:09 +00:00
README.md platform/readme: detail problem about IPv6 multihop routes 2022-01-18 12:00:02 +01:00

libnm-platform

A static helper library that provides NMPlatform and other utils. This is NetworkManager's internal netlink library, but also contains helpers for sysfs, ethtool and other kernel APIs.

NMPlaform is also a cache of objects of the netlink API: NMPCache and NMPObject. These objects are used throughout NetworkManager also for generally tracking information about these types. For example, NMPlatformIP4Address (the public part of a certain type of NMPObject) is not only used to track platform addresses from netlink in the cache, but to track information about IPv4 addresses in general.

This depends on the following helper libraries

TODO and Bugs

IPv6 Multi-hop Routes

NMPlatform has a cache (dictionary) with netlink objects, which can also be augmented with additional information like the WifiData or the udev device. A dictionary requires that objects have an identity, which they can be compared and hash. In other words, a set of properties that determines that the object is something distinctly recognizable.

Route routes and routing policy routes, from point of view of kernel there is not a simple set of properties/attributes that determine the identity of the route/rule. Rather, most attributes are part of the ID, but not all. See NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID and NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID.

For routes, we currently ignore all multi-hop routes (ECMP). For IPv4, that is fine because kernel also treats the next hops (of any number) to be the part of the ID of a route. For example, you can see in ip route two IPv4 routes that only differ by their next-hops. As NetworkManager currently doesn't configure multi-hop routes, ignoring those routes and not caching them is no problem.

For IPv6 routes that is different. When you add two IPv6 routes that only differ by their next hops, then kernel will merge them into a multi-hop route (as you can see in ip -6 route). Likewise, if you remove a (single or multi-hop) route, then kernel will "subtract" those hops from the multi-hop route. In a way, kernel always mangles the result into a multi-hop route. If you logically consider the hops of an IPv6 part of the identity of a route, then adding a route, can create a new (because distinct as by their ID) route while removing the previously existing route (without sending a RTM_DELROUTE message). As NetworkManager currently ignores all multi-hop routes, this easily leads to an inconsistent cache, because NetworkManager does not understand that the addition/removal of an IPv6 route, interferes with an entirely different route (from point of view of the identity). So you could say the problem is that the ID of a route changes (by merging the next hops). But that makes no sense, because the ID identifies the route, it cannot change without creating a different route. So the alternative to see this problem is that adding a route can create a different route and deleting the previous one, but there are not sufficient netlink events to understand which route got mangled (short of searching the cache). But also, the RTM_NEWROUTE command no longer necessarily results in the addition of the route we requested and a RTM_DELROUTE event does not necessarily notify about the route that was removed (rather, it notifies about the part that got subtracted).

Another way to see kernel's bogus behavior is to pretend that there are only single-hop routes. That makes everything simple, the only speciality is that a RTM_NEWROUTE now can contain (with this point of view of the identity) multiple routes, one for each hop.

To solve the problem of platform cache inconsistencies for IPv6 routes, NetworkManager should only honor IPv6 single-path routes, but with the twist that one RTM_NEWROUTE can announce multiple routes at once.

This alternative view that we should implement is possibly a deviation from kernel's view. Usually we avoid modelling things differently than kernel, but in this case it makes more sense as this is more how it appears on the netlink API (based on the events that we get).

See also: https://bugzilla.redhat.com/show_bug.cgi?id=1837254#c20