summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-04-17 09:17:51 +0200
committerThomas Haller <thaller@redhat.com>2019-04-18 11:14:07 +0200
commitef4f8ccf6dc7d9ed1d02321d1e5c72ad1580ea5c (patch)
tree715130c5ceb76197d51d71e67bb53778af976e3e
parenteba4fd56f5fa5e03fb854fb91874496b15ebc2e4 (diff)
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.
-rw-r--r--src/platform/nm-platform.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 922804a4b9..cb69c6fabe 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);