diff options
author | Thomas Haller <thaller@redhat.com> | 2017-10-09 11:09:16 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-10-12 10:38:19 +0200 |
commit | 37ffc8bae9688a2a6fb98c118e194f17267cff96 (patch) | |
tree | c6b4a8aa1a6c2c2dcba6bd835115d03c92f6467f /src | |
parent | 5b0745e7bd77b5b4dcd2a2061820fe2e80615ba8 (diff) | |
download | NetworkManager-37ffc8bae9688a2a6fb98c118e194f17267cff96.tar.gz |
platform: support pref option for IPv6 routes (RTA_PREF)
Support IPv6 router preference (RFC4191) in platform code.
Diffstat (limited to 'src')
-rw-r--r-- | src/platform/nm-linux-platform.c | 14 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 24 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 6 |
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 { |