summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2015-07-27 18:04:46 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2015-10-02 17:39:22 +0200
commit4fc6de5df31c81ae35e82ed91d0a2ee515edad41 (patch)
tree28eafab32619e68f35a179b196a7f3813687a9f5 /src
parent7434883c40f3623372044f88cdde3eda49ba9758 (diff)
lldp: add sd_lldp_tlv_packet_get_destination_type()
It can be useful to know the destination address of a LLDP frame because it determines the scope of propagation of the frame and thus this information be used to know whether the neighbor is connected to the same physical link. See clause 7.1 of IEEE Std 802.1AB-2009.
Diffstat (limited to 'src')
-rw-r--r--src/libsystemd-network/lldp-tlv.c17
-rw-r--r--src/libsystemd-network/lldp-tlv.h4
-rw-r--r--src/libsystemd-network/test-lldp.c11
-rw-r--r--src/systemd/sd-lldp.h8
4 files changed, 40 insertions, 0 deletions
diff --git a/src/libsystemd-network/lldp-tlv.c b/src/libsystemd-network/lldp-tlv.c
index 24f2606f31..996c5b8881 100644
--- a/src/libsystemd-network/lldp-tlv.c
+++ b/src/libsystemd-network/lldp-tlv.c
@@ -539,3 +539,20 @@ int sd_lldp_packet_read_system_capability(tlv_packet *tlv, uint16_t *data) {
return r;
}
+
+int sd_lldp_packet_get_destination_type(tlv_packet *tlv, int *dest) {
+ assert_return(tlv, -EINVAL);
+ assert_return(dest, -EINVAL);
+
+ /* 802.1AB-2009, Table 7-1 */
+ if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_BRIDGE, ETH_ALEN))
+ *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE;
+ else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_NON_TPMR_BRIDGE, ETH_ALEN))
+ *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE;
+ else if (!memcmp(&tlv->mac, LLDP_MAC_NEAREST_CUSTOMER_BRIDGE, ETH_ALEN))
+ *dest = SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE;
+ else
+ return -EINVAL;
+
+ return 0;
+}
diff --git a/src/libsystemd-network/lldp-tlv.h b/src/libsystemd-network/lldp-tlv.h
index 19509d3589..5af06b40ca 100644
--- a/src/libsystemd-network/lldp-tlv.h
+++ b/src/libsystemd-network/lldp-tlv.h
@@ -43,6 +43,10 @@ struct tlv_section {
LIST_FIELDS(tlv_section, section);
};
+#define LLDP_MAC_NEAREST_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }
+#define LLDP_MAC_NEAREST_NON_TPMR_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }
+#define LLDP_MAC_NEAREST_CUSTOMER_BRIDGE (uint8_t[]) { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }
+
int tlv_section_new(tlv_section **ret);
void tlv_section_free(tlv_section *ret);
diff --git a/src/libsystemd-network/test-lldp.c b/src/libsystemd-network/test-lldp.c
index 26f64347a7..294198a0b5 100644
--- a/src/libsystemd-network/test-lldp.c
+++ b/src/libsystemd-network/test-lldp.c
@@ -202,6 +202,15 @@ static int lldp_parse_ttl_tlv(tlv_packet *m) {
return 0;
}
+static int lldp_get_destination_type(tlv_packet *m) {
+ int dest;
+
+ assert_se(sd_lldp_packet_get_destination_type(m, &dest) >= 0);
+ assert_se(dest == SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE);
+
+ return 0;
+}
+
static int lldp_parse_tlv_packet(tlv_packet *m, int len) {
uint8_t subtype;
@@ -212,6 +221,8 @@ static int lldp_parse_tlv_packet(tlv_packet *m, int len) {
assert_se(lldp_parse_ttl_tlv(m) >= 0);
assert_se(lldp_parse_system_desc_tlv(m) >= 0);
+ assert_se(lldp_get_destination_type(m) >= 0);
+
return 0;
}
diff --git a/src/systemd/sd-lldp.h b/src/systemd/sd-lldp.h
index e472cbece9..bf6dfc1ee0 100644
--- a/src/systemd/sd-lldp.h
+++ b/src/systemd/sd-lldp.h
@@ -28,6 +28,12 @@ enum {
SD_LLDP_EVENT_UPDATE_INFO = 0,
};
+enum {
+ SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE,
+ SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE,
+ SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE,
+};
+
typedef struct sd_lldp sd_lldp;
typedef struct tlv_packet sd_lldp_packet;
@@ -56,4 +62,6 @@ int sd_lldp_packet_read_port_description(sd_lldp_packet *tlv, char **data, uint1
sd_lldp_packet *sd_lldp_packet_ref(sd_lldp_packet *tlv);
sd_lldp_packet *sd_lldp_packet_unref(sd_lldp_packet *tlv);
+int sd_lldp_packet_get_destination_type(sd_lldp_packet *tlv, int *dest);
+
int sd_lldp_get_packets(sd_lldp *lldp, sd_lldp_packet ***tlvs);