lldp: support multiple vlans
Previously we exported the contents of VLAN Name TLV in the 'vid' (uint32) and 'vlan-name' (string) attributes. This is not entirely correct as the TLV can appear multiple times. We need a way to export all the VLAN IDs and names for the neighbor. Add a new 'vlans' attribute which obsoletes the other two and is an array of dictionaries, where each dictionary contains the 'vid' and 'name' keys.
This commit is contained in:
@@ -841,6 +841,10 @@ typedef enum /*< flags >*/ {
|
|||||||
#define NM_LLDP_ATTR_IEEE_802_1_PVID "ieee-802-1-pvid"
|
#define NM_LLDP_ATTR_IEEE_802_1_PVID "ieee-802-1-pvid"
|
||||||
#define NM_LLDP_ATTR_IEEE_802_1_PPVID "ieee-802-1-ppvid"
|
#define NM_LLDP_ATTR_IEEE_802_1_PPVID "ieee-802-1-ppvid"
|
||||||
#define NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS "ieee-802-1-ppvid-flags"
|
#define NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS "ieee-802-1-ppvid-flags"
|
||||||
|
#define NM_LLDP_ATTR_IEEE_802_1_VLANS "ieee-802-1-vlans"
|
||||||
|
|
||||||
|
/* These are deprecated in favor of NM_LLDP_ATTR_IEEE_802_1_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"
|
||||||
#define NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME "ieee-802-1-vlan-name"
|
#define NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME "ieee-802-1-vlan-name"
|
||||||
|
|
||||||
|
@@ -58,6 +58,7 @@ typedef enum {
|
|||||||
LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS,
|
LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS,
|
||||||
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_COUNT,
|
_LLDP_ATTR_ID_COUNT,
|
||||||
} LldpAttrId;
|
} LldpAttrId;
|
||||||
|
|
||||||
@@ -174,6 +175,7 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_lldp_attr_id_to_name, LldpAttrId,
|
|||||||
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS),
|
NM_UTILS_LOOKUP_STR_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS),
|
||||||
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_ITEM_IGNORE (_LLDP_ATTR_ID_COUNT),
|
NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_ATTR_ID_COUNT),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -189,6 +191,7 @@ _NM_UTILS_LOOKUP_DEFINE (static, _lldp_attr_id_to_type, LldpAttrId, LldpAttrType
|
|||||||
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, LLDP_ATTR_TYPE_UINT32),
|
NM_UTILS_LOOKUP_ITEM (LLDP_ATTR_ID_IEEE_802_1_PPVID_FLAGS, 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_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_IGNORE (_LLDP_ATTR_ID_COUNT),
|
NM_UTILS_LOOKUP_ITEM_IGNORE (_LLDP_ATTR_ID_COUNT),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -208,13 +211,8 @@ _lldp_attr_set_str (LldpAttrData *pdata, LldpAttrId attr_id, const char *v_strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_lldp_attr_set_str_ptr (LldpAttrData *pdata, LldpAttrId attr_id, const void *str, gsize len)
|
_lldp_attr_take_str_ptr (LldpAttrData *pdata, LldpAttrId attr_id, char *str)
|
||||||
{
|
{
|
||||||
const char *s = str;
|
|
||||||
const char *tmp;
|
|
||||||
gsize len0 = len;
|
|
||||||
gs_free char *str_free = NULL;
|
|
||||||
|
|
||||||
nm_assert (pdata);
|
nm_assert (pdata);
|
||||||
nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_STRING);
|
nm_assert (_lldp_attr_id_to_type (attr_id) == LLDP_ATTR_TYPE_STRING);
|
||||||
|
|
||||||
@@ -225,23 +223,7 @@ _lldp_attr_set_str_ptr (LldpAttrData *pdata, LldpAttrId attr_id, const void *str
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
pdata->attr_type = LLDP_ATTR_TYPE_STRING;
|
pdata->attr_type = LLDP_ATTR_TYPE_STRING;
|
||||||
|
pdata->v_string = str;
|
||||||
/* truncate at first NUL, including removing trailing NULs*/
|
|
||||||
tmp = memchr (s, '\0', len);
|
|
||||||
if (tmp)
|
|
||||||
len = tmp - s;
|
|
||||||
|
|
||||||
if (!len) {
|
|
||||||
pdata->v_string = g_strdup ("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len0 <= len || s[len] != '\0') {
|
|
||||||
/* hmpf, g_strescape needs a trailing NUL. Need to clone */
|
|
||||||
s = str_free = g_strndup (s, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
pdata->v_string = g_strescape (s, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -637,6 +619,10 @@ lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error)
|
|||||||
break;
|
break;
|
||||||
case SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME: {
|
case SD_LLDP_OUI_802_1_SUBTYPE_VLAN_NAME: {
|
||||||
int l;
|
int l;
|
||||||
|
GVariantDict dict;
|
||||||
|
guint32 vid;
|
||||||
|
const char *name;
|
||||||
|
char *name_to_free;
|
||||||
|
|
||||||
if (len <= 3)
|
if (len <= 3)
|
||||||
continue;
|
continue;
|
||||||
@@ -647,10 +633,21 @@ lldp_neighbor_new (sd_lldp_neighbor *neighbor_sd, GError **error)
|
|||||||
if (l > 32)
|
if (l > 32)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VID,
|
name = nm_utils_buf_utf8safe_escape (&data8[3], l, 0, &name_to_free);
|
||||||
unaligned_read_be16 (&data8[0]));
|
vid = unaligned_read_be16 (&data8[0]);
|
||||||
_lldp_attr_set_str_ptr (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME,
|
|
||||||
&data8[3], l);
|
g_variant_dict_init (&dict, NULL);
|
||||||
|
g_variant_dict_insert (&dict, "vid", "u", vid);
|
||||||
|
g_variant_dict_insert (&dict, "name", "s", name);
|
||||||
|
|
||||||
|
_lldp_attr_add_vardict (neigh->attrs,
|
||||||
|
LLDP_ATTR_ID_IEEE_802_1_VLANS,
|
||||||
|
g_variant_dict_end (&dict));
|
||||||
|
|
||||||
|
_lldp_attr_set_uint32 (neigh->attrs, LLDP_ATTR_ID_IEEE_802_1_VID, vid);
|
||||||
|
_lldp_attr_take_str_ptr (neigh->attrs,
|
||||||
|
LLDP_ATTR_ID_IEEE_802_1_VLAN_NAME,
|
||||||
|
name_to_free ?: g_strdup (name));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@@ -234,6 +234,7 @@ _test_recv_data1_check (GMainLoop *loop, NMLldpListener *listener)
|
|||||||
GVariant *neighbors, *attr, *child;
|
GVariant *neighbors, *attr, *child;
|
||||||
gs_unref_variant GVariant *neighbor = NULL;
|
gs_unref_variant GVariant *neighbor = NULL;
|
||||||
guint v_uint = 0;
|
guint v_uint = 0;
|
||||||
|
const char *v_str = NULL;
|
||||||
|
|
||||||
neighbors = nm_lldp_listener_get_neighbors (listener);
|
neighbors = nm_lldp_listener_get_neighbors (listener);
|
||||||
nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}"));
|
nmtst_assert_variant_is_of_type (neighbors, G_VARIANT_TYPE ("aa{sv}"));
|
||||||
@@ -243,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 + 11);
|
g_assert_cmpint (g_variant_n_children (neighbor), ==, 4 + 12);
|
||||||
|
|
||||||
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);
|
||||||
@@ -312,6 +313,18 @@ _test_recv_data1_check (GMainLoop *loop, NMLldpListener *listener)
|
|||||||
nmtst_assert_variant_uint32 (attr, 488);
|
nmtst_assert_variant_uint32 (attr, 488);
|
||||||
nm_clear_g_variant (&attr);
|
nm_clear_g_variant (&attr);
|
||||||
|
|
||||||
|
/* new VLAN attributes */
|
||||||
|
attr = g_variant_lookup_value (neighbor, NM_LLDP_ATTR_IEEE_802_1_VLANS, G_VARIANT_TYPE ("aa{sv}"));
|
||||||
|
g_assert_cmpuint (g_variant_n_children (attr), ==, 1);
|
||||||
|
child = g_variant_get_child_value (attr, 0);
|
||||||
|
g_assert (child);
|
||||||
|
g_variant_lookup (child, "vid", "u", &v_uint);
|
||||||
|
g_assert_cmpint (v_uint, ==, 488);
|
||||||
|
g_variant_lookup (child, "name", "&s", &v_str);
|
||||||
|
g_assert_cmpstr (v_str, ==, "v2-0488-03-0505");
|
||||||
|
nm_clear_g_variant (&child);
|
||||||
|
nm_clear_g_variant (&attr);
|
||||||
|
|
||||||
/* unsupported: IEEE 802.1 - Protocol Identity */
|
/* unsupported: IEEE 802.1 - Protocol Identity */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -741,7 +741,17 @@ class Device(ExportedObj):
|
|||||||
'system-name': dbus.String('test2.example.com'),
|
'system-name': dbus.String('test2.example.com'),
|
||||||
'system-description': dbus.String('Test system #2'),
|
'system-description': dbus.String('Test system #2'),
|
||||||
'system-capabilities': dbus.UInt32(2047),
|
'system-capabilities': dbus.UInt32(2047),
|
||||||
'destination': dbus.String('nearest-non-tpmr-bridge')
|
'destination': dbus.String('nearest-non-tpmr-bridge'),
|
||||||
|
'ieee-802-1-vlans': dbus.Array([
|
||||||
|
dbus.Dictionary({
|
||||||
|
'vid': dbus.UInt32(80),
|
||||||
|
'name': dbus.String('vlan80'),
|
||||||
|
}, signature = 'sv'),
|
||||||
|
dbus.Dictionary({
|
||||||
|
'vid': dbus.UInt32(4000),
|
||||||
|
'name': dbus.String('My VLAN'),
|
||||||
|
}, signature = 'sv'),
|
||||||
|
]),
|
||||||
}),
|
}),
|
||||||
dbus.Dictionary({
|
dbus.Dictionary({
|
||||||
'chassis-id-type': dbus.UInt32(6),
|
'chassis-id-type': dbus.UInt32(6),
|
||||||
|
Reference in New Issue
Block a user