diff options
author | Thomas Haller <thaller@redhat.com> | 2016-03-11 11:40:34 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-03-17 15:00:48 +0100 |
commit | e66c581c11bff7f6e3f7cfd699ca739dc2190ff3 (patch) | |
tree | 828891708ca330a45471e22cf087789921e869a1 | |
parent | 4797e9fcdb413baa3d361a1a855c5ad5f024319d (diff) | |
download | NetworkManager-e66c581c11bff7f6e3f7cfd699ca739dc2190ff3.tar.gz |
lldp: split out creation of LldpNeighbor instance
-rw-r--r-- | src/devices/nm-lldp-listener.c | 374 |
1 files changed, 211 insertions, 163 deletions
diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c index 9a0493fcf8..cf35457ab8 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/devices/nm-lldp-listener.c @@ -182,6 +182,8 @@ gvalue_new_uint_u16 (const void *data) return gvalue_new_uint (ntohs (v)); } +/*****************************************************************************/ + static guint lldp_neighbor_id_hash (gconstpointer ptr) { @@ -267,6 +269,203 @@ lldp_neighbor_equal (LldpNeighbor *a, LldpNeighbor *b) return TRUE; } +static LldpNeighbor * +lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error) +{ + nm_auto (lldp_neighbor_freep) LldpNeighbor *neigh = NULL; + LldpNeighbor *neigh_result; + uint8_t chassis_id_type, port_id_type; + uint16_t data16; + uint8_t *data8; + const void *chassis_id, *port_id; + gsize chassis_id_len, port_id_len, len; + GValue *value; + const char *str; + int r; + + r = sd_lldp_neighbor_get_chassis_id (neighbor_sd, &chassis_id_type, + &chassis_id, &chassis_id_len); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading chassis-id: %s", g_strerror (-r)); + return NULL; + } + if (chassis_id_len < 1) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "empty chassis-id"); + return NULL; + } + + r = sd_lldp_neighbor_get_port_id (neighbor_sd, &port_id_type, + &port_id, &port_id_len); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading port-id: %s", g_strerror (-r)); + return NULL; + } + if (port_id_len < 1) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "empty port-id"); + return NULL; + } + + neigh = g_slice_new0 (LldpNeighbor); + neigh->tlvs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); + neigh->chassis_id_type = chassis_id_type; + neigh->port_id_type = port_id_type; + + r = sd_lldp_neighbor_get_destination_address (neighbor_sd, &neigh->destination_address); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed getting destination address: %s", g_strerror (-r)); + return NULL; + } + + switch (chassis_id_type) { + case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: + case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: + case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: + case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: + neigh->chassis_id = g_strndup ((const char *) chassis_id, chassis_id_len); + break; + case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: + neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len); + break; + default: + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "unsupported chassis-id type %d", chassis_id_type); + return NULL; + } + + switch (port_id_type) { + case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: + case LLDP_PORT_SUBTYPE_INTERFACE_NAME: + case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: + case LLDP_PORT_SUBTYPE_PORT_COMPONENT: + neigh->port_id = strndup ((char *) port_id, port_id_len); + break; + case LLDP_PORT_SUBTYPE_MAC_ADDRESS: + neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len); + break; + default: + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "unsupported port-id type %d", port_id_type); + return NULL; + } + + if (sd_lldp_neighbor_get_port_description (neighbor_sd, &str) == 0) { + value = gvalue_new_str (str); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_PORT_DESCRIPTION, value); + } + + if (sd_lldp_neighbor_get_system_name (neighbor_sd, &str) == 0) { + value = gvalue_new_str (str); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_NAME, value); + } + + if (sd_lldp_neighbor_get_system_description (neighbor_sd, &str) == 0) { + value = gvalue_new_str (str); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, value); + } + + if (sd_lldp_neighbor_get_system_capabilities (neighbor_sd, &data16) == 0) { + value = gvalue_new_uint (data16); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_CAPABILITIES, value); + } + + r = sd_lldp_neighbor_tlv_rewind (neighbor_sd); + if (r < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading tlv (rewind): %s", g_strerror (-r)); + return NULL; + } + do { + guint8 oui[3]; + guint8 subtype; + + r = sd_lldp_neighbor_tlv_get_oui (neighbor_sd, oui, &subtype); + if (r < 0) { + if (r == -ENXIO) + continue; + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + "failed reading tlv: %s", g_strerror (-r)); + return NULL; + } + + if (!( memcmp (oui, LLDP_OUI_802_1, sizeof (oui)) == 0 + && NM_IN_SET (subtype, + LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID, + LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID, + LLDP_OUI_802_1_SUBTYPE_VLAN_NAME))) + continue; + + if (sd_lldp_neighbor_tlv_get_raw (neighbor_sd, (void *) &data8, &len) < 0) + continue; + + /* skip over leading TLV, OUI and subtype */ +#ifdef WITH_MORE_ASSERTS + { + guint8 check_hdr[] = { + 0xfe | (((len - 2) >> 8) & 0x01), ((len - 2) & 0xFF), + oui[0], oui[1], oui[2], + subtype + }; + + nm_assert (len > 2 + 3 +1); + nm_assert (memcmp (data8, check_hdr, sizeof check_hdr) == 0); + } +#endif + if (len <= 6) + continue; + data8 += 6; + len -= 6; + + /*if (memcmp (oui, LLDP_OUI_802_1, sizeof (oui)) == 0)*/ + { + switch (subtype) { + case LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID: + if (len != 2) + continue; + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PVID, + gvalue_new_uint_u16 (data8)); + break; + case LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID: + if (len != 3) + continue; + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS, + gvalue_new_uint_u8 (&data8[0])); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID, + gvalue_new_uint_u16 (&data8[1])); + break; + case LLDP_OUI_802_1_SUBTYPE_VLAN_NAME: { + int l; + + if (len <= 3) + continue; + + l = data8[2]; + if (len != 3 + l) + continue; + + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VID, + gvalue_new_uint_u16 (&data8[0])); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, + gvalue_new_str_ptr (&data8[3], len)); + break; + } + default: + g_assert_not_reached (); + } + } + } while (sd_lldp_neighbor_tlv_next (neighbor_sd) > 0); + + neigh_result = neigh; + neigh = NULL; + return neigh_result; +} + +/*****************************************************************************/ + static gboolean lldp_hash_table_equal (GHashTable *a, GHashTable *b) { @@ -320,7 +519,8 @@ process_lldp_neighbors (NMLldpListener *self) NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); nm_auto_free sd_lldp_neighbor **neighbors = NULL; GHashTable *hash; - int num, i, r; + int num, i; + GError *parse_error = NULL, **p_parse_error; g_return_if_fail (priv->lldp_handle); @@ -334,178 +534,26 @@ process_lldp_neighbors (NMLldpListener *self) hash = g_hash_table_new_full (lldp_neighbor_id_hash, lldp_neighbor_id_equal, (GDestroyNotify) lldp_neighbor_free, NULL); + p_parse_error = _LOGT_ENABLED () ? &parse_error : NULL; + for (i = 0; neighbors && i < num; i++) { - nm_auto (lldp_neighbor_freep) LldpNeighbor *neigh = NULL; - uint8_t chassis_id_type, port_id_type; - uint16_t data16; - uint8_t *data8; - const void *chassis_id, *port_id; - gsize chassis_id_len, port_id_len, len; - GValue *value; - const char *str; + LldpNeighbor *neigh; if (i >= MAX_NEIGHBORS) break; - r = sd_lldp_neighbor_get_chassis_id (neighbors[i], &chassis_id_type, - &chassis_id, &chassis_id_len); - if (r < 0) - goto next_neighbor; - if (chassis_id_len < 1) - goto next_neighbor; - - r = sd_lldp_neighbor_get_port_id (neighbors[i], &port_id_type, - &port_id, &port_id_len); - if (r < 0) - goto next_neighbor; - if (port_id_len < 1) - goto next_neighbor; - - neigh = g_slice_new0 (LldpNeighbor); - neigh->tlvs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); - neigh->chassis_id_type = chassis_id_type; - neigh->port_id_type = port_id_type; - - if (sd_lldp_neighbor_get_destination_address (neighbors[i], &neigh->destination_address) < 0) - goto next_neighbor; - - switch (chassis_id_type) { - case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: - case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: - case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: - case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: - neigh->chassis_id = g_strndup ((const char *) chassis_id, chassis_id_len); - break; - case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: - neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len); - break; - default: - _LOGD ("process: unsupported chassis ID type %d", chassis_id_type); - goto next_neighbor; - } - - switch (port_id_type) { - case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: - case LLDP_PORT_SUBTYPE_INTERFACE_NAME: - case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: - case LLDP_PORT_SUBTYPE_PORT_COMPONENT: - neigh->port_id = strndup ((char *) port_id, port_id_len); - break; - case LLDP_PORT_SUBTYPE_MAC_ADDRESS: - neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len); - break; - default: - _LOGD ("process: unsupported port ID type %d", port_id_type); - goto next_neighbor; - } - - if (sd_lldp_neighbor_get_port_description (neighbors[i], &str) == 0) { - value = gvalue_new_str (str); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_PORT_DESCRIPTION, value); - } - - if (sd_lldp_neighbor_get_system_name (neighbors[i], &str) == 0) { - value = gvalue_new_str (str); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_NAME, value); - } - - if (sd_lldp_neighbor_get_system_description (neighbors[i], &str) == 0) { - value = gvalue_new_str (str); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, value); - } - - if (sd_lldp_neighbor_get_system_capabilities (neighbors[i], &data16) == 0) { - value = gvalue_new_uint (data16); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_CAPABILITIES, value); - } - - if (sd_lldp_neighbor_tlv_rewind (neighbors[i]) < 0) - goto next_neighbor; - do { - guint8 oui[3]; - guint8 subtype; - - r = sd_lldp_neighbor_tlv_get_oui (neighbors[i], oui, &subtype); - if (r < 0) { - if (r == -ENXIO) - continue; - goto next_neighbor; + neigh = lldp_neighbor_new (neighbors[i], p_parse_error); + if (!neigh) { + if (p_parse_error) { + _LOGT ("parse: %s", parse_error->message); + g_clear_error (&parse_error); } - - if (!( memcmp (oui, LLDP_OUI_802_1, sizeof (oui)) == 0 - && NM_IN_SET (subtype, - LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID, - LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID, - LLDP_OUI_802_1_SUBTYPE_VLAN_NAME))) - continue; - - if (sd_lldp_neighbor_tlv_get_raw (neighbors[i], (void *) &data8, &len) < 0) - continue; - - /* skip over leading TLV, OUI and subtype */ -#ifdef WITH_MORE_ASSERTS - { - guint8 check_hdr[] = { - 0xfe | (((len - 2) >> 8) & 0x01), ((len - 2) & 0xFF), - oui[0], oui[1], oui[2], - subtype - }; - - nm_assert (len > 2 + 3 +1); - nm_assert (memcmp (data8, check_hdr, sizeof check_hdr) == 0); - } -#endif - if (len <= 6) - goto next_neighbor; - data8 += 6; - len -= 6; - - /*if (memcmp (oui, LLDP_OUI_802_1, sizeof (oui)) == 0)*/ - { - switch (subtype) { - case LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID: - if (len != 2) - goto next_neighbor; - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PVID, - gvalue_new_uint_u16 (data8)); - break; - case LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID: - if (len != 3) - goto next_neighbor; - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS, - gvalue_new_uint_u8 (&data8[0])); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID, - gvalue_new_uint_u16 (&data8[1])); - break; - case LLDP_OUI_802_1_SUBTYPE_VLAN_NAME: { - int l; - - if (len <= 3) - goto next_neighbor; - - l = data8[2]; - if (len != 3 + l) - goto next_neighbor; - - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VID, - gvalue_new_uint_u16 (&data8[0])); - g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, - gvalue_new_str_ptr (&data8[3], len)); - break; - } - default: - g_assert_not_reached (); - } - } - } while (sd_lldp_neighbor_tlv_next (neighbors[i]) > 0); + continue; + } _LOGD ("process: new neigh: CHASSIS='%s' PORT='%s'", neigh->chassis_id, neigh->port_id); - g_hash_table_add (hash, neigh); - neigh = NULL; -next_neighbor: - ; } for (i = 0; neighbors && i < num; i++) |