ndisc: fix IPv6 address lifetimes computation

Background: when router sends router advertisement (RA) message,
NetworkManager processes it and passes data to a lower system layer.
Currently there is a problem that NetworkManager adds one second to both
valid lifetime and preferred lifetime. This happens because of the
algorithm in nm_ndisc_data_to_l3cd() function.

Let's look at an example: let current timestamp be 100450, so now_sec
variable is 100. At this moment RA message was received from the router.
The IPv6 address' valid lifetime is 200 seconds (for example), so
expiration timestamp (ndisc_addr->expiry_msec) is 300450. But after the
_nm_ndisc_lifetime_from_expiry() call, NMPlatformIP6Address lifetime
becomes 201 ((300450-(100*1000)+999)/1000). Which is wrong.

This commit fixes this behaviour by replacing
nm_utils_get_monotonic_timestamp_sec() with
nm_utils_get_monotonic_timestamp_msec() so that timestamps are
calculated more precisely.

Related issue: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1464
Merge request: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1863

(cherry picked from commit 14e7220f5f)
This commit is contained in:
Sergey Koshelenko 2024-02-09 01:51:04 +02:00 committed by Íñigo Huguet
parent 27c701ebfb
commit d88e21ff91

View file

@ -114,7 +114,7 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_idx,
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
guint32 ifa_flags;
guint i;
const gint32 now_sec = nm_utils_get_monotonic_timestamp_sec();
const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec();
l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_NDISC);
@ -134,12 +134,10 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex *multi_idx,
.ifindex = ifindex,
.address = ndisc_addr->address,
.plen = 64,
.timestamp = now_sec,
.lifetime = _nm_ndisc_lifetime_from_expiry(((gint64) now_sec) * 1000,
ndisc_addr->expiry_msec,
TRUE),
.timestamp = now_msec / 1000,
.lifetime = _nm_ndisc_lifetime_from_expiry(now_msec, ndisc_addr->expiry_msec, TRUE),
.preferred = _nm_ndisc_lifetime_from_expiry(
((gint64) now_sec) * 1000,
now_msec,
NM_MIN(ndisc_addr->expiry_msec, ndisc_addr->expiry_preferred_msec),
TRUE),
.addr_source = NM_IP_CONFIG_SOURCE_NDISC,