From: Vincent Bernat Date: Fri, 5 Dec 2008 21:43:08 +0000 (+0100) Subject: More LLDP-MED support, thanks to Michael Hanig. X-Git-Tag: 0.3~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=efe3f9b0fcb09b79190102d95282d8967d34ab0e;p=thirdparty%2Flldpd.git More LLDP-MED support, thanks to Michael Hanig. --- diff --git a/CHANGELOG b/CHANGELOG index 411fd44f..6b1aba3e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,6 @@ lldpd (0.3) - * Initial support of LLDP-MED (inventory part) + * Initial support of LLDP-MED * Fix for bridge detection (don't send bridge ioctl on random interfaces) -- Vincent Bernat diff --git a/src/lldp.c b/src/lldp.c index bd36c137..25186c79 100644 --- a/src/lldp.c +++ b/src/lldp.c @@ -490,7 +490,8 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, break; case LLDP_TLV_SYSTEM_CAP: if (size != 4) { - LLOG_WARNX("system cap tlv with incorrect size received on %s", + LLOG_WARNX("system cap tlv with incorrect size " + "received on %s", hardware->h_ifname); goto malformed; } @@ -536,14 +537,16 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, if ((size < 7) || (size != 7 + *(u_int8_t*)(frame + f + 6))) { - LLOG_WARNX("too short vlan tlv received on %s", + LLOG_WARNX("too short vlan tlv " + "received on %s", hardware->h_ifname); goto malformed; } f += 4; if ((vlan = (struct lldpd_vlan *)calloc(1, sizeof(struct lldpd_vlan))) == NULL) { - LLOG_WARN("unable to alloc vlan structure for " + LLOG_WARN("unable to alloc vlan " + "structure for " "tlv received on %s", hardware->h_ifname); goto malformed; @@ -626,7 +629,7 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, case LLDP_TLV_MED_CAP: f += 4; if (size != 7) { - LLOG_WARN("too short LLDP-MED cap " + LLOG_WARNX("too short LLDP-MED cap " "tlv received on %s", hardware->h_ifname); goto malformed; @@ -638,6 +641,58 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, *(u_int8_t*)(frame + f); f += 1; break; + case LLDP_TLV_MED_POLICY: + f += 4; + if (size != 8) { + LLOG_WARNX("too short LLDP-MED policy " + "tlv received on %s", + hardware->h_ifname); + goto malformed; + } + chassis->c_med_policy = + ntohl(*(u_int32_t*)(frame + f)); + f += 4; + break; + case LLDP_TLV_MED_LOCATION: + f += 4; + if (size <= 5) { + LLOG_WARNX("too short LLDP-MED location " + "tlv received on %s", + hardware->h_ifname); + goto malformed; + } + chassis->c_med_locsize = size - 5; + chassis->c_med_locformat = + *(u_int8_t*)(frame + f); + f += 1; + if ((b = (char*)malloc(size - 5)) == NULL) { + LLOG_WARN("unable to allocate memory " + "for LLDP-MED location for " + "frame received on %s", + hardware->h_ifname); + goto malformed; + } + strlcpy(b, + (char*)(frame + f), + size - 5); + chassis->c_med_locdata = b; + f += size - 5; + break; + case LLDP_TLV_MED_MDI: + f += 4; + if (size != 7) { + LLOG_WARNX("too short LLDP-MED PoE-MDI " + "tlv received on %s", + hardware->h_ifname); + goto malformed; + } + chassis->c_med_powtype = + *(u_int8_t*)(frame + f); + f += 1; + chassis->c_med_powval = + ntohs(*(u_int16_t*)(frame + f)); + f += 2; + break; case LLDP_TLV_MED_IV_HW: case LLDP_TLV_MED_IV_SW: case LLDP_TLV_MED_IV_FW: @@ -649,7 +704,15 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, if (size <= 4) b = NULL; else { - b = (char*)malloc(size - 3); + if ((b = (char*)malloc(size - 3)) == + NULL) { + LLOG_WARN("unable to allocate " + "memory for LLDP-MED " + "inventory for frame " + "received on %s", + hardware->h_ifname); + goto malformed; + } strlcpy(b, (char*)(frame + f), size - 3); diff --git a/src/lldp.h b/src/lldp.h index a16d26dd..7f74f9ad 100644 --- a/src/lldp.h +++ b/src/lldp.h @@ -251,6 +251,19 @@ enum { #define LLDPMED_CLASS_III 3 #define LLDPMED_NETWORK_DEVICE 4 +#define LLDPMED_APPTYPE_VOICE 1 +#define LLDPMED_APPTYPE_VOICESIGNAL 2 +#define LLDPMED_APPTYPE_GUESTVOICE 3 +#define LLDPMED_APPTYPE_GUESTVOICESIGNAL 4 +#define LLDPMED_APPTYPE_SOFTPHONEVOICE 5 +#define LLDPMED_APPTYPE_VIDEOCONFERENCE 6 +#define LLDPMED_APPTYPE_VIDEOSTREAM 7 +#define LLDPMED_APPTYPE_VIDEOSIGNAL 8 + +#define LLDPMED_LOCFORMAT_COORD 1 +#define LLDPMED_LOCFORMAT_CIVIC 2 +#define LLDPMED_LOCFORMAT_ELIN 3 + #define LLDPMED_CAP_CAP 0x01 #define LLDPMED_CAP_POLICY 0x02 #define LLDPMED_CAP_LOCATION 0x04 @@ -265,7 +278,6 @@ struct lldpmed_cap { u_int16_t tlv_cap; u_int8_t tlv_type; } __attribute__ ((__packed__)); - #endif /* ENABLE_LLDPMED */ diff --git a/src/lldpctl.c b/src/lldpctl.c index 2c24cb3c..ea78ee09 100644 --- a/src/lldpctl.c +++ b/src/lldpctl.c @@ -251,7 +251,7 @@ pretty_print(char *string) void display_med(struct lldpd_chassis *chassis) { - printf(" LLDP-MED device type: "); + printf(" LLDP-MED Device Type: "); switch (chassis->c_med_type) { case LLDPMED_CLASS_I: printf("Generic Endpoint (Class I)"); @@ -269,7 +269,7 @@ display_med(struct lldpd_chassis *chassis) printf("Unknown (%d)", chassis->c_med_type); break; } - printf("\n LLDP-MED capabilities:"); + printf("\n LLDP-MED Capabilities:"); if (chassis->c_med_cap & LLDPMED_CAP_CAP) printf(" Capabilities"); if (chassis->c_med_cap & LLDPMED_CAP_POLICY) @@ -281,6 +281,128 @@ display_med(struct lldpd_chassis *chassis) if (chassis->c_med_cap & LLDPMED_CAP_IV) printf(" Inventory"); printf("\n"); + if (chassis->c_med_policy) { + printf(" LLDP-MED Network Policy:\n"); + printf(" Application Type: "); + switch(chassis->c_med_policy >> 24) { + case LLDPMED_APPTYPE_VOICE: + printf("Voice"); + break; + case LLDPMED_APPTYPE_VOICESIGNAL: + printf("Voice Signaling"); + break; + case LLDPMED_APPTYPE_GUESTVOICE: + printf("Guest Voice"); + break; + case LLDPMED_APPTYPE_GUESTVOICESIGNAL: + printf("Guest Voice Signaling"); + break; + case LLDPMED_APPTYPE_SOFTPHONEVOICE: + printf("Softphone Voice"); + break; + case LLDPMED_APPTYPE_VIDEOCONFERENCE: + printf("Video Conferencing"); + break; + case LLDPMED_APPTYPE_VIDEOSTREAM: + printf("Streaming Video"); + break; + case LLDPMED_APPTYPE_VIDEOSIGNAL: + printf("Video Signaling"); + break; + default: + printf("Reserved"); + } + printf("\n Policy: "); + if((chassis->c_med_policy & 0x00800000) == 0x00800000) { + printf("unknown, "); + } else { + printf("defined, "); + } + if((chassis->c_med_policy & 0x00400000) != 0x00400000) { + printf("un"); + } + printf("tagged"); + printf("\n VLAN ID: "); + if((chassis->c_med_policy & 0x001FFE00) >> 9 == 0) { + printf("Priority Tagged"); + } else if((chassis->c_med_policy & 0x001FFE00) >> 9 == 4095) { + printf("reserved"); + } else { + printf("%u", (chassis->c_med_policy & 0x001FFE00) >> 9); + } + printf("\n Layer 2 Priority: "); + printf("%u", (chassis->c_med_policy & 0x000001C0) >> 6); + printf("\n DSCP Value: "); + printf("%u", (chassis->c_med_policy & 0x0000003F)); + } + printf("\n"); + if (chassis->c_med_locformat) { + printf(" LLDP-MED Location Identification:\n"); + switch(chassis->c_med_locformat) { + case LLDPMED_LOCFORMAT_COORD: + printf(" Coordinate-based data"); + break; + case LLDPMED_LOCFORMAT_CIVIC: + printf(" Civic address"); + break; + case LLDPMED_LOCFORMAT_ELIN: + printf(" ECS ELIN"); + break; + default: + printf("unknown location data format"); + } + printf("\n data: %s\n", dump(chassis->c_med_locdata, + chassis->c_med_locsize, 40, ' ')); + } + printf("\n"); + if (chassis->c_med_powtype) { + printf(" LLDP-MED Extended Power-over-Ethernet:\n"); + printf(" Power Type & Source: "); + if((chassis->c_med_powtype & 0xC0) == 0x00) { + printf("PSE Device"); + if((chassis->c_med_powtype & 0x30) == 0x00) { + printf(", unknown"); + } else if((chassis->c_med_powtype & 0x30) == 0x10) { + printf(", Primary Power Source"); + } else if((chassis->c_med_powtype & 0x30) == 0x20) { + printf(", Backup Power Source / Power Conservation Mode"); + } else { + printf(""); + } + } else if((chassis->c_med_powtype & 0xC0) == 0x40) { + printf("PD Device"); + if((chassis->c_med_powtype & 0x30) == 0x00) { + printf(", unknown"); + } else if((chassis->c_med_powtype & 0x30) == 0x10) { + printf(", PSE"); + } else if((chassis->c_med_powtype & 0x30) == 0x20) { + printf(", local"); + } else { + printf(", PSE & local"); + } + } else { + printf("reserved"); + } + printf("\n Power Priority: "); + if((chassis->c_med_powtype & 0x0F) == 0x00) { + printf("unknown"); + } else if((chassis->c_med_powtype & 0x0F) == 0x01) { + printf("critical"); + } else if((chassis->c_med_powtype & 0x0F) == 0x02) { + printf("high"); + } else if((chassis->c_med_powtype & 0x0F) == 0x03) { + printf("low"); + } else { + printf("reserved"); + } + printf("\n Power Value: "); + if(chassis->c_med_powval < 1024) { + printf("%u mW", chassis->c_med_powval * 100); + } else { + printf("reserved"); + } + } + printf("\n"); if (chassis->c_med_hw || chassis->c_med_sw || chassis->c_med_fw || diff --git a/src/lldpd.h b/src/lldpd.h index 6312c1df..bb5377b4 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -84,9 +84,15 @@ struct lldpd_chassis { u_int32_t c_mgmt_if; #ifdef ENABLE_LLDPMED -#define STRUCT_LLDPD_CHASSIS_MED "wbsssssss" +#define STRUCT_LLDPD_CHASSIS_MED "wblwbsbwsssssss" u_int16_t c_med_cap; u_int8_t c_med_type; + u_int32_t c_med_policy; + u_int16_t c_med_locsize; + u_int8_t c_med_locformat; + char *c_med_locdata; + u_int8_t c_med_powtype; + u_int16_t c_med_powval; char *c_med_hw; char *c_med_fw; char *c_med_sw;