summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-06-09 10:03:01 +0200
committerThomas Haller <thaller@redhat.com>2014-06-19 22:26:10 +0200
commitc29496125f32211e3337db3250aacc5a89e13325 (patch)
treec492dcca85cead01f5817761afa639ffb9387106
parenta2791f54da771cf7354dfdc4a420aaf772a8c6ee (diff)
downloadNetworkManager-c29496125f32211e3337db3250aacc5a89e13325.tar.gz
platform: handle unset address timestamp as *now* in to_string()
When printing an address in nm_platform_ip4_address_to_string() and nm_platform_ip6_address_to_string() treat an unset @timestamp as counting from @now. This is useful, if you just have the remaining lifetime at hand and want to print an address. In general it is not a good idea to leave the timestamp not anchored to an absolute @timestamp. Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--src/platform/nm-platform.c28
-rw-r--r--src/platform/nm-platform.h21
2 files changed, 39 insertions, 10 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 71c60ca5bf..17f452c547 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -1436,6 +1436,7 @@ nm_platform_ip4_address_add (int ifindex,
addr.address = address;
addr.peer_address = peer_address;
addr.plen = plen;
+ addr.timestamp = 0; /* set it at zero, which to_string will treat as *now* */
addr.lifetime = lifetime;
addr.preferred = preferred;
if (label)
@@ -1470,6 +1471,7 @@ nm_platform_ip6_address_add (int ifindex,
addr.address = address;
addr.peer_address = peer_address;
addr.plen = plen;
+ addr.timestamp = 0; /* set it to zero, which to_string will treat as *now* */
addr.lifetime = lifetime;
addr.preferred = preferred;
addr.flags = flags;
@@ -1571,6 +1573,17 @@ _rebase_relative_time_on_now (guint32 timestamp, guint32 duration, guint32 now,
if (duration == NM_PLATFORM_LIFETIME_PERMANENT)
return NM_PLATFORM_LIFETIME_PERMANENT;
+ if (timestamp == 0) {
+ /* if the @timestamp is zero, assume it was just left unset and that the relative
+ * @duration starts counting from @now. This is convenient to construct an address
+ * and print it in nm_platform_ip4_address_to_string().
+ *
+ * In general it does not make sense to set the @duration without anchoring at
+ * @timestamp because you don't know the absolute expiration time when looking
+ * at the address at a later moment. */
+ timestamp = now;
+ }
+
/* For timestamp > now, just accept it and calculate the expected(?) result. */
t = (gint64) timestamp + (gint64) duration - (gint64) now;
@@ -1597,13 +1610,18 @@ _address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32
if (!lifetime)
return FALSE;
preferred = _rebase_relative_time_on_now (address->timestamp, address->preferred, now, padding);
- if (preferred > lifetime) {
- g_warn_if_reached ();
- preferred = lifetime;
- }
*out_lifetime = lifetime;
- *out_preferred = preferred;
+ *out_preferred = MIN (preferred, lifetime);
+
+ /* Assert that non-permanent addresses have a (positive) @timestamp. _rebase_relative_time_on_now()
+ * treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always
+ * should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew.
+ */
+ g_return_val_if_fail ( address->timestamp != 0
+ || ( address->lifetime == NM_PLATFORM_LIFETIME_PERMANENT
+ && address->preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE);
+ g_return_val_if_fail (preferred <= lifetime, TRUE);
}
return TRUE;
}
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 7dc0127648..96b6cfabbd 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -167,11 +167,22 @@ typedef struct {
NMPlatformSource source; \
\
/* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*().
- * This value is mainly used to anchor the relative lifetime and preferred values.
- * For addresses originating from DHCP it might be set to nm_utils_get_monotonic_timestamp_s()
- * of when the lease was received. For addresses from platform/kernel it might be set to
- * when the address was last modified. For permanent addresses it is mostly set to 0.
- * For non-permanent addresses it should not be 0 (because 0 is not a valid timestamp).
+ *
+ * The rules are:
+ * 1 @lifetime==0: @timestamp and @preferred is irrelevant (but mostly set to 0 too). Such addresses
+ * are permanent. This rule is so that unset addresses (calloc) are permanent by default.
+ * 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly
+ * set to 0). Such addresses are permanent.
+ * 3 Non permanent addreses should (almost) always have @timestamp > 0. 0 is not a valid timestamp
+ * and never returned by nm_utils_get_monotonic_timestamp_s(). In this case @valid/@preferred
+ * is anchored at @timestamp.
+ * 4 Non permanent addresses with @timestamp == 0 are implicitely anchored at *now*, thus the time
+ * moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add().
+ *
+ * Non permanent addresses from DHCP/RA might have the @timestamp set to the moment of when the
+ * lease was received. Addresses from kernel might have the @timestamp based on the last modification
+ * time of the addresses. But don't rely on this behaviour, the @timestamp is only defined for anchoring
+ * @lifetime and @preferred.
*/ \
guint32 timestamp; \
guint32 lifetime; /* seconds since timestamp */ \