mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 09:00:21 +01:00
platform: support setting the nexthop in routes
This commit is contained in:
parent
6f154c1500
commit
00aa445226
3 changed files with 73 additions and 31 deletions
|
|
@ -4066,6 +4066,7 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter
|
|||
[RTA_PRIORITY] = {.type = NLA_U32},
|
||||
[RTA_PREF] = {.type = NLA_U8},
|
||||
[RTA_FLOW] = {.type = NLA_U32},
|
||||
[RTA_NH_ID] = {.type = NLA_U32},
|
||||
[RTA_CACHEINFO] = {.minlen = nm_offsetofend(struct rta_cacheinfo, rta_tsage)},
|
||||
[RTA_VIA] = {.minlen = nm_offsetofend(struct rtvia, rtvia_family)},
|
||||
[RTA_METRICS] = {.type = NLA_NESTED},
|
||||
|
|
@ -4103,6 +4104,7 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter
|
|||
guint32 mtu = 0;
|
||||
guint32 rto_min = 0;
|
||||
guint32 lock = 0;
|
||||
guint32 nhid = 0;
|
||||
gboolean quickack = FALSE;
|
||||
gboolean rto_min_set = FALSE;
|
||||
|
||||
|
|
@ -4148,7 +4150,7 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter
|
|||
if (rtm->rtm_dst_len > (IS_IPv4 ? 32 : 128))
|
||||
return NULL;
|
||||
|
||||
if (tb[RTA_MULTIPATH]) {
|
||||
if (!tb[RTA_NH_ID] && tb[RTA_MULTIPATH]) {
|
||||
size_t tlen;
|
||||
struct rtnexthop *rtnh;
|
||||
guint idx;
|
||||
|
|
@ -4257,7 +4259,7 @@ rta_multipath_done:
|
|||
return nm_assert_unreachable_val(NULL);
|
||||
}
|
||||
|
||||
if (tb[RTA_OIF] || tb[RTA_GATEWAY] || tb[RTA_FLOW] || tb[RTA_VIA]) {
|
||||
if (!tb[RTA_NH_ID] && (tb[RTA_OIF] || tb[RTA_GATEWAY] || tb[RTA_FLOW] || tb[RTA_VIA])) {
|
||||
int ifindex = 0;
|
||||
NMIPAddr gateway = {};
|
||||
|
||||
|
|
@ -4303,6 +4305,10 @@ rta_multipath_done:
|
|||
}
|
||||
}
|
||||
|
||||
if (tb[RTA_NH_ID]) {
|
||||
nhid = nla_get_u32(tb[RTA_NH_ID]);
|
||||
}
|
||||
|
||||
if (nm_platform_route_type_is_nodev(rtm->rtm_type)) {
|
||||
/* These routes are special. They don't have an device/ifindex.
|
||||
*
|
||||
|
|
@ -4439,6 +4445,9 @@ rta_multipath_done:
|
|||
obj->ip6_route.src_plen = rtm->rtm_src_len;
|
||||
}
|
||||
|
||||
if (!IS_IPv4)
|
||||
obj->ip6_route.nhid = nhid;
|
||||
|
||||
obj->ip_route.mss = mss;
|
||||
obj->ip_route.window = window;
|
||||
obj->ip_route.cwnd = cwnd;
|
||||
|
|
@ -5982,10 +5991,14 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob
|
|||
NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip4_route.gateway);
|
||||
}
|
||||
} else {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&obj->ip6_route.gateway))
|
||||
if (obj->ip6_route.nhid != 0) {
|
||||
NLA_PUT_U32(msg, RTA_NH_ID, obj->ip6_route.nhid);
|
||||
} else if (!IN6_IS_ADDR_UNSPECIFIED(&obj->ip6_route.gateway))
|
||||
NLA_PUT(msg, RTA_GATEWAY, addr_len, &obj->ip6_route.gateway);
|
||||
}
|
||||
NLA_PUT_U32(msg, RTA_OIF, obj->ip_route.ifindex);
|
||||
|
||||
if (IS_IPv4 || obj->ip6_route.nhid == 0)
|
||||
NLA_PUT_U32(msg, RTA_OIF, obj->ip_route.ifindex);
|
||||
|
||||
if (!IS_IPv4 && obj->ip6_route.rt_pref != NM_ICMPV6_ROUTER_PREF_MEDIUM)
|
||||
NLA_PUT_U8(msg, RTA_PREF, obj->ip6_route.rt_pref);
|
||||
|
|
|
|||
|
|
@ -7521,33 +7521,37 @@ nm_platform_ip6_nexthop_to_string(const NMPlatformIP6NextHop *nexthop, char *buf
|
|||
const char *
|
||||
nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsize len)
|
||||
{
|
||||
char s_network[INET6_ADDRSTRLEN];
|
||||
char s_gateway[INET6_ADDRSTRLEN];
|
||||
char s_pref_src[INET6_ADDRSTRLEN];
|
||||
char s_src_all[INET6_ADDRSTRLEN + 40];
|
||||
char s_src[INET6_ADDRSTRLEN];
|
||||
char str_type[30];
|
||||
char str_table[30];
|
||||
char str_pref[40];
|
||||
char str_pref2[30];
|
||||
char str_dev[30];
|
||||
char str_mss[32];
|
||||
char s_source[50];
|
||||
char str_window[32];
|
||||
char str_cwnd[32];
|
||||
char str_initcwnd[32];
|
||||
char str_initrwnd[32];
|
||||
char str_rto_min[32];
|
||||
char str_mtu[32];
|
||||
char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN];
|
||||
char str_metric[30];
|
||||
char s_network[INET6_ADDRSTRLEN];
|
||||
char s_gateway[INET6_ADDRSTRLEN];
|
||||
char s_pref_src[INET6_ADDRSTRLEN];
|
||||
char s_src_all[INET6_ADDRSTRLEN + 40];
|
||||
char s_src[INET6_ADDRSTRLEN];
|
||||
char str_type[30];
|
||||
char str_table[30];
|
||||
char str_pref[40];
|
||||
char str_pref2[30];
|
||||
char str_dev[30];
|
||||
char str_mss[32];
|
||||
char s_source[50];
|
||||
char str_window[32];
|
||||
char str_cwnd[32];
|
||||
char str_initcwnd[32];
|
||||
char str_initrwnd[32];
|
||||
char str_rto_min[32];
|
||||
char str_mtu[32];
|
||||
char str_rtm_flags[_RTM_FLAGS_TO_STRING_MAXLEN];
|
||||
char str_metric[30];
|
||||
gboolean has_nhid = FALSE;
|
||||
|
||||
if (!nm_utils_to_string_buffer_init_null(route, &buf, &len))
|
||||
return buf;
|
||||
|
||||
inet_ntop(AF_INET6, &route->network, s_network, sizeof(s_network));
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&route->gateway))
|
||||
if (route->nhid) {
|
||||
g_snprintf(s_gateway, sizeof(s_gateway), " nhid %u", route->nhid);
|
||||
has_nhid = TRUE;
|
||||
} else if (IN6_IS_ADDR_UNSPECIFIED(&route->gateway))
|
||||
s_gateway[0] = '\0';
|
||||
else
|
||||
inet_ntop(AF_INET6, &route->gateway, s_gateway, sizeof(s_gateway));
|
||||
|
|
@ -7591,7 +7595,7 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
|
|||
: ""),
|
||||
s_network,
|
||||
route->plen,
|
||||
s_gateway[0] ? " via " : "",
|
||||
!has_nhid && s_gateway[0] ? " via " : "",
|
||||
s_gateway,
|
||||
_to_string_dev(str_dev, route->ifindex),
|
||||
route->metric_any
|
||||
|
|
@ -9353,6 +9357,7 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj,
|
|||
*nm_ip6_addr_clear_host_address(&a1, &obj->network, obj->plen),
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
obj->nhid,
|
||||
*nm_ip6_addr_clear_host_address(&a2, &obj->src, obj->src_plen),
|
||||
obj->src_plen,
|
||||
NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any));
|
||||
|
|
@ -9368,12 +9373,13 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj,
|
|||
*nm_ip6_addr_clear_host_address(&a1, &obj->network, obj->plen),
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
obj->nhid,
|
||||
*nm_ip6_addr_clear_host_address(&a2, &obj->src, obj->src_plen),
|
||||
obj->src_plen,
|
||||
NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any),
|
||||
/* on top of WEAK_ID: */
|
||||
obj->ifindex,
|
||||
obj->gateway);
|
||||
obj->nhid == 0 ? obj->gateway : in6addr_any);
|
||||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
nm_hash_update_vals(
|
||||
|
|
@ -9384,7 +9390,8 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj,
|
|||
*nm_ip6_addr_clear_host_address(&a1, &obj->network, obj->plen),
|
||||
obj->plen,
|
||||
obj->metric,
|
||||
obj->gateway,
|
||||
obj->nhid,
|
||||
obj->nhid == 0 ? obj->gateway : in6addr_any,
|
||||
obj->pref_src,
|
||||
*nm_ip6_addr_clear_host_address(&a2, &obj->src, obj->src_plen),
|
||||
obj->src_plen,
|
||||
|
|
@ -9416,7 +9423,8 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj,
|
|||
obj->ifindex,
|
||||
obj->network,
|
||||
obj->metric,
|
||||
obj->gateway,
|
||||
obj->nhid,
|
||||
obj->nhid == 0 ? obj->gateway : in6addr_any,
|
||||
obj->pref_src,
|
||||
obj->src,
|
||||
obj->src_plen,
|
||||
|
|
@ -9463,12 +9471,15 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a,
|
|||
NM_CMP_FIELD(a, b, plen);
|
||||
NM_CMP_FIELD_UNSAFE(a, b, metric_any);
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_FIELD(a, b, nhid);
|
||||
NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->src, &b->src, NM_MIN(a->src_plen, b->src_plen));
|
||||
NM_CMP_FIELD(a, b, src_plen);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) {
|
||||
NM_CMP_FIELD(a, b, ifindex);
|
||||
NM_CMP_FIELD(a, b, type_coerced);
|
||||
NM_CMP_FIELD_IN6ADDR(a, b, gateway);
|
||||
if (a->nhid == 0) {
|
||||
NM_CMP_FIELD_IN6ADDR(a, b, gateway);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY:
|
||||
|
|
@ -9488,7 +9499,10 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a,
|
|||
NM_CMP_FIELD(a, b, plen);
|
||||
NM_CMP_FIELD_UNSAFE(a, b, metric_any);
|
||||
NM_CMP_FIELD(a, b, metric);
|
||||
NM_CMP_FIELD_IN6ADDR(a, b, gateway);
|
||||
NM_CMP_FIELD(a, b, nhid);
|
||||
if (a->nhid == 0) {
|
||||
NM_CMP_FIELD_IN6ADDR(a, b, gateway);
|
||||
}
|
||||
NM_CMP_FIELD_IN6ADDR(a, b, pref_src);
|
||||
if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) {
|
||||
NM_CMP_DIRECT_IP6_ADDR_SAME_PREFIX(&a->src, &b->src, NM_MIN(a->src_plen, b->src_plen));
|
||||
|
|
|
|||
|
|
@ -533,6 +533,21 @@ struct _NMPlatformIP6Route {
|
|||
* The type is guint8 to keep the struct size small. But the values are compatible with
|
||||
* the NMIcmpv6RouterPref enum. */
|
||||
guint8 rt_pref;
|
||||
|
||||
/* RTA_NH_ID. The unique id of the nexthop object.
|
||||
*
|
||||
* When sending a route with a nexthop to the kernel, the ifindex
|
||||
* and gateway must be unset, otherwise the route will be
|
||||
* rejected. When the kernel sends notifications to userspace it
|
||||
* copies the ifindex and the gateway from the nexthop into the
|
||||
* route.
|
||||
*
|
||||
* In a route platform object, the ifindex and gateway are ignored
|
||||
* if the routes has a nexthop. The ifindex must be always set
|
||||
* when creating new synthetic route because the platform code
|
||||
* needs it to properly track the object.
|
||||
*/
|
||||
guint32 nhid;
|
||||
} _nm_alignas(NMPlatformObject);
|
||||
|
||||
typedef union {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue