libnm: add LLDP support

Add functions to libnm for retrieving a list of LLDP neighbors and
accessor functions to get their attributes.
This commit is contained in:
Beniamino Galvani 2015-10-07 11:48:44 +02:00
parent 07a9364d9c
commit d3d2b49400
3 changed files with 287 additions and 0 deletions

View file

@ -859,11 +859,19 @@ libnm_1_2_0 {
global:
nm_access_point_get_last_seen;
nm_device_ethernet_get_s390_subchannels;
nm_device_get_lldp_neighbors;
nm_device_get_metered;
nm_device_get_nm_plugin_missing;
nm_device_set_managed;
nm_device_wifi_request_scan_options;
nm_device_wifi_request_scan_options_async;
nm_lldp_neighbor_get_attr_names;
nm_lldp_neighbor_get_attr_string_value;
nm_lldp_neighbor_get_attr_type;
nm_lldp_neighbor_get_attr_uint_value;
nm_lldp_neighbor_new;
nm_lldp_neighbor_ref;
nm_lldp_neighbor_unref;
nm_metered_get_type;
nm_setting_802_1x_check_cert_scheme;
nm_setting_bridge_get_multicast_snooping;

View file

@ -105,6 +105,7 @@ typedef struct {
char *physical_port_id;
guint32 mtu;
GPtrArray *lldp_neighbors;
} NMDevicePrivate;
enum {
@ -134,6 +135,7 @@ enum {
PROP_PHYSICAL_PORT_ID,
PROP_MTU,
PROP_METERED,
PROP_LLDP_NEIGHBORS,
LAST_PROP
};
@ -146,6 +148,11 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
struct _NMLldpNeighbor {
guint refcount;
GHashTable *attrs;
};
static void
nm_device_init (NMDevice *device)
{
@ -153,6 +160,7 @@ nm_device_init (NMDevice *device)
priv->state = NM_DEVICE_STATE_UNKNOWN;
priv->reason = NM_DEVICE_STATE_REASON_NONE;
priv->lldp_neighbors = g_ptr_array_new ();
}
static gboolean
@ -165,6 +173,38 @@ demarshal_state_reason (NMObject *object, GParamSpec *pspec, GVariant *value, gp
return TRUE;
}
static gboolean
demarshal_lldp_neighbors (NMObject *object, GParamSpec *pspec, GVariant *value, gpointer field)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
GVariantIter iter, attrs_iter;
GVariant *variant, *attr_variant;
const char *attr_name;
g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), FALSE);
g_ptr_array_unref (priv->lldp_neighbors);
priv->lldp_neighbors = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_lldp_neighbor_unref);
g_variant_iter_init (&iter, value);
while (g_variant_iter_next (&iter, "@a{sv}", &variant)) {
NMLldpNeighbor *neigh;
neigh = nm_lldp_neighbor_new ();
g_variant_iter_init (&attrs_iter, variant);
while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant))
g_hash_table_insert (neigh->attrs, g_strdup (attr_name), attr_variant);
g_variant_unref (variant);
g_ptr_array_add (priv->lldp_neighbors, neigh);
}
_nm_object_queue_notify (object, NM_DEVICE_LLDP_NEIGHBORS);
return TRUE;
}
static void
device_state_changed (NMDBusDevice *proxy,
guint new_state,
@ -199,6 +239,7 @@ init_dbus (NMObject *object)
{ NM_DEVICE_PHYSICAL_PORT_ID, &priv->physical_port_id },
{ NM_DEVICE_MTU, &priv->mtu },
{ NM_DEVICE_METERED, &priv->metered },
{ NM_DEVICE_LLDP_NEIGHBORS, &priv->lldp_neighbors, demarshal_lldp_neighbors },
/* Properties that exist in D-Bus but that we don't track */
{ "ip4-address", NULL },
@ -350,6 +391,7 @@ dispose (GObject *object)
g_clear_object (&priv->active_connection);
g_clear_pointer (&priv->available_connections, g_ptr_array_unref);
g_clear_pointer (&priv->lldp_neighbors, g_ptr_array_unref);
G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
}
@ -461,6 +503,9 @@ get_property (GObject *object,
case PROP_METERED:
g_value_set_uint (value, nm_device_get_metered (device));
break;
case PROP_LLDP_NEIGHBORS:
g_value_set_boxed (value, nm_device_get_lldp_neighbors (device));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -839,6 +884,18 @@ nm_device_class_init (NMDeviceClass *device_class)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMDevice:lldp-neighbors:
*
* The LLDP neighbors.
**/
g_object_class_install_property
(object_class, PROP_LLDP_NEIGHBORS,
g_param_spec_boxed (NM_DEVICE_LLDP_NEIGHBORS, "", "",
G_TYPE_PTR_ARRAY,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/* signals */
/**
@ -2010,6 +2067,26 @@ nm_device_get_metered (NMDevice *device)
NM_BACKPORT_SYMBOL (libnm_1_0_6, NMMetered, nm_device_get_metered, (NMDevice *device), (device));
/**
* nm_device_get_lldp_neighbors:
* @device: a #NMDevice
*
* Gets the list of neighbors discovered through LLDP.
*
* Returns: (element-type NMLldpNeighbor) (transfer none): the #GPtrArray
* containing #NMLldpNeighbor<!-- -->s. This is the internal copy used by the
* device and must not be modified.
*
* Since: 1.2
**/
GPtrArray *
nm_device_get_lldp_neighbors (NMDevice *device)
{
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
return NM_DEVICE_GET_PRIVATE (device)->lldp_neighbors;
}
/**
* nm_device_is_software:
* @device: a #NMDevice
@ -2360,3 +2437,182 @@ nm_device_get_setting_type (NMDevice *device)
return NM_DEVICE_GET_CLASS (device)->get_setting_type (device);
}
/**
* nm_lldp_neighbor_new
*
* Creates a new #NMLldpNeighbor object.
*
* Returns: (transfer full): the new #NMLldpNeighbor object.
*
* Since: 1.2
**/
NMLldpNeighbor *
nm_lldp_neighbor_new (void)
{
NMLldpNeighbor *neigh;
neigh = g_new0 (NMLldpNeighbor, 1);
neigh->refcount = 1;
neigh->attrs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify) g_variant_unref);
return neigh;
}
/**
* nm_lldp_neighbor_ref
* @neighbor: the #NMLldpNeighbor
*
* Increases the reference count of the object.
*
* Since: 1.2
**/
void
nm_lldp_neighbor_ref (NMLldpNeighbor *neighbor)
{
g_return_if_fail (neighbor);
g_return_if_fail (neighbor->refcount > 0);
neighbor->refcount++;
}
/**
* nm_lldp_neighbor_unref:
* @neighbor: the #NMLldpNeighbor
*
* Decreases the reference count of the object. If the reference count
* reaches zero, the object will be destroyed.
*
* Since: 1.2
**/
void
nm_lldp_neighbor_unref (NMLldpNeighbor *neighbor)
{
g_return_if_fail (neighbor);
g_return_if_fail (neighbor->refcount > 0);
if (--neighbor->refcount == 0) {
g_return_if_fail (neighbor->attrs);
g_hash_table_unref (neighbor->attrs);
g_free (neighbor);
}
}
/**
* nm_lldp_neighbor_get_attr_names:
* @neighbor: the #NMLldpNeighbor
*
* Gets an array of attribute names available for @neighbor.
*
* Returns: (transfer full): a %NULL-terminated array of attribute names.
*
* Since: 1.2
**/
char **
nm_lldp_neighbor_get_attr_names (NMLldpNeighbor *neighbor)
{
GHashTableIter iter;
const char *key;
GPtrArray *names;
g_return_val_if_fail (neighbor, NULL);
g_return_val_if_fail (neighbor->attrs, NULL);
names = g_ptr_array_new ();
g_hash_table_iter_init (&iter, neighbor->attrs);
while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL))
g_ptr_array_add (names, g_strdup (key));
g_ptr_array_add (names, NULL);
return (char **) g_ptr_array_free (names, FALSE);
}
/**
* nm_lldp_neighbor_get_attr_string_value:
* @neighbor: the #NMLldpNeighbor
* @name: the attribute name
* @out_value: (out) (allow-none) (transfer none): on return, the attribute value
*
* Gets the string value of attribute with name @name on @neighbor
*
* Returns: %TRUE if a string attribute with name @name was found, %FALSE otherwise
*
* Since: 1.2
**/
gboolean
nm_lldp_neighbor_get_attr_string_value (NMLldpNeighbor *neighbor, char *name,
const char **out_value)
{
GVariant *variant;
g_return_val_if_fail (neighbor, FALSE);
g_return_val_if_fail (name && name[0], FALSE);
variant = g_hash_table_lookup (neighbor->attrs, name);
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING)) {
if (out_value)
*out_value = g_variant_get_string (variant, NULL);
return TRUE;
} else
return FALSE;
}
/**
* nm_lldp_neighbor_get_attr_uint_value:
* @neighbor: the #NMLldpNeighbor
* @name: the attribute name
* @out_value: (out) (allow-none) on return, the attribute value
*
* Gets the uint value of attribute with name @name on @neighbor
*
* Returns: %TRUE if a uint attribute with name @name was found, %FALSE otherwise
*
* Since: 1.2
**/
gboolean
nm_lldp_neighbor_get_attr_uint_value (NMLldpNeighbor *neighbor, char *name,
guint *out_value)
{
GVariant *variant;
g_return_val_if_fail (neighbor, FALSE);
g_return_val_if_fail (name && name[0], FALSE);
variant = g_hash_table_lookup (neighbor->attrs, name);
if (variant && g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32)) {
if (out_value)
*out_value = g_variant_get_uint32 (variant);
return TRUE;
} else
return FALSE;
}
/**
* nm_lldp_neighbor_get_attr_type:
* @neighbor: the #NMLldpNeighbor
* @name: the attribute name
*
* Get the type of an attribute.
*
* Returns: the #GVariantType of the attribute with name @name
*
* Since: 1.2
**/
const GVariantType *
nm_lldp_neighbor_get_attr_type (NMLldpNeighbor *neighbor, char *name)
{
GVariant *variant;
g_return_val_if_fail (neighbor, NULL);
g_return_val_if_fail (name && name[0], NULL);
variant = g_hash_table_lookup (neighbor->attrs, name);
if (variant)
return g_variant_get_type (variant);
else
return NULL;
}

