diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index 7ca03936fb..5b2903d809 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -2625,12 +2625,15 @@ set_interface_flags_full(NMDevice * self, } static gboolean -set_interface_flags(NMDevice *self, NMDeviceInterfaceFlags interface_flags, gboolean set) +set_interface_flags(NMDevice * self, + NMDeviceInterfaceFlags interface_flags, + gboolean set, + gboolean notify) { return set_interface_flags_full(self, interface_flags, set ? interface_flags : NM_DEVICE_INTERFACE_FLAG_NONE, - TRUE); + notify); } void @@ -5051,11 +5054,7 @@ nm_device_set_carrier(NMDevice *self, gboolean carrier) if (NM_FLAGS_ALL(priv->capabilities, NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_NONSTANDARD_CARRIER)) { - notify_flags = set_interface_flags_full(self, - NM_DEVICE_INTERFACE_FLAG_CARRIER, - carrier ? NM_DEVICE_INTERFACE_FLAG_CARRIER - : NM_DEVICE_INTERFACE_FLAG_NONE, - FALSE); + notify_flags = set_interface_flags(self, NM_DEVICE_INTERFACE_FLAG_CARRIER, carrier, FALSE); } priv->carrier = carrier; @@ -7944,14 +7943,6 @@ master_ready_cb(NMActiveConnection *active, GParamSpec *pspec, NMDevice *self) nm_device_activate_schedule_stage1_device_prepare(self, FALSE); } -static void -lldp_neighbors_changed(NMLldpListener *lldp_listener, GParamSpec *pspec, gpointer user_data) -{ - NMDevice *self = NM_DEVICE(user_data); - - _notify(self, PROP_LLDP_NEIGHBORS); -} - static NMPlatformVF * sriov_vf_config_to_platform(NMDevice *self, NMSriovVF *vf, GError **error) { @@ -8239,43 +8230,56 @@ act_stage2_config(NMDevice *self, NMDeviceStateReason *out_failure_reason) } static void -lldp_init(NMDevice *self, gboolean restart) +_lldp_neighbors_changed_cb(NMLldpListener *lldp_listener, gpointer user_data) +{ + _notify(user_data, PROP_LLDP_NEIGHBORS); +} + +static void +lldp_setup(NMDevice *self, NMTernary enabled) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + int ifindex; + gboolean notify_lldp_neighbors = FALSE; + gboolean notify_interface_flags = FALSE; - if (priv->ifindex > 0 && _prop_get_connection_lldp(self)) { - gs_free_error GError *error = NULL; + ifindex = nm_device_get_ifindex(self); - if (priv->lldp_listener) { - if (restart && nm_lldp_listener_is_running(priv->lldp_listener)) { - nm_lldp_listener_stop(priv->lldp_listener); - set_interface_flags(self, NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED, FALSE); - } - } else { - priv->lldp_listener = nm_lldp_listener_new(); - g_signal_connect(priv->lldp_listener, - "notify::" NM_LLDP_LISTENER_NEIGHBORS, - G_CALLBACK(lldp_neighbors_changed), - self); - } + if (ifindex <= 0) + enabled = FALSE; + else if (enabled == NM_TERNARY_DEFAULT) + enabled = _prop_get_connection_lldp(self); - if (!nm_lldp_listener_is_running(priv->lldp_listener)) { - if (nm_lldp_listener_start(priv->lldp_listener, nm_device_get_ifindex(self), &error)) { - _LOGD(LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener); - set_interface_flags(self, NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED, TRUE); - } else { - _LOGD(LOGD_DEVICE, - "LLDP listener %p could not be started: %s", - priv->lldp_listener, - error->message); - } - } - } else { - if (priv->lldp_listener) { - nm_lldp_listener_stop(priv->lldp_listener); - set_interface_flags(self, NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED, FALSE); + if (priv->lldp_listener) { + if (!enabled || nm_lldp_listener_get_ifindex(priv->lldp_listener) != ifindex) { + nm_clear_pointer(&priv->lldp_listener, nm_lldp_listener_destroy); + notify_lldp_neighbors = TRUE; } } + + if (enabled && !priv->lldp_listener) { + gs_free_error GError *error = NULL; + + priv->lldp_listener = + nm_lldp_listener_new(ifindex, _lldp_neighbors_changed_cb, self, &error); + if (!priv->lldp_listener) { + /* This really shouldn't happen. It's likely a bug. Investigate when this happens! */ + _LOGW(LOGD_DEVICE, + "LLDP listener for ifindex %d could not be started: %s", + ifindex, + error->message); + } else + notify_lldp_neighbors = TRUE; + } + + notify_interface_flags = set_interface_flags(self, + NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED, + !!priv->lldp_listener, + FALSE); + + nm_gobject_notify_together(self, + notify_lldp_neighbors ? PROP_LLDP_NEIGHBORS : PROP_0, + notify_interface_flags ? PROP_INTERFACE_FLAGS : PROP_0); } /* set-mode can be: @@ -8488,7 +8492,7 @@ activate_stage2_device_config(NMDevice *self) nm_device_queue_recheck_assume(info->slave); } - lldp_init(self, TRUE); + lldp_setup(self, NM_TERNARY_DEFAULT); nm_device_activate_schedule_stage3_ip_config_start(self); } @@ -12720,7 +12724,7 @@ check_and_reapply_connection(NMDevice * self, klass->reapply_connection(self, con_old, con_new); if (priv->state >= NM_DEVICE_STATE_CONFIG) - lldp_init(self, FALSE); + lldp_setup(self, NM_TERNARY_DEFAULT); if (priv->state >= NM_DEVICE_STATE_IP_CONFIG) { s_ip4_old = nm_connection_get_setting_ip4_config(con_old); @@ -15960,10 +15964,7 @@ nm_device_cleanup(NMDevice *self, NMDeviceStateReason reason, CleanupType cleanu FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); - if (priv->lldp_listener) { - nm_lldp_listener_stop(priv->lldp_listener); - set_interface_flags(self, NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED, FALSE); - } + lldp_setup(self, NM_TERNARY_FALSE); nm_device_update_metered(self); @@ -18396,14 +18397,7 @@ dispose(GObject *object) nm_clear_g_source(&priv->device_link_changed_id); nm_clear_g_source(&priv->device_ip_link_changed_id); - if (priv->lldp_listener) { - g_signal_handlers_disconnect_by_func(priv->lldp_listener, - G_CALLBACK(lldp_neighbors_changed), - self); - nm_lldp_listener_stop(priv->lldp_listener); - set_interface_flags(self, NM_DEVICE_INTERFACE_FLAG_LLDP_CLIENT_ENABLED, FALSE); - g_clear_object(&priv->lldp_listener); - } + lldp_setup(self, FALSE); nm_clear_g_source(&priv->concheck_x[0].p_cur_id); nm_clear_g_source(&priv->concheck_x[1].p_cur_id); diff --git a/src/core/devices/nm-lldp-listener.c b/src/core/devices/nm-lldp-listener.c index 5cf99484f1..76b7bd80e0 100644 --- a/src/core/devices/nm-lldp-listener.c +++ b/src/core/devices/nm-lldp-listener.c @@ -31,34 +31,21 @@ /*****************************************************************************/ -NM_GOBJECT_PROPERTIES_DEFINE(NMLldpListener, PROP_NEIGHBORS, ); - -typedef struct { +struct _NMLldpListener { sd_lldp * lldp_handle; GHashTable *lldp_neighbors; GVariant * variant; + NMLldpListenerNotify notify_callback; + gpointer notify_user_data; + /* the timestamp in nsec until which we delay updates. */ gint64 ratelimit_next_nsec; guint ratelimit_id; int ifindex; -} NMLldpListenerPrivate; - -struct _NMLldpListener { - GObject parent; - NMLldpListenerPrivate _priv; }; -struct _NMLldpListenerClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE(NMLldpListener, nm_lldp_listener, G_TYPE_OBJECT) - -#define NM_LLDP_LISTENER_GET_PRIVATE(self) \ - _NM_GET_PRIVATE(self, NMLldpListener, NM_IS_LLDP_LISTENER) - /*****************************************************************************/ typedef struct { @@ -74,27 +61,28 @@ typedef struct { #define _NMLOG_PREFIX_NAME "lldp" #define _NMLOG_DOMAIN LOGD_DEVICE -#define _NMLOG(level, ...) \ - G_STMT_START \ - { \ - const NMLogLevel _level = (level); \ - \ - if (nm_logging_enabled(_level, _NMLOG_DOMAIN)) { \ - char _sbuf[64]; \ - int _ifindex = (self) ? NM_LLDP_LISTENER_GET_PRIVATE(self)->ifindex : 0; \ - \ - _nm_log(_level, \ - _NMLOG_DOMAIN, \ - 0, \ - _ifindex > 0 ? nm_platform_link_get_name(NM_PLATFORM_GET, _ifindex) : NULL, \ - NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - ((_ifindex > 0) ? nm_sprintf_buf(_sbuf, "[%p,%d]", (self), _ifindex) \ - : ((self) ? nm_sprintf_buf(_sbuf, "[%p]", (self)) : "")) \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } \ +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + const NMLogLevel _level = (level); \ + \ + if (nm_logging_enabled(_level, _NMLOG_DOMAIN)) { \ + char _sbuf[100]; \ + \ + _nm_log(_level, \ + _NMLOG_DOMAIN, \ + 0, \ + (self) ? nm_platform_link_get_name(NM_PLATFORM_GET, (self)->ifindex) : NULL, \ + NULL, \ + "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + ((self) ? nm_sprintf_buf(_sbuf, \ + "[" NM_HASH_OBFUSCATE_PTR_FMT ",%d]", \ + NM_HASH_OBFUSCATE_PTR(self), \ + (self)->ifindex) \ + : "") _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ G_STMT_END #define LOG_NEIGH_FMT "CHASSIS=%u/%s PORT=%u/%s" @@ -812,80 +800,71 @@ nmtst_lldp_parse_from_raw(const guint8 *raw_data, gsize raw_len) /*****************************************************************************/ static void -data_changed_notify(NMLldpListener *self, NMLldpListenerPrivate *priv) +data_changed_notify(NMLldpListener *self) { - nm_clear_g_variant(&priv->variant); - _notify(self, PROP_NEIGHBORS); + nm_clear_g_variant(&self->variant); + + self->notify_callback(self, self->notify_user_data); } static gboolean data_changed_timeout(gpointer user_data) { - NMLldpListener * self = user_data; - NMLldpListenerPrivate *priv; + NMLldpListener *self = user_data; - g_return_val_if_fail(NM_IS_LLDP_LISTENER(self), G_SOURCE_REMOVE); - - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - - priv->ratelimit_id = 0; - priv->ratelimit_next_nsec = nm_utils_get_monotonic_timestamp_nsec() + MIN_UPDATE_INTERVAL_NSEC; - data_changed_notify(self, priv); + self->ratelimit_id = 0; + self->ratelimit_next_nsec = nm_utils_get_monotonic_timestamp_nsec() + MIN_UPDATE_INTERVAL_NSEC; + data_changed_notify(self); return G_SOURCE_REMOVE; } static void data_changed_schedule(NMLldpListener *self) { - NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - gint64 now_nsec; + gint64 now_nsec; - if (priv->ratelimit_id != 0) + if (self->ratelimit_id != 0) return; now_nsec = nm_utils_get_monotonic_timestamp_nsec(); - if (now_nsec < priv->ratelimit_next_nsec) { - priv->ratelimit_id = + if (now_nsec < self->ratelimit_next_nsec) { + self->ratelimit_id = g_timeout_add_full(G_PRIORITY_LOW, - NM_UTILS_NSEC_TO_MSEC_CEIL(priv->ratelimit_next_nsec - now_nsec), + NM_UTILS_NSEC_TO_MSEC_CEIL(self->ratelimit_next_nsec - now_nsec), data_changed_timeout, self, NULL); return; } - priv->ratelimit_id = g_idle_add_full(G_PRIORITY_LOW, data_changed_timeout, self, NULL); + self->ratelimit_id = g_idle_add_full(G_PRIORITY_LOW, data_changed_timeout, self, NULL); } static void process_lldp_neighbor(NMLldpListener *self, sd_lldp_neighbor *neighbor_sd, gboolean remove) { - NMLldpListenerPrivate * priv; nm_auto(lldp_neighbor_freep) LldpNeighbor *neigh = NULL; LldpNeighbor * neigh_old; - g_return_if_fail(NM_IS_LLDP_LISTENER(self)); + nm_assert(self); + nm_assert(self->lldp_handle); + nm_assert(self->lldp_neighbors); - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - - g_return_if_fail(priv->lldp_handle); g_return_if_fail(neighbor_sd); - nm_assert(priv->lldp_neighbors); - neigh = lldp_neighbor_new(neighbor_sd); if (!neigh) { _LOGT("process: failed to parse neighbor"); return; } - neigh_old = g_hash_table_lookup(priv->lldp_neighbors, neigh); + neigh_old = g_hash_table_lookup(self->lldp_neighbors, neigh); if (remove) { if (neigh_old) { _LOGT("process: %s neigh: " LOG_NEIGH_FMT, "remove", LOG_NEIGH_ARG(neigh)); - g_hash_table_remove(priv->lldp_neighbors, neigh_old); + g_hash_table_remove(self->lldp_neighbors, neigh_old); goto handle_changed; } return; @@ -896,7 +875,7 @@ process_lldp_neighbor(NMLldpListener *self, sd_lldp_neighbor *neighbor_sd, gbool _LOGD("process: %s neigh: " LOG_NEIGH_FMT, neigh_old ? "update" : "new", LOG_NEIGH_ARG(neigh)); - g_hash_table_add(priv->lldp_neighbors, g_steal_pointer(&neigh)); + g_hash_table_add(self->lldp_neighbors, g_steal_pointer(&neigh)); handle_changed: data_changed_schedule(self); @@ -911,25 +890,57 @@ lldp_event_handler(sd_lldp *lldp, sd_lldp_event_t event, sd_lldp_neighbor *n, vo !NM_IN_SET(event, SD_LLDP_EVENT_ADDED, SD_LLDP_EVENT_UPDATED, SD_LLDP_EVENT_REFRESHED)); } -gboolean -nm_lldp_listener_start(NMLldpListener *self, int ifindex, GError **error) +/*****************************************************************************/ + +int +nm_lldp_listener_get_ifindex(NMLldpListener *self) { - NMLldpListenerPrivate *priv; - int ret; + g_return_val_if_fail(self, 0); - g_return_val_if_fail(NM_IS_LLDP_LISTENER(self), FALSE); - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(!error || !*error, FALSE); + return self->ifindex; +} - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); +/*****************************************************************************/ - if (priv->lldp_handle) { - g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "already running"); - return FALSE; +GVariant * +nm_lldp_listener_get_neighbors(NMLldpListener *self) +{ + g_return_val_if_fail(self, FALSE); + + if (G_UNLIKELY(!self->variant)) { + gs_free LldpNeighbor **neighbors = NULL; + GVariantBuilder array_builder; + guint i, n; + + g_variant_builder_init(&array_builder, G_VARIANT_TYPE("aa{sv}")); + neighbors = (LldpNeighbor **) + nm_utils_hash_keys_to_array(self->lldp_neighbors, lldp_neighbor_id_cmp_p, NULL, &n); + for (i = 0; i < n; i++) + g_variant_builder_add_value(&array_builder, lldp_neighbor_to_variant(neighbors[i])); + self->variant = g_variant_ref_sink(g_variant_builder_end(&array_builder)); } - ret = sd_lldp_new(&priv->lldp_handle); - if (ret < 0) { + return self->variant; +} + +/*****************************************************************************/ + +NMLldpListener * +nm_lldp_listener_new(int ifindex, + NMLldpListenerNotify notify_callback, + gpointer notify_user_data, + GError ** error) +{ + NMLldpListener *self = NULL; + sd_lldp * lldp_handle; + int r; + + g_return_val_if_fail(ifindex > 0, FALSE); + g_return_val_if_fail(!error || !*error, FALSE); + g_return_val_if_fail(notify_callback, FALSE); + + r = sd_lldp_new(&lldp_handle); + if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, @@ -937,189 +948,77 @@ nm_lldp_listener_start(NMLldpListener *self, int ifindex, GError **error) return FALSE; } - ret = sd_lldp_set_ifindex(priv->lldp_handle, ifindex); - if (ret < 0) { + r = sd_lldp_set_ifindex(lldp_handle, ifindex); + if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "failed setting ifindex"); - goto err; + goto fail_handle; } - ret = sd_lldp_set_callback(priv->lldp_handle, lldp_event_handler, self); - if (ret < 0) { + r = sd_lldp_set_neighbors_max(lldp_handle, MAX_NEIGHBORS); + nm_assert(r == 0); + + self = g_slice_new(NMLldpListener); + *self = (NMLldpListener){ + .ifindex = ifindex, + .notify_callback = notify_callback, + .notify_user_data = notify_user_data, + }; + + r = sd_lldp_set_callback(lldp_handle, lldp_event_handler, self); + if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "set callback failed"); - goto err; + goto fail_handle; } - ret = sd_lldp_set_neighbors_max(priv->lldp_handle, MAX_NEIGHBORS); - nm_assert(ret == 0); - - priv->ifindex = ifindex; - - ret = sd_lldp_attach_event(priv->lldp_handle, NULL, 0); - if (ret < 0) { + r = sd_lldp_attach_event(lldp_handle, NULL, 0); + if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "attach event failed"); - goto err_free; + goto fail_attached; } - ret = sd_lldp_start(priv->lldp_handle); - if (ret < 0) { + r = sd_lldp_start(lldp_handle); + if (r < 0) { g_set_error_literal(error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, "start failed"); - goto err; + goto fail_attached; } - priv->lldp_neighbors = g_hash_table_new_full(lldp_neighbor_id_hash, + self->lldp_neighbors = g_hash_table_new_full(lldp_neighbor_id_hash, lldp_neighbor_id_equal, (GDestroyNotify) lldp_neighbor_free, NULL); + self->lldp_handle = lldp_handle; - _LOGD("start"); + _LOGD("start lldp listener"); + return self; - return TRUE; - -err: - sd_lldp_detach_event(priv->lldp_handle); -err_free: - sd_lldp_unref(priv->lldp_handle); - priv->lldp_handle = NULL; - priv->ifindex = 0; - return FALSE; +fail_attached: + sd_lldp_detach_event(lldp_handle); +fail_handle: + if (self) + nm_g_slice_free(self); + sd_lldp_unref(lldp_handle); + return NULL; } void -nm_lldp_listener_stop(NMLldpListener *self) +nm_lldp_listener_destroy(NMLldpListener *self) { - NMLldpListenerPrivate *priv; - guint size; - gboolean changed = FALSE; + g_return_if_fail(self); - g_return_if_fail(NM_IS_LLDP_LISTENER(self)); - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); + sd_lldp_stop(self->lldp_handle); + sd_lldp_detach_event(self->lldp_handle); + sd_lldp_unref(self->lldp_handle); - if (priv->lldp_handle) { - _LOGD("stop"); - sd_lldp_stop(priv->lldp_handle); - sd_lldp_detach_event(priv->lldp_handle); - sd_lldp_unref(priv->lldp_handle); - priv->lldp_handle = NULL; + nm_clear_g_source(&self->ratelimit_id); - size = g_hash_table_size(priv->lldp_neighbors); - g_hash_table_remove_all(priv->lldp_neighbors); - nm_clear_pointer(&priv->lldp_neighbors, g_hash_table_unref); - if (size > 0 || priv->ratelimit_id != 0) - changed = TRUE; - } + g_hash_table_destroy(self->lldp_neighbors); - nm_clear_g_source(&priv->ratelimit_id); - priv->ratelimit_next_nsec = 0; - priv->ifindex = 0; - - if (changed) - data_changed_notify(self, priv); -} - -gboolean -nm_lldp_listener_is_running(NMLldpListener *self) -{ - NMLldpListenerPrivate *priv; - - g_return_val_if_fail(NM_IS_LLDP_LISTENER(self), FALSE); - - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - return !!priv->lldp_handle; -} - -GVariant * -nm_lldp_listener_get_neighbors(NMLldpListener *self) -{ - NMLldpListenerPrivate *priv; - - g_return_val_if_fail(NM_IS_LLDP_LISTENER(self), FALSE); - - priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - - if (G_UNLIKELY(!priv->variant)) { - gs_free LldpNeighbor **neighbors = NULL; - GVariantBuilder array_builder; - guint i, n; - - g_variant_builder_init(&array_builder, G_VARIANT_TYPE("aa{sv}")); - neighbors = (LldpNeighbor **) - nm_utils_hash_keys_to_array(priv->lldp_neighbors, lldp_neighbor_id_cmp_p, NULL, &n); - for (i = 0; i < n; i++) - g_variant_builder_add_value(&array_builder, lldp_neighbor_to_variant(neighbors[i])); - priv->variant = g_variant_ref_sink(g_variant_builder_end(&array_builder)); - } - return priv->variant; -} - -static void -get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - NMLldpListener *self = NM_LLDP_LISTENER(object); - - switch (prop_id) { - case PROP_NEIGHBORS: - g_value_set_variant(value, nm_lldp_listener_get_neighbors(self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -nm_lldp_listener_init(NMLldpListener *self) -{ - _LOGT("lldp listener created"); -} - -NMLldpListener * -nm_lldp_listener_new(void) -{ - return g_object_new(NM_TYPE_LLDP_LISTENER, NULL); -} - -static void -dispose(GObject *object) -{ - nm_lldp_listener_stop(NM_LLDP_LISTENER(object)); - - G_OBJECT_CLASS(nm_lldp_listener_parent_class)->dispose(object); -} - -static void -finalize(GObject *object) -{ - NMLldpListener * self = NM_LLDP_LISTENER(object); - NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE(self); - - nm_lldp_listener_stop(self); - - nm_clear_g_variant(&priv->variant); + nm_g_variant_unref(self->variant); _LOGT("lldp listener destroyed"); - G_OBJECT_CLASS(nm_lldp_listener_parent_class)->finalize(object); -} - -static void -nm_lldp_listener_class_init(NMLldpListenerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - - object_class->dispose = dispose; - object_class->finalize = finalize; - object_class->get_property = get_property; - - obj_properties[PROP_NEIGHBORS] = - g_param_spec_variant(NM_LLDP_LISTENER_NEIGHBORS, - "", - "", - G_VARIANT_TYPE("aa{sv}"), - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); + nm_g_slice_free(self); } diff --git a/src/core/devices/nm-lldp-listener.h b/src/core/devices/nm-lldp-listener.h index 9d3e243685..762eb3d21a 100644 --- a/src/core/devices/nm-lldp-listener.h +++ b/src/core/devices/nm-lldp-listener.h @@ -6,28 +6,21 @@ #ifndef __NM_LLDP_LISTENER__ #define __NM_LLDP_LISTENER__ -#define NM_TYPE_LLDP_LISTENER (nm_lldp_listener_get_type()) -#define NM_LLDP_LISTENER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_LLDP_LISTENER, NMLldpListener)) -#define NM_LLDP_LISTENER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_LLDP_LISTENER, NMLldpListenerClass)) -#define NM_IS_LLDP_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_LLDP_LISTENER)) -#define NM_IS_LLDP_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_LLDP_LISTENER)) -#define NM_LLDP_LISTENER_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_LLDP_LISTENER, NMLldpListenerClass)) +/*****************************************************************************/ -#define NM_LLDP_LISTENER_NEIGHBORS "neighbors" +typedef void (*NMLldpListenerNotify)(NMLldpListener *self, gpointer user_data); -typedef struct _NMLldpListenerClass NMLldpListenerClass; - -GType nm_lldp_listener_get_type(void); -NMLldpListener *nm_lldp_listener_new(void); -gboolean nm_lldp_listener_start(NMLldpListener *self, int ifindex, GError **error); -void nm_lldp_listener_stop(NMLldpListener *self); -gboolean nm_lldp_listener_is_running(NMLldpListener *self); +NMLldpListener *nm_lldp_listener_new(int ifindex, + NMLldpListenerNotify notify_callback, + gpointer notify_user_data, + GError ** error); +void nm_lldp_listener_destroy(NMLldpListener *self); +int nm_lldp_listener_get_ifindex(NMLldpListener *self); GVariant *nm_lldp_listener_get_neighbors(NMLldpListener *self); +/*****************************************************************************/ + GVariant *nmtst_lldp_parse_from_raw(const guint8 *raw_data, gsize raw_len); #endif /* __NM_LLDP_LISTENER__ */ diff --git a/src/core/devices/tests/test-lldp.c b/src/core/devices/tests/test-lldp.c index ef0b154903..fd0deae4d0 100644 --- a/src/core/devices/tests/test-lldp.c +++ b/src/core/devices/tests/test-lldp.c @@ -83,6 +83,7 @@ typedef struct { const uint8_t *frame; const char * as_variant; } TestRecvFrame; + #define TEST_RECV_FRAME_DEFINE(name, _as_variant, ...) \ static const guint8 _##name##_v[] = {__VA_ARGS__}; \ static const TestRecvFrame name = { \ @@ -91,12 +92,18 @@ typedef struct { .frame = _##name##_v, \ } +typedef struct { + int num_called; + GMainLoop *loop_to_quit; +} TestRecvCallbackInfo; + typedef struct { guint expected_num_called; gsize frames_len; const TestRecvFrame *frames[10]; - void (*check)(GMainLoop *loop, NMLldpListener *listener); + void (*check)(GMainLoop *loop, NMLldpListener *listener, TestRecvCallbackInfo *info); } TestRecvData; + #define TEST_RECV_DATA_DEFINE(name, _expected_num_called, _check, ...) \ static const TestRecvData name = { \ .expected_num_called = _expected_num_called, \ @@ -213,7 +220,7 @@ _test_recv_data0_check_do(GMainLoop *loop, NMLldpListener *listener, const TestR } static void -_test_recv_data0_check(GMainLoop *loop, NMLldpListener *listener) +_test_recv_data0_check(GMainLoop *loop, NMLldpListener *listener, TestRecvCallbackInfo *info) { _test_recv_data0_check_do(loop, listener, &_test_recv_data0_frame0); } @@ -528,7 +535,7 @@ TEST_RECV_FRAME_DEFINE( ); static void -_test_recv_data1_check(GMainLoop *loop, NMLldpListener *listener) +_test_recv_data1_check(GMainLoop *loop, NMLldpListener *listener, TestRecvCallbackInfo *info) { GVariant * neighbors, *attr, *child; gs_unref_variant GVariant *neighbor = NULL; @@ -756,21 +763,17 @@ TEST_RECV_FRAME_DEFINE( ); static void -_test_recv_data2_ttl1_check(GMainLoop *loop, NMLldpListener *listener) +_test_recv_data2_ttl1_check(GMainLoop *loop, NMLldpListener *listener, TestRecvCallbackInfo *info) { - gulong notify_id; GVariant *neighbors; _test_recv_data0_check_do(loop, listener, &_test_recv_data2_frame0_ttl1); /* wait for signal. */ - notify_id = g_signal_connect(listener, - "notify::" NM_LLDP_LISTENER_NEIGHBORS, - nmtst_main_loop_quit_on_notify, - loop); + info->loop_to_quit = loop; if (!nmtst_main_loop_run(loop, 5000)) g_assert_not_reached(); - nm_clear_g_signal_handler(listener, ¬ify_id); + info->loop_to_quit = NULL; neighbors = nm_lldp_listener_get_neighbors(listener); nmtst_assert_variant_is_of_type(neighbors, G_VARIANT_TYPE("aa{sv}")); @@ -852,46 +855,37 @@ again: memcpy(fixture->mac, link->l_address.data, ETH_ALEN); } -typedef struct { - int num_called; -} TestRecvCallbackInfo; - static void -lldp_neighbors_changed(NMLldpListener *lldp_listener, GParamSpec *pspec, gpointer user_data) +lldp_neighbors_changed(NMLldpListener *lldp_listener, gpointer user_data) { TestRecvCallbackInfo *info = user_data; info->num_called++; + if (info->loop_to_quit) + g_main_loop_quit(info->loop_to_quit); } static void test_recv(TestRecvFixture *fixture, gconstpointer user_data) { - const TestRecvData *data = user_data; - gs_unref_object NMLldpListener *listener = NULL; - GMainLoop * loop; - TestRecvCallbackInfo info = {}; - gsize i_frames; - gulong notify_id; - GError * error = NULL; - guint sd_id; + const TestRecvData * data = user_data; + NMLldpListener * listener; + GMainLoop * loop; + TestRecvCallbackInfo info = {}; + gsize i_frames; + GError * error = NULL; + guint sd_id; if (fixture->ifindex == 0) { g_test_skip("Tun device not available"); return; } - listener = nm_lldp_listener_new(); - g_assert(listener != NULL); - g_assert(nm_lldp_listener_start(listener, fixture->ifindex, &error)); - g_assert_no_error(error); + listener = nm_lldp_listener_new(fixture->ifindex, lldp_neighbors_changed, &info, &error); + nmtst_assert_success(listener, error); - notify_id = g_signal_connect(listener, - "notify::" NM_LLDP_LISTENER_NEIGHBORS, - (GCallback) lldp_neighbors_changed, - &info); - loop = g_main_loop_new(NULL, FALSE); - sd_id = nm_sd_event_attach_default(); + loop = g_main_loop_new(NULL, FALSE); + sd_id = nm_sd_event_attach_default(); for (i_frames = 0; i_frames < data->frames_len; i_frames++) { const TestRecvFrame *f = data->frames[i_frames]; @@ -904,9 +898,9 @@ test_recv(TestRecvFixture *fixture, gconstpointer user_data) g_assert_cmpint(info.num_called, ==, data->expected_num_called); - nm_clear_g_signal_handler(listener, ¬ify_id); + data->check(loop, listener, &info); - data->check(loop, listener); + nm_clear_pointer(&listener, nm_lldp_listener_destroy); nm_clear_g_source(&sd_id); nm_clear_pointer(&loop, g_main_loop_unref);