diff options
author | Thomas Haller <thaller@redhat.com> | 2019-04-17 09:17:51 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-04-18 11:14:07 +0200 |
commit | ef4f8ccf6dc7d9ed1d02321d1e5c72ad1580ea5c (patch) | |
tree | 715130c5ceb76197d51d71e67bb53778af976e3e | |
parent | eba4fd56f5fa5e03fb854fb91874496b15ebc2e4 (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.c | 15 |
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); |