View file

@ -62,6 +62,7 @@ G_BEGIN_DECLS
#define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id"
#define NM_DEVICE_MTU "mtu"
#define NM_DEVICE_METERED "metered"
#define NM_DEVICE_LLDP_NEIGHBORS "lldp-neighbors"
struct _NMDevice {
NMObject parent;
@ -90,6 +91,8 @@ typedef struct {
gpointer padding[8];
} NMDeviceClass;
typedef struct _NMLldpNeighbor NMLldpNeighbor;
GType nm_device_get_type (void);
const char * nm_device_get_iface (NMDevice *device);
@ -127,6 +130,8 @@ const char * nm_device_get_vendor (NMDevice *device);
const char * nm_device_get_description (NMDevice *device);
NM_AVAILABLE_IN_1_2
NMMetered nm_device_get_metered (NMDevice *device);
NM_AVAILABLE_IN_1_2
GPtrArray * nm_device_get_lldp_neighbors (NMDevice *device);
char ** nm_device_disambiguate_names (NMDevice **devices,
int num_devices);
@ -164,6 +169,24 @@ gboolean nm_device_connection_compatible (NMDevice *device,
GType nm_device_get_setting_type (NMDevice *device);
NM_AVAILABLE_IN_1_2
NMLldpNeighbor *nm_lldp_neighbor_new (void);
NM_AVAILABLE_IN_1_2
void nm_lldp_neighbor_ref (NMLldpNeighbor *neighbor);
NM_AVAILABLE_IN_1_2
void nm_lldp_neighbor_unref (NMLldpNeighbor *neighbor);
NM_AVAILABLE_IN_1_2
char **nm_lldp_neighbor_get_attr_names (NMLldpNeighbor *neighbor);
NM_AVAILABLE_IN_1_2
gboolean nm_lldp_neighbor_get_attr_string_value (NMLldpNeighbor *neighbor, char *name,
const char **out_value);
NM_AVAILABLE_IN_1_2
gboolean nm_lldp_neighbor_get_attr_uint_value (NMLldpNeighbor *neighbor, char *name,
guint *out_value);
NM_AVAILABLE_IN_1_2
const GVariantType *nm_lldp_neighbor_get_attr_type (NMLldpNeighbor *neighbor, char *name);
G_END_DECLS
#endif /* __NM_DEVICE_H__ */