diff options
author | Thomas Haller <thaller@redhat.com> | 2015-04-29 07:52:23 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-04-29 07:52:23 +0200 |
commit | 39aa27c32f9493111d9efa3b65d3ad9505afa960 (patch) | |
tree | 33193b3f2de384c11b45870282a7166a0754cd47 | |
parent | b5beaef8fa19a85110582b3c4439daa49e567d85 (diff) | |
parent | 1e85c3584670c167b36b784f3504f190047b84f8 (diff) |
wifi/libnm: merge branch 'mtl/wifi-ap-last-seen'
https://mail.gnome.org/archives/networkmanager-list/2015-April/msg00053.html
-rw-r--r-- | introspection/nm-access-point.xml | 7 | ||||
-rw-r--r-- | libnm-glib/libnm-glib.ver | 1 | ||||
-rw-r--r-- | libnm-glib/nm-access-point.c | 44 | ||||
-rw-r--r-- | libnm-glib/nm-access-point.h | 2 | ||||
-rw-r--r-- | libnm/libnm.ver | 1 | ||||
-rw-r--r-- | libnm/nm-access-point.c | 43 | ||||
-rw-r--r-- | libnm/nm-access-point.h | 2 | ||||
-rw-r--r-- | src/NetworkManagerUtils.c | 53 | ||||
-rw-r--r-- | src/NetworkManagerUtils.h | 1 | ||||
-rw-r--r-- | src/devices/wifi/nm-wifi-ap.c | 25 | ||||
-rw-r--r-- | src/devices/wifi/nm-wifi-ap.h | 1 | ||||
-rw-r--r-- | src/tests/test-general-with-expect.c | 37 |
12 files changed, 210 insertions, 7 deletions
diff --git a/introspection/nm-access-point.xml b/introspection/nm-access-point.xml index 21f238ffaf..ef5af6ab77 100644 --- a/introspection/nm-access-point.xml +++ b/introspection/nm-access-point.xml @@ -30,6 +30,13 @@ <property name="Strength" type="y" access="read"> <tp:docstring>The current signal quality of the access point, in percent.</tp:docstring> </property> + <property name="LastSeen" type="i" access="read"> + <tp:docstring> + The timestamp (in CLOCK_BOOTTIME seconds) for the last time the access + point was found in scan results. A value of -1 means the access point + has never been found in scan results. + </tp:docstring> + </property> <signal name="PropertiesChanged"> <arg name="properties" type="a{sv}" tp:type="String_Variant_Map"> diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver index 9219c4a2bb..dc982e566b 100644 --- a/libnm-glib/libnm-glib.ver +++ b/libnm-glib/libnm-glib.ver @@ -11,6 +11,7 @@ global: nm_access_point_get_flags; nm_access_point_get_frequency; nm_access_point_get_hw_address; + nm_access_point_get_last_seen; nm_access_point_get_max_bitrate; nm_access_point_get_mode; nm_access_point_get_rsn_flags; diff --git a/libnm-glib/nm-access-point.c b/libnm-glib/nm-access-point.c index abf61cc923..c6b7c9ce74 100644 --- a/libnm-glib/nm-access-point.c +++ b/libnm-glib/nm-access-point.c @@ -53,6 +53,7 @@ typedef struct { NM80211Mode mode; guint32 max_bitrate; guint8 strength; + gint last_seen; } NMAccessPointPrivate; enum { @@ -67,6 +68,7 @@ enum { PROP_MAX_BITRATE, PROP_STRENGTH, PROP_BSSID, + PROP_LAST_SEEN, LAST_PROP }; @@ -266,6 +268,27 @@ nm_access_point_get_strength (NMAccessPoint *ap) } /** + * nm_access_point_get_last_seen: + * @ap: a #NMAccessPoint + * + * Returns the timestamp (in CLOCK_BOOTTIME seconds) for the last time the + * access point was found in scan results. A value of -1 means the access + * point has not been found in a scan. + * + * Returns: the last seen time in seconds + * + * Since: 1.2 + **/ +gint +nm_access_point_get_last_seen (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), -1); + + _nm_object_ensure_inited (NM_OBJECT (ap)); + return NM_ACCESS_POINT_GET_PRIVATE (ap)->last_seen; +} + +/** * nm_access_point_connection_valid: * @ap: an #NMAccessPoint to validate @connection against * @connection: an #NMConnection to validate against @ap @@ -416,6 +439,7 @@ nm_access_point_filter_connections (NMAccessPoint *ap, const GSList *connections static void nm_access_point_init (NMAccessPoint *ap) { + NM_ACCESS_POINT_GET_PRIVATE (ap)->last_seen = -1; } static void @@ -482,6 +506,9 @@ get_property (GObject *object, case PROP_STRENGTH: g_value_set_uchar (value, nm_access_point_get_strength (ap)); break; + case PROP_LAST_SEEN: + g_value_set_int (value, nm_access_point_get_last_seen (ap)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -512,6 +539,7 @@ register_properties (NMAccessPoint *ap) { NM_ACCESS_POINT_MODE, &priv->mode }, { NM_ACCESS_POINT_MAX_BITRATE, &priv->max_bitrate }, { NM_ACCESS_POINT_STRENGTH, &priv->strength }, + { NM_ACCESS_POINT_LAST_SEEN, &priv->last_seen }, { NULL }, }; @@ -671,4 +699,20 @@ nm_access_point_class_init (NMAccessPointClass *ap_class) 0, G_MAXUINT8, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:last-seen: + * + * The timestamp (in CLOCK_BOOTTIME seconds) for the last time the + * access point was found in scan results. A value of -1 means the + * access point has not been found in a scan. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_LAST_SEEN, + g_param_spec_int (NM_ACCESS_POINT_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } diff --git a/libnm-glib/nm-access-point.h b/libnm-glib/nm-access-point.h index d3150f8eee..fc43cbacd0 100644 --- a/libnm-glib/nm-access-point.h +++ b/libnm-glib/nm-access-point.h @@ -46,6 +46,7 @@ G_BEGIN_DECLS #define NM_ACCESS_POINT_MODE "mode" #define NM_ACCESS_POINT_MAX_BITRATE "max-bitrate" #define NM_ACCESS_POINT_STRENGTH "strength" +#define NM_ACCESS_POINT_LAST_SEEN "last-seen" /* DEPRECATED */ #define NM_ACCESS_POINT_HW_ADDRESS "hw-address" @@ -80,6 +81,7 @@ guint32 nm_access_point_get_frequency (NMAccessPoint *ap); NM80211Mode nm_access_point_get_mode (NMAccessPoint *ap); guint32 nm_access_point_get_max_bitrate (NMAccessPoint *ap); guint8 nm_access_point_get_strength (NMAccessPoint *ap); +gint nm_access_point_get_last_seen (NMAccessPoint *ap); GSList * nm_access_point_filter_connections (NMAccessPoint *ap, const GSList *connections); diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 0b7bacc27e..1fe8e30d53 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -847,6 +847,7 @@ local: libnm_1_2_0 { global: + nm_access_point_get_last_seen; nm_device_get_nm_plugin_missing; nm_setting_802_1x_check_cert_scheme; nm_setting_bridge_get_multicast_snooping; diff --git a/libnm/nm-access-point.c b/libnm/nm-access-point.c index e20cd9971e..34c7e15e79 100644 --- a/libnm/nm-access-point.c +++ b/libnm/nm-access-point.c @@ -49,6 +49,7 @@ typedef struct { NM80211Mode mode; guint32 max_bitrate; guint8 strength; + gint last_seen; } NMAccessPointPrivate; enum { @@ -63,6 +64,7 @@ enum { PROP_MAX_BITRATE, PROP_STRENGTH, PROP_BSSID, + PROP_LAST_SEEN, LAST_PROP }; @@ -221,6 +223,26 @@ nm_access_point_get_strength (NMAccessPoint *ap) } /** + * nm_access_point_get_strength: + * @ap: a #NMAccessPoint + * + * Returns the timestamp (in CLOCK_BOOTTIME seconds) for the last time the + * access point was found in scan results. A value of -1 means the access + * point has not been found in a scan. + * + * Returns: the last seen time in seconds + * + * Since: 1.2 + **/ +gint +nm_access_point_get_last_seen (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_ACCESS_POINT (ap), -1); + + return NM_ACCESS_POINT_GET_PRIVATE (ap)->last_seen; +} + +/** * nm_access_point_connection_valid: * @ap: an #NMAccessPoint to validate @connection against * @connection: an #NMConnection to validate against @ap @@ -364,6 +386,7 @@ nm_access_point_filter_connections (NMAccessPoint *ap, const GPtrArray *connecti static void nm_access_point_init (NMAccessPoint *ap) { + NM_ACCESS_POINT_GET_PRIVATE (ap)->last_seen = -1; } static void @@ -418,6 +441,9 @@ get_property (GObject *object, case PROP_STRENGTH: g_value_set_uchar (value, nm_access_point_get_strength (ap)); break; + case PROP_LAST_SEEN: + g_value_set_int (value, nm_access_point_get_last_seen (ap)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -439,6 +465,7 @@ init_dbus (NMObject *object) { NM_ACCESS_POINT_MODE, &priv->mode }, { NM_ACCESS_POINT_MAX_BITRATE, &priv->max_bitrate }, { NM_ACCESS_POINT_STRENGTH, &priv->strength }, + { NM_ACCESS_POINT_LAST_SEEN, &priv->last_seen }, { NULL }, }; @@ -595,4 +622,20 @@ nm_access_point_class_init (NMAccessPointClass *ap_class) 0, G_MAXUINT8, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * NMAccessPoint:last-seen: + * + * The timestamp (in CLOCK_BOOTTIME seconds) for the last time the + * access point was found in scan results. A value of -1 means the + * access point has not been found in a scan. + * + * Since: 1.2 + **/ + g_object_class_install_property + (object_class, PROP_LAST_SEEN, + g_param_spec_int (NM_ACCESS_POINT_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); } diff --git a/libnm/nm-access-point.h b/libnm/nm-access-point.h index 6991c19ac6..953a1567c4 100644 --- a/libnm/nm-access-point.h +++ b/libnm/nm-access-point.h @@ -46,6 +46,7 @@ G_BEGIN_DECLS #define NM_ACCESS_POINT_MODE "mode" #define NM_ACCESS_POINT_MAX_BITRATE "max-bitrate" #define NM_ACCESS_POINT_STRENGTH "strength" +#define NM_ACCESS_POINT_LAST_SEEN "last-seen" /* DEPRECATED */ #define NM_ACCESS_POINT_HW_ADDRESS "hw-address" @@ -73,6 +74,7 @@ guint32 nm_access_point_get_frequency (NMAccessPoint *ap); NM80211Mode nm_access_point_get_mode (NMAccessPoint *ap); guint32 nm_access_point_get_max_bitrate (NMAccessPoint *ap); guint8 nm_access_point_get_strength (NMAccessPoint *ap); +gint nm_access_point_get_last_seen (NMAccessPoint *ap); GPtrArray * nm_access_point_filter_connections (NMAccessPoint *ap, const GPtrArray *connections); diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 0f957814d3..ae2e83e482 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -1818,15 +1818,15 @@ nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection /**************************************************************************/ static gint64 monotonic_timestamp_offset_sec; +static int monotonic_timestamp_clock_mode = 0; static void monotonic_timestamp_get (struct timespec *tp) { - static int clock_mode = 0; - gboolean first_time = FALSE; + int clock_mode = 0; int err = 0; - switch (clock_mode) { + switch (monotonic_timestamp_clock_mode) { case 0: /* the clock is not yet initialized (first run) */ err = clock_gettime (CLOCK_BOOTTIME, tp); @@ -1835,7 +1835,6 @@ monotonic_timestamp_get (struct timespec *tp) err = clock_gettime (CLOCK_MONOTONIC, tp); } else clock_mode = 1; - first_time = TRUE; break; case 1: /* default, return CLOCK_BOOTTIME */ @@ -1851,7 +1850,7 @@ monotonic_timestamp_get (struct timespec *tp) g_assert (err == 0); (void)err; g_assert (tp->tv_nsec >= 0 && tp->tv_nsec < NM_UTILS_NS_PER_SECOND); - if (G_LIKELY (!first_time)) + if (G_LIKELY (clock_mode == 0)) return; /* Calculate an offset for the time stamp. @@ -1868,6 +1867,7 @@ monotonic_timestamp_get (struct timespec *tp) * wraps (~68 years). **/ monotonic_timestamp_offset_sec = (- ((gint64) tp->tv_sec)) + 1; + monotonic_timestamp_clock_mode = clock_mode; if (nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) { time_t now = time (NULL); @@ -2232,6 +2232,49 @@ out: g_array_free (sorted_hashes, TRUE); } +/** + * nm_utils_monotonic_timestamp_as_boottime: + * @timestamp: the monotonic-timestamp that should be converted into CLOCK_BOOTTIME. + * @timestamp_ns_per_tick: How many nano seconds make one unit of @timestamp? E.g. if + * @timestamp is in unit seconds, pass %NM_UTILS_NS_PER_SECOND; @timestamp in nano + * seconds, pass 1; @timestamp in milli seconds, pass %NM_UTILS_NS_PER_SECOND/1000; etc. + * + * Returns: the monotonic-timestamp as CLOCK_BOOTTIME, as returned by clock_gettime(). + * The unit is the same as the passed in @timestamp basd on @timestamp_ns_per_tick. + * E.g. if you passed @timestamp in as seconds, it will return boottime in seconds. + * If @timestamp is a non-positive, it returns -1. Note that a (valid) monotonic-timestamp + * is always positive. + * + * On older kernels that don't support CLOCK_BOOTTIME, the returned time is instead CLOCK_MONOTONIC. + **/ +gint64 +nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ns_per_tick) +{ + gint64 offset; + + /* only support ns-per-tick being a multiple of 10. */ + g_return_val_if_fail (timestamp_ns_per_tick == 1 + || (timestamp_ns_per_tick > 0 && + timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND && + timestamp_ns_per_tick % 10 == 0), + -1); + + /* Check that the timestamp is in a valid range. */ + g_return_val_if_fail (timestamp >= 0, -1); + + /* if the caller didn't yet ever fetch a monotonic-timestamp, he cannot pass any meaningful + * value (because he has no idea what these timestamps would be). That would be a bug. */ + g_return_val_if_fail (monotonic_timestamp_clock_mode != 0, -1); + + /* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */ + offset = monotonic_timestamp_offset_sec * (NM_UTILS_NS_PER_SECOND / timestamp_ns_per_tick); + + /* check for overflow. */ + g_return_val_if_fail (offset > 0 || timestamp < G_MAXINT64 + offset, G_MAXINT64); + + return timestamp - offset; +} + #define IPV6_PROPERTY_DIR "/proc/sys/net/ipv6/conf/" #define IPV4_PROPERTY_DIR "/proc/sys/net/ipv4/conf/" diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 99de3b66b9..16c5ba39bd 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -141,6 +141,7 @@ gint64 nm_utils_get_monotonic_timestamp_ns (void); gint64 nm_utils_get_monotonic_timestamp_us (void); gint64 nm_utils_get_monotonic_timestamp_ms (void); gint32 nm_utils_get_monotonic_timestamp_s (void); +gint64 nm_utils_monotonic_timestamp_as_boottime (gint64 timestamp, gint64 timestamp_ticks_per_ns); const char *ASSERT_VALID_PATH_COMPONENT (const char *name) G_GNUC_WARN_UNUSED_RESULT; const char *nm_utils_ip6_property_path (const char *ifname, const char *property); diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index c891fc73c2..56d7cbfd69 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -80,6 +80,7 @@ enum { PROP_MODE, PROP_MAX_BITRATE, PROP_STRENGTH, + PROP_LAST_SEEN, LAST_PROP }; @@ -195,6 +196,12 @@ get_property (GObject *object, guint prop_id, case PROP_STRENGTH: g_value_set_schar (value, priv->strength); break; + case PROP_LAST_SEEN: + g_value_set_int (value, + priv->last_seen > 0 + ? (gint) nm_utils_monotonic_timestamp_as_boottime (priv->last_seen, NM_UTILS_NS_PER_SECOND) + : -1); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -294,6 +301,13 @@ nm_ap_class_init (NMAccessPointClass *ap_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_LAST_SEEN, + g_param_spec_int (NM_AP_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), G_TYPE_FROM_CLASS (ap_class), &dbus_glib_nm_access_point_object_info); @@ -1055,7 +1069,7 @@ void nm_ap_set_fake (NMAccessPoint *ap, gboolean fake) gint32 nm_ap_get_last_seen (const NMAccessPoint *ap) { - g_return_val_if_fail (NM_IS_AP (ap), FALSE); + g_return_val_if_fail (NM_IS_AP (ap), 0); return NM_AP_GET_PRIVATE (ap)->last_seen; } @@ -1063,9 +1077,16 @@ nm_ap_get_last_seen (const NMAccessPoint *ap) void nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen) { + NMAccessPointPrivate *priv; + g_return_if_fail (NM_IS_AP (ap)); - NM_AP_GET_PRIVATE (ap)->last_seen = last_seen; + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->last_seen != last_seen) { + priv->last_seen = last_seen; + g_object_notify (G_OBJECT (ap), NM_AP_LAST_SEEN); + } } static guint diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index bcbf7eea0e..2bdb023507 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -43,6 +43,7 @@ #define NM_AP_MODE "mode" #define NM_AP_MAX_BITRATE "max-bitrate" #define NM_AP_STRENGTH "strength" +#define NM_AP_LAST_SEEN "last-seen" typedef struct { GObject parent; diff --git a/src/tests/test-general-with-expect.c b/src/tests/test-general-with-expect.c index 4318b594c6..304543df58 100644 --- a/src/tests/test-general-with-expect.c +++ b/src/tests/test-general-with-expect.c @@ -34,6 +34,42 @@ /*******************************************/ +static void +test_nm_utils_monotonic_timestamp_as_boottime () +{ + gint64 timestamp_ns_per_tick, now, now_boottime, now_boottime_2, now_boottime_3; + struct timespec tp; + clockid_t clockid; + guint i; + + if (clock_gettime (CLOCK_BOOTTIME, &tp) != 0 && errno == EINVAL) + clockid = CLOCK_MONOTONIC; + else + clockid = CLOCK_BOOTTIME; + + for (i = 0; i < 10; i++) { + + if (clock_gettime (clockid, &tp) != 0) + g_assert_not_reached (); + now_boottime = ( ((gint64) tp.tv_sec) * NM_UTILS_NS_PER_SECOND ) + ((gint64) tp.tv_nsec); + + now = nm_utils_get_monotonic_timestamp_ns (); + + now_boottime_2 = nm_utils_monotonic_timestamp_as_boottime (now, 1); + g_assert_cmpint (now_boottime_2, >=, 0); + g_assert_cmpint (now_boottime_2, >=, now_boottime); + g_assert_cmpint (now_boottime_2 - now_boottime, <=, NM_UTILS_NS_PER_SECOND / 1000); + + for (timestamp_ns_per_tick = 1; timestamp_ns_per_tick <= NM_UTILS_NS_PER_SECOND; timestamp_ns_per_tick *= 10) { + now_boottime_3 = nm_utils_monotonic_timestamp_as_boottime (now / timestamp_ns_per_tick, timestamp_ns_per_tick); + + g_assert_cmpint (now_boottime_2 / timestamp_ns_per_tick, ==, now_boottime_3); + } + } +} + +/*******************************************/ + struct test_nm_utils_kill_child_async_data { GMainLoop *loop; @@ -465,6 +501,7 @@ main (int argc, char **argv) { nmtst_init_assert_logging (&argc, &argv, "DEBUG", "DEFAULT"); + g_test_add_func ("/general/nm_utils_monotonic_timestamp_as_boottime", test_nm_utils_monotonic_timestamp_as_boottime); g_test_add_func ("/general/nm_utils_kill_child", test_nm_utils_kill_child); g_test_add_func ("/general/nm_utils_array_remove_at_indexes", test_nm_utils_array_remove_at_indexes); g_test_add_func ("/general/nm_ethernet_address_is_valid", test_nm_ethernet_address_is_valid); |