lldp: support IEEE 802.3 TLVs
Add support for IEEE 802.3 organizationally specific TLVs: - MAC/PHY configuration/status (IEEE 802.1AB-2009 clause F.2) - power via medium dependent interface (clause F.3) - maximum frame size (clause F.4)
This commit is contained in:
@@ -843,6 +843,10 @@ typedef enum /*< flags >*/ {
|
|||||||
#define NM_LLDP_ATTR_IEEE_802_1_VLANS "ieee-802-1-vlans"
|
#define NM_LLDP_ATTR_IEEE_802_1_VLANS "ieee-802-1-vlans"
|
||||||
#define NM_LLDP_ATTR_IEEE_802_1_PPVIDS "ieee-802-1-ppvids"
|
#define NM_LLDP_ATTR_IEEE_802_1_PPVIDS "ieee-802-1-ppvids"
|
||||||
|
|
||||||
|
#define NM_LLDP_ATTR_IEEE_802_3_MAC_PHY_CONF "ieee-802-3-mac-phy-conf"
|
||||||
|
#define NM_LLDP_ATTR_IEEE_802_3_POWER_VIA_MDI "ieee-802-3-power-via-mdi"
|
||||||
|
#define NM_LLDP_ATTR_IEEE_802_3_MAX_FRAME_SIZE "ieee-802-3-max-frame-size"
|
||||||
|
|
||||||
/* These are deprecated in favor of NM_LLDP_ATTR_IEEE_802_1_VLANS,
|
/* These are deprecated in favor of NM_LLDP_ATTR_IEEE_802_1_VLANS,
|
||||||
* which can report multiple VLANs */
|
* which can report multiple VLANs */
|
||||||
#define NM_LLDP_ATTR_IEEE_802_1_VID "ieee-802-1-vid"
|
#define NM_LLDP_ATTR_IEEE_802_1_VID "ieee-802-1-vid"
|
||||||
|
@@ -42,6 +42,7 @@ typedef enum {
|
|||||||
LLDP_ATTR_TYPE_NONE,
|
LLDP_ATTR_TYPE_NONE,
|
||||||
LLDP_ATTR_TYPE_UINT32,
|
LLDP_ATTR_TYPE_UINT32,
|
||||||
LLDP_ATTR_TYPE_STRING,
|
LLDP_ATTR_TYPE_STRING,
|
||||||
|
LLDP_ATTR_TYPE_VARDICT,
|
||||||
LLDP_ATTR_TYPE_ARRAY_OF_VARDICTS,
|
LLDP_ATTR_TYPE_ARRAY_OF_VARDICTS,
|
||||||
} LldpAttrType;
|
} LldpAttrType;
|
||||||
|
|
||||||
@@ -60,6 +61,9 @@ typedef enum {
|
|||||||
LLDP_ATTR_ID_IEEE_802_1_VID,
|
LLDP_ATTR_ID_IEEE_802_1_VID,
|
||||||
LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME,
|
LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME,
|
||||||
LLDP_ATTR_ID_IEEE_802_1_VLANS,
|
LLDP_ATTR_ID_IEEE_802_1_VLANS,
|
||||||
|
LLDP_ATTR_ID_IEEE_802_3_MAC_PHY_CONF,
|
||||||
|
LLDP_ATTR_ID_IEEE_802_3_POWER_VIA_MDI,
|
||||||
|
LLDP_ATTR_ID_IEEE_802_3_MAX_FRAME_SIZE,
|
||||||
_LLDP_ATTR_ID_COUNT,
|
_LLDP_ATTR_ID_COUNT,
|
||||||
} LldpAttrId;
|
} LldpAttrId;
|
||||||
|
|
||||||
@@ -68,6 +72,7 @@ typedef struct {
|
|||||||
union {
|
union {
|
||||||
guint32 v_uint32;
|
guint32 v_uint32;
|
||||||
char *v_string;
|
char *v_string;
|
||||||
|
GVariant *v_variant;
|
||||||
CList v_variant_list;
|
CList v_variant_list;
|
||||||
};
|
};
|
||||||
} LldpAttrData;
|
} LldpAttrData;
|
||||||
@@ -178,6 +183,9 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_lldp_attr_id_to_name, LldpAttrId,
|
|||||||
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VID, NM_LLDP_ATTR_IEEE_802_1_VID),
|
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VID, NM_LLDP_ATTR_IEEE_802_1_VID),
|
||||||
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME),
|
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME),
|
||||||
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLANS, NM_LLDP_ATTR_IEEE_802_1_VLANS),
|
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLANS, NM_LLDP_ATTR_IEEE_802_1_VLANS),
|
||||||
|
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_3_MAC_PHY_CONF, NM_LLDP_ATTR_IEEE_802_3_MAC_PHY_CONF),
|
||||||
|
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_3_POWER_VIA_MDI, NM_LLDP_ATTR_IEEE_802_3_POWER_VIA_MDI),
|
||||||
|
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_3_MAX_FRAME_SIZE,NM_LLDP_ATTR_IEEE_802_3_MAX_FRAME_SIZE),
|
||||||
NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_ATTR_ID_COUNT),
|
NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_ATTR_ID_COUNT),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -195,6 +203,9 @@ _NM_UTILS_LOOKUP_DEFINE (static, _lldp_attr_id_to_type, LldpAttrId, LldpAttrType
|
|||||||
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VID, LLDP_ATTR_TYPE_UINT32),
|
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VID, LLDP_ATTR_TYPE_UINT32),
|
||||||
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, LLDP_ATTR_TYPE_STRING),
|
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME, LLDP_ATTR_TYPE_STRING),
|
||||||
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLANS, LLDP_ATTR_TYPE_ARRAY_OF_VARDICTS),
|
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_VLANS, LLDP_ATTR_TYPE_ARRAY_OF_VARDICTS),
|
||||||
|
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_3_MAC_PHY_CONF, LLDP_ATTR_TYPE_VARDICT),
|
||||||
|
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_3_POWER_VIA_MDI, LLDP_ATTR_TYPE_VARDICT),
|
||||||
|
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_3_MAX_FRAME_SIZE, LLDP_ATTR_TYPE_UINT32),
|
||||||
NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_ATTR_ID_COUNT),
|
NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_ATTR_ID_COUNT),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -244,6 +255,26 @@ _lldp_attr_set_uint32 (LldpAttrData *pdata, LldpAttrId attr_id, guint32 v_uint32
|
|||||||
pdata->v_uint32 = v_uint32;
|
pdata->v_uint32 = v_uint32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_lldp_attr_set_vardict (LldpAttrData *pdata, LldpAttrId attr_id, GVariant *variant)
|
||||||
|
{
|
||||||
|
|
||||||
|
nm_assert (pdata);
|
||||||
|
nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_VARDICT);
|
||||||
|
|
||||||
|
pdata = &pdata[attr_id];
|
||||||
|
|
||||||
|
/* we ignore duplicate fields silently */
|
||||||
|
if (pdata->attr_type != LLDP_ATTR_TYPE_NONE) {
|
||||||
|
if (g_variant_is_floating (variant))
|
||||||
|
g_variant_unref (variant);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdata->attr_type = LLDP_ATTR_TYPE_VARDICT;
|
||||||
|
pdata->v_variant = g_variant_ref_sink (variant);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_lldp_attr_add_vardict (LldpAttrData *pdata, LldpAttrId attr_id, GVariant *variant)
|
_lldp_attr_add_vardict (LldpAttrData *pdata, LldpAttrId attr_id, GVariant *variant)
|
||||||
{
|
{
|
||||||
@@ -319,6 +350,9 @@ lldp_neighbor_free (LldpNeighbor *neighbor)
|
|||||||
case LLDP_ATTR_TYPE_STRING:
|
case LLDP_ATTR_TYPE_STRING:
|
||||||
g_free (neighbor->attrs[attr_id].v_string);
|
g_free (neighbor->attrs[attr_id].v_string);
|
||||||
break;
|
break;
|
||||||
|
case LLDP_ATTR_TYPE_VARDICT:
|
||||||
|
g_variant_unref (neighbor->attrs[attr_id].v_variant);
|
||||||
|
break;
|
||||||
case LLDP_ATTR_TYPE_ARRAY_OF_VARDICTS:
|
case LLDP_ATTR_TYPE_ARRAY_OF_VARDICTS:
|
||||||
nm_c_list_elem_free_all (&neighbor->attrs[attr_id].v_variant_list,
|
nm_c_list_elem_free_all (&neighbor->attrs[attr_id].v_variant_list,
|
||||||
(GDestroyNotify) g_variant_unref);
|
(GDestroyNotify) g_variant_unref);
|
||||||
@@ -577,14 +611,10 @@ lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!( memcmp (oui, SD_LLDP_OUI_802_1, sizeof (oui)) == 0
|
if ( memcmp (oui, SD_LLDP_OUI_802_1, sizeof (oui)) != 0
|
||||||
&& NM_IN_SET (subtype,
|
&& memcmp (oui, SD_LLDP_OUI_802_3, sizeof (oui)) != 0)
|
||||||
SD_LLDP_OUI_802_1_SUBTYPE_PORT_PROTOCOL_VLAN_ID,
|
|
||||||
SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID,
|
|
||||||
SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME)))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
/* skip over leading TLV, OUI and subtype */
|
/* skip over leading TLV, OUI and subtype */
|
||||||
#ifdef WITH_MORE_ASSERTS
|
#ifdef WITH_MORE_ASSERTS
|
||||||
{
|
{
|
||||||
@@ -603,8 +633,7 @@ lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error)
|
|||||||
data8 += 6;
|
data8 += 6;
|
||||||
len -= 6;
|
len -= 6;
|
||||||
|
|
||||||
/*if (memcmp (oui, SD_LLDP_OUI_802_1, sizeof (oui)) == 0)*/
|
if (memcmp (oui, SD_LLDP_OUI_802_1, sizeof (oui)) == 0) {
|
||||||
{
|
|
||||||
GVariantDict dict;
|
GVariantDict dict;
|
||||||
|
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
@@ -663,7 +692,44 @@ lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
continue;
|
||||||
|
}
|
||||||
|
} else if (memcmp (oui, SD_LLDP_OUI_802_3, sizeof (oui)) == 0) {
|
||||||
|
GVariantDict dict;
|
||||||
|
|
||||||
|
switch (subtype) {
|
||||||
|
case SD_LLDP_OUI_802_3_SUBTYPE_MAC_PHY_CONFIG_STATUS:
|
||||||
|
if (len != 5)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_variant_dict_init (&dict, NULL);
|
||||||
|
g_variant_dict_insert (&dict, "autoneg", "u", (guint32) data8[0]);
|
||||||
|
g_variant_dict_insert (&dict, "pmd-autoneg-cap", "u", (guint32) unaligned_read_be16 (&data8[1]));
|
||||||
|
g_variant_dict_insert (&dict, "operational-mau-type", "u", (guint32) unaligned_read_be16 (&data8[3]));
|
||||||
|
|
||||||
|
_lldp_attr_set_vardict (neigh->attrs,
|
||||||
|
LLDP_ATTR_ID_IEEE_802_3_MAC_PHY_CONF,
|
||||||
|
g_variant_dict_end (&dict));
|
||||||
|
break;
|
||||||
|
case SD_LLDP_OUI_802_3_SUBTYPE_POWER_VIA_MDI:
|
||||||
|
if (len != 3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_variant_dict_init (&dict, NULL);
|
||||||
|
g_variant_dict_insert (&dict, "mdi-power-support", "u", (guint32) data8[0]);
|
||||||
|
g_variant_dict_insert (&dict, "pse-power-pair", "u", (guint32) data8[1]);
|
||||||
|
g_variant_dict_insert (&dict, "power-class", "u", (guint32) data8[2]);
|
||||||
|
|
||||||
|
_lldp_attr_set_vardict (neigh->attrs,
|
||||||
|
LLDP_ATTR_ID_IEEE_802_3_POWER_VIA_MDI,
|
||||||
|
g_variant_dict_end (&dict));
|
||||||
|
break;
|
||||||
|
case SD_LLDP_OUI_802_3_SUBTYPE_MAXIMUM_FRAME_SIZE:
|
||||||
|
if (len != 2)
|
||||||
|
continue;
|
||||||
|
_lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_3_MAX_FRAME_SIZE,
|
||||||
|
unaligned_read_be16 (data8));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (sd_lldp_neighbor_tlv_next (neighbor_sd) > 0);
|
} while (sd_lldp_neighbor_tlv_next (neighbor_sd) > 0);
|
||||||
@@ -728,6 +794,11 @@ lldp_neighbor_to_variant (LldpNeighbor *neigh)
|
|||||||
_lldp_attr_id_to_name (attr_id),
|
_lldp_attr_id_to_name (attr_id),
|
||||||
g_variant_new_string (data->v_string));
|
g_variant_new_string (data->v_string));
|
||||||
break;
|
break;
|
||||||
|
case LLDP_ATTR_TYPE_VARDICT:
|
||||||
|
g_variant_builder_add (&builder, "{sv}",
|
||||||
|
_lldp_attr_id_to_name (attr_id),
|
||||||
|
data->v_variant);
|
||||||
|
break;
|
||||||
case LLDP_ATTR_TYPE_ARRAY_OF_VARDICTS: {
|
case LLDP_ATTR_TYPE_ARRAY_OF_VARDICTS: {
|
||||||
NMCListElem *elem;
|
NMCListElem *elem;
|
||||||
GVariantBuilder builder2;
|
GVariantBuilder builder2;
|
||||||
|
@@ -244,7 +244,7 @@ _test_recv_data1_check (GMainLoop *loop, NMLldpListener *listener)
|
|||||||
SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS, "00:01:30:F9:AD:A0",
|
SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS, "00:01:30:F9:AD:A0",
|
||||||
SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME, "1/1");
|
SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME, "1/1");
|
||||||
g_assert (neighbor);
|
g_assert (neighbor);
|
||||||
g_assert_cmpint (g_variant_n_children (neighbor), ==, 4 + 13);
|
g_assert_cmpint (g_variant_n_children (neighbor), ==, 4 + 16);
|
||||||
|
|
||||||
attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_DESTINATION, G_VARIANT_TYPE_STRING);
|
attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_DESTINATION, G_VARIANT_TYPE_STRING);
|
||||||
nmtst_assert_variant_string (attr, NM_LLDP_DEST_NEAREST_BRIDGE);
|
nmtst_assert_variant_string (attr, NM_LLDP_DEST_NEAREST_BRIDGE);
|
||||||
@@ -287,10 +287,34 @@ _test_recv_data1_check (GMainLoop *loop, NMLldpListener *listener)
|
|||||||
nm_clear_g_variant (&child);
|
nm_clear_g_variant (&child);
|
||||||
nm_clear_g_variant (&attr);
|
nm_clear_g_variant (&attr);
|
||||||
|
|
||||||
/* unsupported: IEEE 802.3 - Power Via MDI */
|
/* IEEE 802.3 - Power Via MDI */
|
||||||
/* unsupported: IEEE 802.3 - MAC/PHY Configuration/Status */
|
attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_3_POWER_VIA_MDI, G_VARIANT_TYPE_VARDICT);
|
||||||
|
g_assert (attr);
|
||||||
|
g_variant_lookup (attr, "mdi-power-support", "u", &v_uint);
|
||||||
|
g_assert_cmpint (v_uint, ==, 7);
|
||||||
|
g_variant_lookup (attr, "pse-power-pair", "u", &v_uint);
|
||||||
|
g_assert_cmpint (v_uint, ==, 1);
|
||||||
|
g_variant_lookup (attr, "power-class", "u", &v_uint);
|
||||||
|
g_assert_cmpint (v_uint, ==, 0);
|
||||||
|
nm_clear_g_variant (&attr);
|
||||||
|
|
||||||
|
/* IEEE 802.3 - MAC/PHY Configuration/Status */
|
||||||
|
attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_3_MAC_PHY_CONF, G_VARIANT_TYPE_VARDICT);
|
||||||
|
g_assert (attr);
|
||||||
|
g_variant_lookup (attr, "autoneg", "u", &v_uint);
|
||||||
|
g_assert_cmpint (v_uint, ==, 3);
|
||||||
|
g_variant_lookup (attr, "pmd-autoneg-cap", "u", &v_uint);
|
||||||
|
g_assert_cmpint (v_uint, ==, 0x6c00);
|
||||||
|
g_variant_lookup (attr, "operational-mau-type", "u", &v_uint);
|
||||||
|
g_assert_cmpint (v_uint, ==, 16);
|
||||||
|
nm_clear_g_variant (&attr);
|
||||||
|
|
||||||
/* unsupported: IEEE 802.3 - Link Aggregation */
|
/* unsupported: IEEE 802.3 - Link Aggregation */
|
||||||
/* unsupported: IEEE 802.3 - Maximum Frame Size*/
|
|
||||||
|
/* Maximum Frame Size */
|
||||||
|
attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_3_MAX_FRAME_SIZE, G_VARIANT_TYPE_UINT32);
|
||||||
|
nmtst_assert_variant_uint32 (attr, 1522);
|
||||||
|
nm_clear_g_variant (&attr);
|
||||||
|
|
||||||
/* IEEE 802.1 - Port VLAN ID */
|
/* IEEE 802.1 - Port VLAN ID */
|
||||||
attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PVID, G_VARIANT_TYPE_UINT32);
|
attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_PVID, G_VARIANT_TYPE_UINT32);
|
||||||
|
@@ -762,6 +762,7 @@ class Device(ExportedObj):
|
|||||||
'flags': dbus.UInt32(0x31),
|
'flags': dbus.UInt32(0x31),
|
||||||
}, signature = 'sv'),
|
}, signature = 'sv'),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
}),
|
}),
|
||||||
dbus.Dictionary({
|
dbus.Dictionary({
|
||||||
'chassis-id-type': dbus.UInt32(6),
|
'chassis-id-type': dbus.UInt32(6),
|
||||||
@@ -787,7 +788,17 @@ class Device(ExportedObj):
|
|||||||
'interface-number': dbus.UInt32(1),
|
'interface-number': dbus.UInt32(1),
|
||||||
'interface-number-subtype': dbus.UInt32(2),
|
'interface-number-subtype': dbus.UInt32(2),
|
||||||
}, signature = 'sv'),
|
}, signature = 'sv'),
|
||||||
])
|
]),
|
||||||
|
'ieee-802-3-mac-phy-conf': dbus.Dictionary({
|
||||||
|
'autoneg': dbus.UInt32(3),
|
||||||
|
'pmd-autoneg-cap': dbus.UInt32(0xfe),
|
||||||
|
'operational-mau-type': dbus.UInt32(5),
|
||||||
|
}, signature = 'sv'),
|
||||||
|
'ieee-802-3-power-via-mdi': dbus.Dictionary({
|
||||||
|
'mdi-power-support': dbus.UInt32(7),
|
||||||
|
'pse-power-pair': dbus.UInt32(6),
|
||||||
|
'power-class': dbus.UInt32(1),
|
||||||
|
}, signature = 'sv'),
|
||||||
})
|
})
|
||||||
], 'a{sv}')
|
], 'a{sv}')
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user