summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-10-09 11:09:16 +0200
committerThomas Haller <thaller@redhat.com>2017-10-12 10:38:19 +0200
commit37ffc8bae9688a2a6fb98c118e194f17267cff96 (patch)
treec6b4a8aa1a6c2c2dcba6bd835115d03c92f6467f
parent5b0745e7bd77b5b4dcd2a2061820fe2e80615ba8 (diff)
downloadNetworkManager-37ffc8bae9688a2a6fb98c118e194f17267cff96.tar.gz
platform: support pref option for IPv6 routes (RTA_PREF)
Support IPv6 router preference (RFC4191) in platform code.
-rw-r--r--src/platform/nm-linux-platform.c14
-rw-r--r--src/platform/nm-platform.c24
-rw-r--r--src/platform/nm-platform.h6
3 files changed, 43 insertions, 1 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index f7ce9851aa..f53019df34 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -104,6 +104,11 @@
#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
#endif
+G_STATIC_ASSERT (RTA_MAX == (__RTA_MAX - 1));
+#define RTA_PREF 20
+#undef RTA_MAX
+#define RTA_MAX (MAX ((__RTA_MAX - 1), RTA_PREF))
+
#ifndef MACVLAN_FLAG_NOPROMISC
#define MACVLAN_FLAG_NOPROMISC 1
#endif
@@ -2020,6 +2025,7 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
[RTA_IIF] = { .type = NLA_U32 },
[RTA_OIF] = { .type = NLA_U32 },
[RTA_PRIORITY] = { .type = NLA_U32 },
+ [RTA_PREF] = { .type = NLA_U8 },
[RTA_FLOW] = { .type = NLA_U32 },
[RTA_CACHEINFO] = { .minlen = nm_offsetofend (struct rta_cacheinfo, rta_tsage) },
[RTA_METRICS] = { .type = NLA_NESTED },
@@ -2224,6 +2230,10 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
obj->ip_route.lock_initrwnd = NM_FLAGS_HAS (lock, 1 << RTAX_INITRWND);
obj->ip_route.lock_mtu = NM_FLAGS_HAS (lock, 1 << RTAX_MTU);
+ if ( !is_v4
+ && tb[RTA_PREF])
+ obj->ip6_route.rt_pref = nla_get_u8 (tb[RTA_PREF]);
+
if (NM_FLAGS_HAS (rtm->rtm_flags, RTM_F_CLONED)) {
/* we must not straight way reject cloned routes, because we might have cached
* a non-cloned route. If we now receive an update of the route with the route
@@ -2719,6 +2729,10 @@ _nl_msg_new_route (int nlmsg_type,
}
NLA_PUT_U32 (msg, RTA_OIF, obj->ip_route.ifindex);
+ if ( !is_v4
+ && obj->ip6_route.rt_pref != NM_ICMPV6_ROUTER_PREF_MEDIUM)
+ NLA_PUT_U8 (msg, RTA_PREF, obj->ip6_route.rt_pref);
+
return msg;
nla_put_failure:
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 222b68f8e0..c04d4f85d3 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -3873,6 +3873,16 @@ _ip_route_scope_inv_get_normalized (const NMPlatformIP4Route *route)
return route->scope_inv;
}
+static guint8
+_route_pref_normalize (guint8 pref)
+{
+ /* for kernel (and ICMPv6) pref can only have one of 3 values. Normalize. */
+ return NM_IN_SET (pref, NM_ICMPV6_ROUTER_PREF_LOW,
+ NM_ICMPV6_ROUTER_PREF_HIGH)
+ ? pref
+ : NM_ICMPV6_ROUTER_PREF_MEDIUM;
+}
+
/**
* nm_platform_ip_route_normalize:
* @addr_family: AF_INET or AF_INET6
@@ -5053,6 +5063,8 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN], s_pref_src[INET6_ADDRSTRLEN];
char s_src_all[INET6_ADDRSTRLEN + 40], s_src[INET6_ADDRSTRLEN];
char str_table[30];
+ char str_pref[40];
+ char str_pref2[30];
char str_dev[TO_STRING_DEV_BUF_SIZE], s_source[50];
char str_window[32], str_cwnd[32], str_initcwnd[32], str_initrwnd[32], str_mtu[32];
@@ -5085,6 +5097,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
"%s" /* initcwnd */
"%s" /* initrwnd */
"%s" /* mtu */
+ "%s" /* pref */
"",
route->table_coerced ? nm_sprintf_buf (str_table, "table %u ", nm_platform_route_table_uncoerce (route->table_coerced, FALSE)) : "",
s_network,
@@ -5104,7 +5117,8 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
route->cwnd || route->lock_cwnd ? nm_sprintf_buf (str_cwnd, " cwnd %s%"G_GUINT32_FORMAT, route->lock_cwnd ? "lock " : "", route->cwnd) : "",
route->initcwnd || route->lock_initcwnd ? nm_sprintf_buf (str_initcwnd, " initcwnd %s%"G_GUINT32_FORMAT, route->lock_initcwnd ? "lock " : "", route->initcwnd) : "",
route->initrwnd || route->lock_initrwnd ? nm_sprintf_buf (str_initrwnd, " initrwnd %s%"G_GUINT32_FORMAT, route->lock_initrwnd ? "lock " : "", route->initrwnd) : "",
- route->mtu || route->lock_mtu ? nm_sprintf_buf (str_mtu, " mtu %s%"G_GUINT32_FORMAT, route->lock_mtu ? "lock " : "", route->mtu) : "");
+ route->mtu || route->lock_mtu ? nm_sprintf_buf (str_mtu, " mtu %s%"G_GUINT32_FORMAT, route->lock_mtu ? "lock " : "", route->mtu) : "",
+ route->rt_pref ? nm_sprintf_buf (str_pref, " pref %s", nm_icmpv6_router_pref_to_string (route->rt_pref, str_pref2, sizeof (str_pref2))) : "");
return buf;
}
@@ -5730,6 +5744,10 @@ nm_platform_ip6_route_hash (const NMPlatformIP6Route *obj, NMPlatformIPRouteCmpT
h = NM_HASH_COMBINE (h, obj->initcwnd);
h = NM_HASH_COMBINE (h, obj->initrwnd);
h = NM_HASH_COMBINE (h, obj->mtu);
+ if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
+ h = NM_HASH_COMBINE (h, _route_pref_normalize (obj->rt_pref));
+ else
+ h = NM_HASH_COMBINE (h, obj->rt_pref);
break;
}
}
@@ -5796,6 +5814,10 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
NM_CMP_FIELD (a, b, initcwnd);
NM_CMP_FIELD (a, b, initrwnd);
NM_CMP_FIELD (a, b, mtu);
+ if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY)
+ NM_CMP_DIRECT (_route_pref_normalize (a->rt_pref), _route_pref_normalize (b->rt_pref));
+ else
+ NM_CMP_FIELD (a, b, rt_pref);
break;
}
return 0;
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 3d6e5bf7f5..845d79b140 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -517,6 +517,12 @@ struct _NMPlatformIP6Route {
*/
struct in6_addr src;
guint8 src_plen;
+
+ /* RTA_PREF router preference.
+ *
+ * The type is guint8 to keep the struct size small. But the values are compatible with
+ * the NMIcmpv6RouterPref enum. */
+ guint8 rt_pref;
};
typedef union {