summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-06-08 13:18:13 +0200
committerThomas Haller <thaller@redhat.com>2020-06-11 16:51:50 +0200
commita7aa2a5e01189622ff2776a25bba3ec1c8346a8c (patch)
tree78c401f71e5cf7b2326284bd7a3e2619c0765e07
parentd2313bef5eebf15e4d8838080066cea4b624ec20 (diff)
downloadNetworkManager-a7aa2a5e01189622ff2776a25bba3ec1c8346a8c.tar.gz
lldp: delay change notification for LLDP neighbor events
We already rate limit change events by two seconds. When we notice that something changed, we call data_changed_schedule(). Previously, that would immediately issue the change notification, if ratelimiting currently was not in effect. That means, if we happen go receive two LLDP neighbor events in short succession, then the first one will trigger the change notification right away, while the second will be rate limited. Avoid that by always issue scheduling the change notification in the background. And if we currently are not rate limited, with an idle handler with low priority.
-rw-r--r--src/devices/nm-lldp-listener.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c
index 91aee3b3bc..ff18975724 100644
--- a/src/devices/nm-lldp-listener.c
+++ b/src/devices/nm-lldp-listener.c
@@ -16,8 +16,8 @@
#include "systemd/nm-sd.h"
-#define MAX_NEIGHBORS 128
-#define MIN_UPDATE_INTERVAL_NS (2 * NM_UTILS_NSEC_PER_SEC)
+#define MAX_NEIGHBORS 128
+#define MIN_UPDATE_INTERVAL_NSEC (2 * NM_UTILS_NSEC_PER_SEC)
#define LLDP_MAC_NEAREST_BRIDGE ((const struct ether_addr *) ((uint8_t[ETH_ALEN]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }))
#define LLDP_MAC_NEAREST_NON_TPMR_BRIDGE ((const struct ether_addr *) ((uint8_t[ETH_ALEN]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }))
@@ -36,7 +36,7 @@ typedef struct {
GHashTable *lldp_neighbors;
/* the timestamp in nsec until which we delay updates. */
- gint64 ratelimit_next;
+ gint64 ratelimit_next_nsec;
guint ratelimit_id;
GVariant *variant;
@@ -678,7 +678,7 @@ data_changed_timeout (gpointer user_data)
priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
priv->ratelimit_id = 0;
- priv->ratelimit_next = nm_utils_get_monotonic_timestamp_nsec() + MIN_UPDATE_INTERVAL_NS;
+ priv->ratelimit_next_nsec = nm_utils_get_monotonic_timestamp_nsec() + MIN_UPDATE_INTERVAL_NSEC;
data_changed_notify (self, priv);
return G_SOURCE_REMOVE;
}
@@ -687,18 +687,25 @@ static void
data_changed_schedule (NMLldpListener *self)
{
NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self);
- gint64 now;
+ gint64 now_nsec;
- now = nm_utils_get_monotonic_timestamp_nsec ();
- if (now < priv->ratelimit_next) {
- if (!priv->ratelimit_id)
- priv->ratelimit_id = g_timeout_add (NM_UTILS_NSEC_TO_MSEC_CEIL (priv->ratelimit_next - now), data_changed_timeout, self);
+ if (priv->ratelimit_id != 0)
+ return;
+
+ now_nsec = nm_utils_get_monotonic_timestamp_nsec ();
+ if (now_nsec < priv->ratelimit_next_nsec) {
+ priv->ratelimit_id = g_timeout_add_full (G_PRIORITY_LOW,
+ NM_UTILS_NSEC_TO_MSEC_CEIL (priv->ratelimit_next_nsec - now_nsec),
+ data_changed_timeout,
+ self,
+ NULL);
return;
}
- nm_clear_g_source (&priv->ratelimit_id);
- priv->ratelimit_next = now + MIN_UPDATE_INTERVAL_NS;
- data_changed_notify (self, priv);
+ priv->ratelimit_id = g_idle_add_full (G_PRIORITY_LOW,
+ data_changed_timeout,
+ self,
+ NULL);
}
static void
@@ -856,12 +863,13 @@ nm_lldp_listener_stop (NMLldpListener *self)
size = g_hash_table_size (priv->lldp_neighbors);
g_hash_table_remove_all (priv->lldp_neighbors);
- if (size || priv->ratelimit_id)
+ if ( size > 0
+ || priv->ratelimit_id != 0)
changed = TRUE;
}
nm_clear_g_source (&priv->ratelimit_id);
- priv->ratelimit_next = 0;
+ priv->ratelimit_next_nsec = 0;
priv->ifindex = 0;
if (changed)