From 74dfc86aa451985283abb7e617aadd9a18aef88f Mon Sep 17 00:00:00 2001 From: Fernando Fernandez Mancera Date: Wed, 6 Oct 2021 16:12:58 +0200 Subject: [PATCH] libnm: introduce nm_device_get_ports() to NMDevice This patch is introducing a "ports" property to NMDevice. In addition it is introducing nm_device_get_ports() and deprecating nm_device_bond_get_slaves(), nm_device_bridge_get_slaves(), nm_device_ovs_bridge_get_slaves(), nm_device_ovs_interface_get_slaves() and nm_device_team_get_slaves(). Signed-off-by: Fernando Fernandez Mancera --- src/libnm-client-impl/libnm.ver | 1 + src/libnm-client-impl/nm-device-bond.c | 22 +++-- src/libnm-client-impl/nm-device-bridge.c | 22 +++-- src/libnm-client-impl/nm-device-ovs-bridge.c | 44 ++++----- src/libnm-client-impl/nm-device-ovs-port.c | 44 ++++----- src/libnm-client-impl/nm-device-team.c | 24 +++-- src/libnm-client-impl/nm-device.c | 95 +++++++++++++++++++- src/libnm-client-impl/nm-libnm-utils.h | 53 ++++++----- src/libnm-client-impl/tests/test-libnm.c | 5 ++ src/libnm-client-public/nm-device-bond.h | 4 +- src/libnm-client-public/nm-device-bridge.h | 4 +- src/libnm-client-public/nm-device.h | 4 + 12 files changed, 208 insertions(+), 114 deletions(-) diff --git a/src/libnm-client-impl/libnm.ver b/src/libnm-client-impl/libnm.ver index 3d033ea92a..497e3a0846 100644 --- a/src/libnm-client-impl/libnm.ver +++ b/src/libnm-client-impl/libnm.ver @@ -1807,6 +1807,7 @@ global: libnm_1_34_0 { global: + nm_device_get_ports; nm_ip_routing_rule_get_uid_range; nm_ip_routing_rule_set_uid_range; nm_setting_bond_port_get_queue_id; diff --git a/src/libnm-client-impl/nm-device-bond.c b/src/libnm-client-impl/nm-device-bond.c index 579cc2f4a1..add5463999 100644 --- a/src/libnm-client-impl/nm-device-bond.c +++ b/src/libnm-client-impl/nm-device-bond.c @@ -18,8 +18,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_CARRIER, PROP_SLAVES, ); typedef struct { - NMLDBusPropertyAO slaves; - bool carrier; + bool carrier; } NMDeviceBondPrivate; struct _NMDeviceBond { @@ -82,13 +81,13 @@ nm_device_bond_get_carrier(NMDeviceBond *device) * Returns: (element-type NMDevice): the #GPtrArray containing * #NMDevices that are slaves of @device. This is the internal * copy used by the device, and must not be modified. + * + * Deprecated: 1.34 Use nm_device_get_ports() instead. **/ const GPtrArray * nm_device_bond_get_slaves(NMDeviceBond *device) { - g_return_val_if_fail(NM_IS_DEVICE_BOND(device), FALSE); - - return nml_dbus_property_ao_get_objs_as_ptrarray(&NM_DEVICE_BOND_GET_PRIVATE(device)->slaves); + return nm_device_get_ports(NM_DEVICE(device)); } static gboolean @@ -151,11 +150,10 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bond = NML_DBUS_META_IFACE 0, "s", _nm_device_notify_update_prop_hw_address), - NML_DBUS_META_PROPERTY_INIT_AO_PROP("Slaves", - PROP_SLAVES, - NMDeviceBond, - _priv.slaves, - nm_device_get_type), ), ); + NML_DBUS_META_PROPERTY_INIT_FCN("Slaves", + PROP_SLAVES, + "ao", + _nm_device_notify_update_prop_ports), ), ); static void nm_device_bond_class_init(NMDeviceBondClass *klass) @@ -168,8 +166,6 @@ nm_device_bond_class_init(NMDeviceBondClass *klass) _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT(nm_object_class, NMDeviceBond); - _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1(nm_object_class, NMDeviceBondPrivate, slaves); - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -196,4 +192,6 @@ nm_device_bond_class_init(NMDeviceBondClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); _nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_device_bond); + + device_class->slaves_param_spec = obj_properties[PROP_SLAVES]; } diff --git a/src/libnm-client-impl/nm-device-bridge.c b/src/libnm-client-impl/nm-device-bridge.c index 9bc41ac896..fb0ad873da 100644 --- a/src/libnm-client-impl/nm-device-bridge.c +++ b/src/libnm-client-impl/nm-device-bridge.c @@ -18,8 +18,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_CARRIER, PROP_SLAVES, ); typedef struct { - NMLDBusPropertyAO slaves; - bool carrier; + bool carrier; } NMDeviceBridgePrivate; struct _NMDeviceBridge { @@ -82,13 +81,13 @@ nm_device_bridge_get_carrier(NMDeviceBridge *device) * Returns: (element-type NMDevice): the #GPtrArray containing * #NMDevices that are slaves of @device. This is the internal * copy used by the device, and must not be modified. + * + * Deprecated: 1.34 Use nm_device_get_ports() instead. **/ const GPtrArray * nm_device_bridge_get_slaves(NMDeviceBridge *device) { - g_return_val_if_fail(NM_IS_DEVICE_BRIDGE(device), FALSE); - - return nml_dbus_property_ao_get_objs_as_ptrarray(&NM_DEVICE_BRIDGE_GET_PRIVATE(device)->slaves); + return nm_device_get_ports(NM_DEVICE(device)); } static gboolean @@ -156,11 +155,10 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_bridge = NML_DBUS_META_IFA 0, "s", _nm_device_notify_update_prop_hw_address), - NML_DBUS_META_PROPERTY_INIT_AO_PROP("Slaves", - PROP_SLAVES, - NMDeviceBridge, - _priv.slaves, - nm_device_get_type), ), ); + NML_DBUS_META_PROPERTY_INIT_FCN("Slaves", + PROP_SLAVES, + "ao", + _nm_device_notify_update_prop_ports), ), ); static void nm_device_bridge_class_init(NMDeviceBridgeClass *klass) @@ -173,8 +171,6 @@ nm_device_bridge_class_init(NMDeviceBridgeClass *klass) _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT(nm_object_class, NMDeviceBridge); - _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1(nm_object_class, NMDeviceBridgePrivate, slaves); - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -201,4 +197,6 @@ nm_device_bridge_class_init(NMDeviceBridgeClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); _nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_device_bridge); + + device_class->slaves_param_spec = obj_properties[PROP_SLAVES]; } diff --git a/src/libnm-client-impl/nm-device-ovs-bridge.c b/src/libnm-client-impl/nm-device-ovs-bridge.c index 898a41fab5..465957c456 100644 --- a/src/libnm-client-impl/nm-device-ovs-bridge.c +++ b/src/libnm-client-impl/nm-device-ovs-bridge.c @@ -17,13 +17,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_SLAVES, ); -typedef struct { - NMLDBusPropertyAO slaves; -} NMDeviceOvsBridgePrivate; - struct _NMDeviceOvsBridge { - NMDevice parent; - NMDeviceOvsBridgePrivate _priv; + NMDevice parent; }; struct _NMDeviceOvsBridgeClass { @@ -48,14 +43,13 @@ G_DEFINE_TYPE(NMDeviceOvsBridge, nm_device_ovs_bridge, NM_TYPE_DEVICE) * copy used by the device, and must not be modified. * * Since: 1.14 + * + * Deprecated: 1.34 Use nm_device_get_ports() instead. **/ const GPtrArray * nm_device_ovs_bridge_get_slaves(NMDeviceOvsBridge *device) { - g_return_val_if_fail(NM_IS_DEVICE_OVS_BRIDGE(device), FALSE); - - return nml_dbus_property_ao_get_objs_as_ptrarray( - &NM_DEVICE_OVS_BRIDGE_GET_PRIVATE(device)->slaves); + return nm_device_get_ports(NM_DEVICE(device)); } static const char * @@ -123,30 +117,24 @@ static void nm_device_ovs_bridge_init(NMDeviceOvsBridge *device) {} -const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsbridge = - NML_DBUS_META_IFACE_INIT_PROP(NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE, - nm_device_ovs_bridge_get_type, - NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30, - NML_DBUS_META_IFACE_DBUS_PROPERTIES( - NML_DBUS_META_PROPERTY_INIT_AO_PROP("Slaves", - PROP_SLAVES, - NMDeviceOvsBridge, - _priv.slaves, - nm_device_get_type), ), ); +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsbridge = NML_DBUS_META_IFACE_INIT_PROP( + NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE, + nm_device_ovs_bridge_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30, + NML_DBUS_META_IFACE_DBUS_PROPERTIES( + NML_DBUS_META_PROPERTY_INIT_FCN("Slaves", + PROP_SLAVES, + "ao", + _nm_device_notify_update_prop_ports), ), ); static void nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS(klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; - _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT(nm_object_class, NMDeviceOvsBridge); - - _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1(nm_object_class, NMDeviceOvsBridgePrivate, slaves); - device_class->get_type_description = get_type_description; device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -166,4 +154,6 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass) _nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_device_ovsbridge); + + device_class->slaves_param_spec = obj_properties[PROP_SLAVES]; } diff --git a/src/libnm-client-impl/nm-device-ovs-port.c b/src/libnm-client-impl/nm-device-ovs-port.c index db30e1c7c8..76ae7a584b 100644 --- a/src/libnm-client-impl/nm-device-ovs-port.c +++ b/src/libnm-client-impl/nm-device-ovs-port.c @@ -17,13 +17,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_SLAVES, ); -typedef struct { - NMLDBusPropertyAO slaves; -} NMDeviceOvsPortPrivate; - struct _NMDeviceOvsPort { - NMDevice parent; - NMDeviceOvsPortPrivate _priv; + NMDevice parent; }; struct _NMDeviceOvsPortClass { @@ -48,14 +43,13 @@ G_DEFINE_TYPE(NMDeviceOvsPort, nm_device_ovs_port, NM_TYPE_DEVICE) * copy used by the device, and must not be modified. * * Since: 1.14 + * + * Deprecated: 1.34 Use nm_device_get_ports() instead. **/ const GPtrArray * nm_device_ovs_port_get_slaves(NMDeviceOvsPort *device) { - g_return_val_if_fail(NM_IS_DEVICE_OVS_PORT(device), FALSE); - - return nml_dbus_property_ao_get_objs_as_ptrarray( - &NM_DEVICE_OVS_PORT_GET_PRIVATE(device)->slaves); + return nm_device_get_ports(NM_DEVICE(device)); } static const char * @@ -123,30 +117,24 @@ static void nm_device_ovs_port_init(NMDeviceOvsPort *device) {} -const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsport = - NML_DBUS_META_IFACE_INIT_PROP(NM_DBUS_INTERFACE_DEVICE_OVS_PORT, - nm_device_ovs_port_get_type, - NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30, - NML_DBUS_META_IFACE_DBUS_PROPERTIES( - NML_DBUS_META_PROPERTY_INIT_AO_PROP("Slaves", - PROP_SLAVES, - NMDeviceOvsPort, - _priv.slaves, - nm_device_get_type), ), ); +const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_ovsport = NML_DBUS_META_IFACE_INIT_PROP( + NM_DBUS_INTERFACE_DEVICE_OVS_PORT, + nm_device_ovs_port_get_type, + NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_30, + NML_DBUS_META_IFACE_DBUS_PROPERTIES( + NML_DBUS_META_PROPERTY_INIT_FCN("Slaves", + PROP_SLAVES, + "ao", + _nm_device_notify_update_prop_ports), ), ); static void nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass) { - GObjectClass * object_class = G_OBJECT_CLASS(klass); - NMObjectClass *nm_object_class = NM_OBJECT_CLASS(klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); + GObjectClass * object_class = G_OBJECT_CLASS(klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS(klass); object_class->get_property = get_property; - _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT(nm_object_class, NMDeviceOvsPort); - - _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1(nm_object_class, NMDeviceOvsPortPrivate, slaves); - device_class->get_type_description = get_type_description; device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -166,4 +154,6 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass) _nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_device_ovsport); + + device_class->slaves_param_spec = obj_properties[PROP_SLAVES]; } diff --git a/src/libnm-client-impl/nm-device-team.c b/src/libnm-client-impl/nm-device-team.c index ca29c9f7b9..9f7fe76810 100644 --- a/src/libnm-client-impl/nm-device-team.c +++ b/src/libnm-client-impl/nm-device-team.c @@ -18,9 +18,8 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_CARRIER, PROP_SLAVES, PROP_CONFIG, ); typedef struct { - NMLDBusPropertyAO slaves; - char * config; - bool carrier; + char *config; + bool carrier; } NMDeviceTeamPrivate; struct _NMDeviceTeam { @@ -83,13 +82,13 @@ nm_device_team_get_carrier(NMDeviceTeam *device) * Returns: (element-type NMDevice): the #GPtrArray containing * #NMDevices that are slaves of @device. This is the internal * copy used by the device, and must not be modified. + * + * Deprecated: 1.34 Use nm_device_get_ports() instead. **/ const GPtrArray * nm_device_team_get_slaves(NMDeviceTeam *device) { - g_return_val_if_fail(NM_IS_DEVICE_TEAM(device), FALSE); - - return nml_dbus_property_ao_get_objs_as_ptrarray(&NM_DEVICE_TEAM_GET_PRIVATE(device)->slaves); + return nm_device_get_ports(NM_DEVICE(device)); } /** @@ -185,11 +184,10 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device_team = NML_DBUS_META_IFACE 0, "s", _nm_device_notify_update_prop_hw_address), - NML_DBUS_META_PROPERTY_INIT_AO_PROP("Slaves", - PROP_SLAVES, - NMDeviceTeam, - _priv.slaves, - nm_device_get_type), ), ); + NML_DBUS_META_PROPERTY_INIT_FCN("Slaves", + PROP_SLAVES, + "ao", + _nm_device_notify_update_prop_ports), ), ); static void nm_device_team_class_init(NMDeviceTeamClass *klass) @@ -203,8 +201,6 @@ nm_device_team_class_init(NMDeviceTeamClass *klass) _NM_OBJECT_CLASS_INIT_PRIV_PTR_DIRECT(nm_object_class, NMDeviceTeam); - _NM_OBJECT_CLASS_INIT_PROPERTY_AO_FIELDS_1(nm_object_class, NMDeviceTeamPrivate, slaves); - device_class->connection_compatible = connection_compatible; device_class->get_setting_type = get_setting_type; @@ -244,4 +240,6 @@ nm_device_team_class_init(NMDeviceTeamClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); _nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_device_team); + + device_class->slaves_param_spec = obj_properties[PROP_SLAVES]; } diff --git a/src/libnm-client-impl/nm-device.c b/src/libnm-client-impl/nm-device.c index 6123fc5956..a680a05f9c 100644 --- a/src/libnm-client-impl/nm-device.c +++ b/src/libnm-client-impl/nm-device.c @@ -61,7 +61,8 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice, PROP_IP4_CONNECTIVITY, PROP_IP6_CONNECTIVITY, PROP_INTERFACE_FLAGS, - PROP_HW_ADDRESS, ); + PROP_HW_ADDRESS, + PROP_PORTS, ); enum { STATE_CHANGED, @@ -82,6 +83,7 @@ enum { enum { PROPERTY_AO_IDX_AVAILABLE_CONNECTIONS, + PROPERTY_AO_IDX_PORTS, _PROPERTY_AO_IDX_NUM, }; @@ -114,6 +116,7 @@ typedef struct _NMDevicePrivate { bool real; bool hw_address_is_new : 1; + bool ports_is_new : 1; guint32 old_state; @@ -462,6 +465,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) case PROP_HW_ADDRESS: g_value_set_string(value, nm_device_get_hw_address(device)); break; + case PROP_PORTS: + g_value_take_boxed(value, _nm_utils_copy_object_array(nm_device_get_ports(device))); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -593,6 +599,15 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device = NML_DBUS_META_IFACE_INIT PROP_PHYSICAL_PORT_ID, NMDevicePrivate, physical_port_id), + NML_DBUS_META_PROPERTY_INIT_FCN( + "Ports", + PROP_PORTS, + "ao", + _nm_device_notify_update_prop_ports, + .prop_struct_offset = + G_STRUCT_OFFSET(NMDevicePrivate, property_ao[PROPERTY_AO_IDX_PORTS]), + .extra.property_vtable_ao = + &((const NMLDBusPropertVTableAO){.get_o_type_fcn = (nm_device_get_type)})), NML_DBUS_META_PROPERTY_INIT_B("Real", PROP_REAL, NMDevicePrivate, real), NML_DBUS_META_PROPERTY_INIT_IGNORE("State", "u"), NML_DBUS_META_PROPERTY_INIT_FCN("StateReason", @@ -600,6 +615,7 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_device = NML_DBUS_META_IFACE_INIT "(uu)", _notify_update_prop_state_reason), NML_DBUS_META_PROPERTY_INIT_S("Udi", PROP_UDI, NMDevicePrivate, udi), ), + .base_struct_offset = G_STRUCT_OFFSET(NMDevice, _priv), ); static void @@ -1037,6 +1053,20 @@ nm_device_class_init(NMDeviceClass *klass) NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + /** + * NMDevice:ports: + * + * The port devices of the controller device. For devices that cannot be + * controllers this is likely to be always empty. + * + * Since: 1.34 + **/ + obj_properties[PROP_PORTS] = g_param_spec_boxed(NM_DEVICE_PORTS, + "", + "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + _nml_dbus_meta_class_init_with_properties(object_class, &_nml_dbus_meta_iface_nm_device); /** @@ -1244,6 +1274,27 @@ nm_device_get_type_description(NMDevice *device) return _nml_coerce_property_str_not_empty(priv->type_description); } +/** + * nm_device_get_ports: + * @device: a #NMDevice + * + * Gets the devices currently set as port of @device. + * + * Returns: (element-type NMDevice): the #GPtrArray containing #NMDevices that + * are slaves of @device. This is the internal copy used by the device and + * must not be modified. + * + * Since: 1.34 + **/ +const GPtrArray * +nm_device_get_ports(NMDevice *device) +{ + g_return_val_if_fail(NM_IS_DEVICE(device), NULL); + + return nml_dbus_property_ao_get_objs_as_ptrarray( + &NM_DEVICE_GET_PRIVATE(device)->property_ao[PROPERTY_AO_IDX_PORTS]); +} + NMLDBusNotifyUpdatePropFlags _nm_device_notify_update_prop_hw_address(NMClient * client, NMLDBusObject * dbobj, @@ -1308,6 +1359,48 @@ nm_device_get_hw_address(NMDevice *device) return priv->hw_address; } +NMLDBusNotifyUpdatePropFlags +_nm_device_notify_update_prop_ports(NMClient * client, + NMLDBusObject * dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant * value) +{ + const NMLDBusMetaProperty *meta_property = + &_nml_dbus_meta_iface_nm_device.dbus_properties[_NML_DEVICE_META_PROPERTY_INDEX_PORTS]; + NMLDBusNotifyUpdatePropFlags notify_update_prop_flags; + NMDevice * self = NM_DEVICE(dbobj->nmobj); + NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + NMDeviceClass * klass; + gboolean is_new = (meta_iface == &_nml_dbus_meta_iface_nm_device); + + nm_assert(nm_streq(meta_property->dbus_property_name, "Ports")); + + if (!is_new && priv->ports_is_new) { + /* once the instance is marked to honor the new property, the + * changed signal for the old variant gets ignored. */ + goto out; + } + priv->ports_is_new = is_new; + + notify_update_prop_flags = + nml_dbus_property_ao_notify(client, + &priv->property_ao[PROPERTY_AO_IDX_PORTS], + dbobj, + &_nml_dbus_meta_iface_nm_device, + _NML_DEVICE_META_PROPERTY_INDEX_PORTS, + value); + if (notify_update_prop_flags == NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE) + goto out; + nm_assert(notify_update_prop_flags == NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NOTIFY); + + klass = NM_DEVICE_GET_CLASS(self); + if (klass->slaves_param_spec) + _nm_client_queue_notify_object(client, self, klass->slaves_param_spec); +out: + return NML_DBUS_NOTIFY_UPDATE_PROP_FLAGS_NONE; +} + /** * nm_device_get_capabilities: * @device: a #NMDevice diff --git a/src/libnm-client-impl/nm-libnm-utils.h b/src/libnm-client-impl/nm-libnm-utils.h index 9b50bf42f7..75e8706471 100644 --- a/src/libnm-client-impl/nm-libnm-utils.h +++ b/src/libnm-client-impl/nm-libnm-utils.h @@ -398,16 +398,16 @@ typedef struct { #define NML_DBUS_META_PROPERTY_INIT_AY(...) \ _NML_DBUS_META_PROPERTY_INIT_DEFAULT("ay", GBytes *, __VA_ARGS__) -#define NML_DBUS_META_PROPERTY_INIT_O(v_dbus_property_name, \ - v_obj_properties_idx, \ - v_container, \ - v_field) \ - NML_DBUS_META_PROPERTY_INIT( \ - v_dbus_property_name, \ - "o", \ - v_obj_properties_idx, \ - .prop_struct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE(NMRefString *, v_container, v_field), \ - .notify_update_prop = _nml_dbus_notify_update_prop_o) +#define NML_DBUS_META_PROPERTY_INIT_O(v_dbus_property_name, \ + v_obj_properties_idx, \ + v_container, \ + v_field) \ + NML_DBUS_META_PROPERTY_INIT( \ + v_dbus_property_name, \ + "o", \ + v_obj_properties_idx, \ + .prop_struct_offset = NM_STRUCT_OFFSET_ENSURE_TYPE(NMRefString *, v_container, v_field), \ + .notify_update_prop = _nml_dbus_notify_update_prop_o) #define NML_DBUS_META_PROPERTY_INIT_O_PROP(v_dbus_property_name, \ v_obj_properties_idx, \ @@ -439,22 +439,22 @@ typedef struct { .extra.property_vtable_ao = &( \ (const NMLDBusPropertVTableAO){.get_o_type_fcn = (v_get_o_type_fcn), ##__VA_ARGS__})) -#define NML_DBUS_META_PROPERTY_INIT_FCN(v_dbus_property_name, \ - v_obj_properties_idx, \ - v_dbus_type, \ - v_notify_update_prop, \ - ...) \ - NML_DBUS_META_PROPERTY_INIT(v_dbus_property_name, \ - v_dbus_type, \ - v_obj_properties_idx, \ - .notify_update_prop = (v_notify_update_prop), \ +#define NML_DBUS_META_PROPERTY_INIT_FCN(v_dbus_property_name, \ + v_obj_properties_idx, \ + v_dbus_type, \ + v_notify_update_prop, \ + ...) \ + NML_DBUS_META_PROPERTY_INIT(v_dbus_property_name, \ + v_dbus_type, \ + v_obj_properties_idx, \ + .notify_update_prop = (v_notify_update_prop), \ ##__VA_ARGS__) #define NML_DBUS_META_PROPERTY_INIT_IGNORE(v_dbus_property_name, v_dbus_type) \ NML_DBUS_META_PROPERTY_INIT(v_dbus_property_name, \ v_dbus_type, \ 0, \ - .notify_update_prop = _nml_dbus_notify_update_prop_ignore) + .notify_update_prop = _nml_dbus_notify_update_prop_ignore) /* "TODO" is like "IGNORE". The difference is that we don't plan to ever implement "IGNORE", but * "TODO" is something we should add support for. */ @@ -828,8 +828,15 @@ struct _NMDeviceClass { const char *(*get_type_description)(NMDevice *device); GType (*get_setting_type)(NMDevice *device); + + /* Slaves was originally part of some subtypes of NMDevice. It was deprecated and + * a new NMDevice::ports property was added. When that property changes, we need + * to notify about the subclass' respective property. This is the property. */ + const GParamSpec *slaves_param_spec; }; +#define _NML_DEVICE_META_PROPERTY_INDEX_PORTS 27 + /*****************************************************************************/ struct _NMDeviceEthernetPrivate; @@ -1033,6 +1040,12 @@ _nm_device_notify_update_prop_hw_address(NMClient * client, guint dbus_property_idx, GVariant * value); +NMLDBusNotifyUpdatePropFlags _nm_device_notify_update_prop_ports(NMClient * client, + NMLDBusObject * dbobj, + const NMLDBusMetaIface *meta_iface, + guint dbus_property_idx, + GVariant *value); + /*****************************************************************************/ #endif /* __NM_LIBNM_UTILS_H__ */ diff --git a/src/libnm-client-impl/tests/test-libnm.c b/src/libnm-client-impl/tests/test-libnm.c index 7ebc3690c0..29ffde97d5 100644 --- a/src/libnm-client-impl/tests/test-libnm.c +++ b/src/libnm-client-impl/tests/test-libnm.c @@ -2837,6 +2837,11 @@ test_nml_dbus_meta(void) g_assert((mif->n_dbus_properties > 0) == (!!mif->dbus_properties)); + if (nm_streq(mif->dbus_iface_name, "org.freedesktop.NetworkManager.Device")) + g_assert(nm_streq( + mif->dbus_properties[_NML_DEVICE_META_PROPERTY_INDEX_PORTS].dbus_property_name, + "Ports")); + if (mif->interface_prio == NML_DBUS_META_INTERFACE_PRIO_NONE) { g_assert(!mif->get_type_fcn); g_assert(!mif->obj_properties); diff --git a/src/libnm-client-public/nm-device-bond.h b/src/libnm-client-public/nm-device-bond.h index 448d877901..19e0e04638 100644 --- a/src/libnm-client-public/nm-device-bond.h +++ b/src/libnm-client-public/nm-device-bond.h @@ -37,7 +37,9 @@ GType nm_device_bond_get_type(void); NM_DEPRECATED_IN_1_24_FOR(nm_device_get_hw_address) const char *nm_device_bond_get_hw_address(NMDeviceBond *device); -gboolean nm_device_bond_get_carrier(NMDeviceBond *device); +gboolean nm_device_bond_get_carrier(NMDeviceBond *device); + +NM_DEPRECATED_IN_1_34_FOR(nm_device_get_ports) const GPtrArray *nm_device_bond_get_slaves(NMDeviceBond *device); G_END_DECLS diff --git a/src/libnm-client-public/nm-device-bridge.h b/src/libnm-client-public/nm-device-bridge.h index 765f400531..07905195b7 100644 --- a/src/libnm-client-public/nm-device-bridge.h +++ b/src/libnm-client-public/nm-device-bridge.h @@ -38,7 +38,9 @@ GType nm_device_bridge_get_type(void); NM_DEPRECATED_IN_1_24_FOR(nm_device_get_hw_address) const char *nm_device_bridge_get_hw_address(NMDeviceBridge *device); -gboolean nm_device_bridge_get_carrier(NMDeviceBridge *device); +gboolean nm_device_bridge_get_carrier(NMDeviceBridge *device); + +NM_DEPRECATED_IN_1_34_FOR(nm_device_get_ports) const GPtrArray *nm_device_bridge_get_slaves(NMDeviceBridge *device); G_END_DECLS diff --git a/src/libnm-client-public/nm-device.h b/src/libnm-client-public/nm-device.h index b98f594bb5..23b1a805d3 100644 --- a/src/libnm-client-public/nm-device.h +++ b/src/libnm-client-public/nm-device.h @@ -57,6 +57,7 @@ _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY #define NM_DEVICE_IP6_CONNECTIVITY "ip6-connectivity" #define NM_DEVICE_INTERFACE_FLAGS "interface-flags" #define NM_DEVICE_HW_ADDRESS "hw-address" +#define NM_DEVICE_PORTS "ports" /** * NMDevice: @@ -141,6 +142,9 @@ const char * nm_device_get_hw_address(NMDevice *device); NMDeviceCapabilities nm_device_get_capabilities(NMDevice *device); gboolean nm_device_get_managed(NMDevice *device); +NM_AVAILABLE_IN_1_34 +const GPtrArray *nm_device_get_ports(NMDevice *device); + NM_AVAILABLE_IN_1_2 NM_DEPRECATED_IN_1_22 _NM_DEPRECATED_SYNC_METHOD