diff options
| author | Michael Biebl <biebl@debian.org> | 2026-05-14 19:21:22 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2026-05-14 19:21:22 +0200 |
| commit | 869e9027026cdbb15d4e4a6327ff41d2697858eb (patch) | |
| tree | 52edec7f935ff1bbb425c3515c6e49e6b8b0e28b /src/libnm-platform/nm-linux-platform.c | |
| parent | 067fb576988f685e83ac8b0ae690334aff547c85 (diff) | |
New upstream version 1.56.1 upstream/1.56.1
Diffstat (limited to 'src/libnm-platform/nm-linux-platform.c')
| -rw-r--r-- | src/libnm-platform/nm-linux-platform.c | 131 |
1 files changed, 116 insertions, 15 deletions
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c index cc5b99e0..b5df8b17 100644 --- a/src/libnm-platform/nm-linux-platform.c +++ b/src/libnm-platform/nm-linux-platform.c @@ -862,6 +862,7 @@ static const LinkDesc link_descs[] = { [NM_LINK_TYPE_BNEP] = {"bluetooth", NULL, "bluetooth"}, [NM_LINK_TYPE_DUMMY] = {"dummy", "dummy", NULL}, + [NM_LINK_TYPE_GENEVE] = {"geneve", "geneve", "geneve"}, [NM_LINK_TYPE_GRE] = {"gre", "gre", NULL}, [NM_LINK_TYPE_GRETAP] = {"gretap", "gretap", NULL}, [NM_LINK_TYPE_IFB] = {"ifb", "ifb", NULL}, @@ -909,6 +910,7 @@ _link_type_from_rtnl_type(const char *name) NM_LINK_TYPE_BOND, /* "bond" */ NM_LINK_TYPE_BRIDGE, /* "bridge" */ NM_LINK_TYPE_DUMMY, /* "dummy" */ + NM_LINK_TYPE_GENEVE, /* "geneve" */ NM_LINK_TYPE_GRE, /* "gre" */ NM_LINK_TYPE_GRETAP, /* "gretap" */ NM_LINK_TYPE_HSR, /* "hsr" */ @@ -987,6 +989,7 @@ _link_type_from_devtype(const char *name) NM_LINK_TYPE_BNEP, /* "bluetooth" */ NM_LINK_TYPE_BOND, /* "bond" */ NM_LINK_TYPE_BRIDGE, /* "bridge" */ + NM_LINK_TYPE_GENEVE, /* "geneve" */ NM_LINK_TYPE_HSR, /* "hsr" */ NM_LINK_TYPE_PPP, /* "ppp" */ NM_LINK_TYPE_VLAN, /* "vlan" */ @@ -1857,6 +1860,57 @@ _parse_lnk_gre(const char *kind, struct nlattr *info_data) /*****************************************************************************/ static NMPObject * +_parse_lnk_geneve(const char *kind, struct nlattr *info_data) +{ + static const struct nla_policy policy[] = { + [IFLA_GENEVE_ID] = {.type = NLA_U32}, + [IFLA_GENEVE_REMOTE] = {.type = NLA_U32}, + [IFLA_GENEVE_REMOTE6] = {.type = NLA_UNSPEC, .minlen = sizeof(struct in6_addr)}, + [IFLA_GENEVE_TTL] = {.type = NLA_U8}, + [IFLA_GENEVE_TOS] = {.type = NLA_U8}, + [IFLA_GENEVE_TTL_INHERIT] = {.type = NLA_U8}, + [IFLA_GENEVE_PORT] = {.type = NLA_U16}, + [IFLA_GENEVE_DF] = {.type = NLA_U8}, + }; + + struct nlattr *tb[G_N_ELEMENTS(policy)]; + NMPObject *obj; + NMPlatformLnkGeneve *props; + + if (!info_data || !nm_streq0(kind, "geneve")) + return NULL; + + if (nla_parse_nested_arr(tb, info_data, policy) < 0) + return NULL; + + obj = nmp_object_new(NMP_OBJECT_TYPE_LNK_GENEVE, NULL); + props = &obj->lnk_geneve; + + if (tb[IFLA_GENEVE_ID]) + props->id = nla_get_u32(tb[IFLA_GENEVE_ID]); + if (tb[IFLA_GENEVE_REMOTE]) + props->remote = nla_get_u32(tb[IFLA_GENEVE_REMOTE]); + if (tb[IFLA_GENEVE_REMOTE6]) + props->remote6 = *nla_data_as(struct in6_addr, tb[IFLA_GENEVE_REMOTE6]); + + if (tb[IFLA_GENEVE_TTL_INHERIT] && nla_get_u8(tb[IFLA_GENEVE_TTL_INHERIT])) + props->ttl = -1; + else if (tb[IFLA_GENEVE_TTL]) + props->ttl = nla_get_u8(tb[IFLA_GENEVE_TTL]); + + if (tb[IFLA_GENEVE_TOS]) + props->tos = nla_get_u8(tb[IFLA_GENEVE_TOS]); + if (tb[IFLA_GENEVE_PORT]) + props->dst_port = ntohs(nla_get_u16(tb[IFLA_GENEVE_PORT])); + if (tb[IFLA_GENEVE_DF]) + props->df = nla_get_u8(tb[IFLA_GENEVE_DF]); + + return obj; +} + +/*****************************************************************************/ + +static NMPObject * _parse_lnk_hsr(const char *kind, struct nlattr *info_data) { static const struct nla_policy policy[] = { @@ -3694,6 +3748,9 @@ _new_from_nl_link(NMPlatform *platform, case NM_LINK_TYPE_BOND: lnk_data = _parse_lnk_bond(nl_info_kind, nl_info_data); break; + case NM_LINK_TYPE_GENEVE: + lnk_data = _parse_lnk_geneve(nl_info_kind, nl_info_data); + break; case NM_LINK_TYPE_GRE: case NM_LINK_TYPE_GRETAP: lnk_data = _parse_lnk_gre(nl_info_kind, nl_info_data); @@ -4033,6 +4090,7 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter int ifindex; NMIPAddr gateway; gboolean is_via; + unsigned rtnh_flags; } nh = { .found = FALSE, .has_more = FALSE, @@ -4142,9 +4200,10 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter v4_nh_extra_nexthops = v4_nh_extra_nexthops_heap; } nm_assert(v4_n_nexthops - 1u < v4_nh_extra_alloc); - new_nexthop = &v4_nh_extra_nexthops[v4_n_nexthops - 1u]; - new_nexthop->ifindex = rtnh->rtnh_ifindex; - new_nexthop->weight = NM_MAX(((guint) rtnh->rtnh_hops) + 1u, 1u); + new_nexthop = &v4_nh_extra_nexthops[v4_n_nexthops - 1u]; + new_nexthop->ifindex = rtnh->rtnh_ifindex; + new_nexthop->weight = NM_MAX(((guint) rtnh->rtnh_hops) + 1u, 1u); + new_nexthop->rtnh_flags = rtnh->rtnh_flags; if (rtnh->rtnh_len > sizeof(*rtnh)) { struct nlattr *ntb[RTA_MAX + 1]; @@ -4159,9 +4218,10 @@ _new_from_nl_route(const struct nlmsghdr *nlh, gboolean id_only, ParseNlmsgIter memcpy(&new_nexthop->gateway, nla_data(ntb[RTA_GATEWAY]), addr_len); } } else if (IS_IPv4 || idx == multihop_idx) { - nh.found = TRUE; - nh.ifindex = rtnh->rtnh_ifindex; - nh.weight = NM_MAX(((guint) rtnh->rtnh_hops) + 1u, 1u); + nh.found = TRUE; + nh.ifindex = rtnh->rtnh_ifindex; + nh.weight = NM_MAX(((guint) rtnh->rtnh_hops) + 1u, 1u); + nh.rtnh_flags = rtnh->rtnh_flags; if (rtnh->rtnh_len > sizeof(*rtnh)) { struct nlattr *ntb[RTA_MAX + 1]; @@ -4409,7 +4469,16 @@ rta_multipath_done: } obj->ip_route.r_rtm_flags = rtm->rtm_flags; - obj->ip_route.rt_source = nmp_utils_ip_config_source_from_rtprot(rtm->rtm_protocol); + + if (IS_IPv4 && v4_n_nexthops > 1u) { + /* For multipath routes, rtm_flags at the route level does not contain + * RTNH_F_ONLINK. Instead, each nexthop has its own rtnh_flags. Merge the + * first nexthop's RTNH_F_ONLINK into r_rtm_flags, since the first nexthop + * is embedded in the route struct. */ + obj->ip_route.r_rtm_flags |= (nh.rtnh_flags & RTNH_F_ONLINK); + } + + obj->ip_route.rt_source = nmp_utils_ip_config_source_from_rtprot(rtm->rtm_protocol); if (nh.has_more) { parse_nlmsg_iter->iter_more = TRUE; @@ -5182,6 +5251,35 @@ _nl_msg_new_link_set_linkinfo(struct nl_msg *msg, NMLinkType link_type, gconstpo nla_nest_end(msg, info_peer); break; } + case NM_LINK_TYPE_GENEVE: + { + const NMPlatformLnkGeneve *props = extra_data; + + nm_assert(props); + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + NLA_PUT_U32(msg, IFLA_GENEVE_ID, props->id); + + if (props->remote) { + NLA_PUT_U32(msg, IFLA_GENEVE_REMOTE, props->remote); + } else if (!IN6_IS_ADDR_UNSPECIFIED(&props->remote6)) { + NLA_PUT(msg, IFLA_GENEVE_REMOTE6, sizeof(props->remote6), &props->remote6); + } + NLA_PUT_U16(msg, IFLA_GENEVE_PORT, htons(props->dst_port)); + if (props->ttl == -1) { + NLA_PUT_U8(msg, IFLA_GENEVE_TTL_INHERIT, 1); + } else { + /* When you want to specify a TTL value, + * don't add TTL_INHERIT to the message */ + NLA_PUT_U8(msg, IFLA_GENEVE_TTL, props->ttl & 0xff); + } + NLA_PUT_U8(msg, IFLA_GENEVE_TOS, props->tos); + NLA_PUT_U8(msg, IFLA_GENEVE_DF, props->df); + break; + } + case NM_LINK_TYPE_GRE: case NM_LINK_TYPE_GRETAP: { @@ -5813,15 +5911,18 @@ _nl_msg_new_route(uint16_t nlmsg_type, uint16_t nlmsg_flags, const NMPObject *ob } NLA_PUT_U32(msg, RTA_GATEWAY, gw); - rtnh->rtnh_flags = 0; + if (i == 0u) { + rtnh->rtnh_flags = + (gw != 0 && NM_FLAGS_HAS(obj->ip_route.r_rtm_flags, (unsigned) RTNH_F_ONLINK)) + ? RTNH_F_ONLINK + : 0; + } else { + const NMPlatformIP4RtNextHop *n2 = &obj->_ip4_route.extra_nexthops[i - 1u]; - if (obj->ip4_route.n_nexthops > 1 - && NM_FLAGS_HAS(obj->ip_route.r_rtm_flags, (unsigned) (RTNH_F_ONLINK)) && gw != 0) { - /* Unlike kernel, we only track the onlink flag per NMPlatformIP4Address, and - * not per nexthop. That is fine for NetworkManager configuring addresses. - * It is not fine for tracking addresses from kernel in platform cache, - * because the rtnh_flags of the nexthops need to be part of nmp_object_id_cmp(). */ - rtnh->rtnh_flags |= RTNH_F_ONLINK; + rtnh->rtnh_flags = + (gw != 0 && NM_FLAGS_HAS(n2->rtnh_flags, (unsigned) RTNH_F_ONLINK)) + ? RTNH_F_ONLINK + : 0; } rtnh->rtnh_len = (char *) nlmsg_tail(nlmsg_hdr(msg)) - (char *) rtnh; |