From f9fe2155991c37be5a6ab7b51ff27285cfed04c1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 17 Apr 2019 09:17:51 +0200 Subject: [PATCH] platform: compare routing rules according to kernel support for FRA_PROTOCOL For routes and routing rules, kernel uses a certain (not stictly defined) set of attributes to decide whether to routes/rules are identical. That is a problem, as different kernel versions disagree on whether two routes/rules are the same (EEXIST) or not. Note that when NetworkManager tries to add a rule with protocol set to anything but RTPROT_UNSPEC, then kernel will ignore the attribute if it doesn't have support for it. Meaning: the added rule will have a different protocol setting then intended. Note that NMPRulesManager will add a rule if it doesn't find it in the platform cache so far. That means, when looking into the platform cache we must ignore or honor the protocol like kernel does. This does not only affect FRA_PROTOCOL, but all attributes where kernel and NetworkManager disagrees. But the protocol is the most prominent one, because the rules tracked by nmp_rules_manager_track_default() specify the protocol. (cherry picked from commit ef4f8ccf6dc7d9ed1d02321d1e5c72ad1580ea5c) --- src/platform/nm-platform.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 922804a4b..cb69c6fab 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -7405,6 +7405,10 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route | FIB_RULE_IIF_DETACHED \ | FIB_RULE_OIF_DETACHED) +#define _routing_rule_compare(cmp_type, kernel_support_type) \ + ( (cmp_type) == NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL \ + || nm_platform_kernel_support_get (kernel_support_type)) + void nm_platform_routing_rule_hash_update (const NMPlatformRoutingRule *obj, NMPlatformRoutingRuleCmpType cmp_type, @@ -7435,7 +7439,6 @@ nm_platform_routing_rule_hash_update (const NMPlatformRoutingRule *obj, /* fall-through */ case NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL: - nm_hash_update_vals (h, obj->addr_family, obj->tun_id, @@ -7464,7 +7467,10 @@ nm_platform_routing_rule_hash_update (const NMPlatformRoutingRule *obj, obj->tos, obj->src_len, obj->dst_len, - obj->protocol, + ( _routing_rule_compare (cmp_type, + NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL) + ? (guint16) obj->protocol + : G_MAXUINT16), obj->ip_proto); addr_size = nm_utils_addr_family_to_size (obj->addr_family); if (cmp_full || obj->src_len > 0) @@ -7550,7 +7556,10 @@ nm_platform_routing_rule_cmp (const NMPlatformRoutingRule *a, if (cmp_full || a->addr_family == AF_INET) NM_CMP_FIELD (a, b, flow); - NM_CMP_FIELD (a, b, protocol); + if (_routing_rule_compare (cmp_type, + NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL)) + NM_CMP_FIELD (a, b, protocol); + NM_CMP_FIELD (a, b, ip_proto); addr_size = nm_utils_addr_family_to_size (a->addr_family);