]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
More LLDP-MED support, thanks to Michael Hanig.
authorVincent Bernat <bernat@luffy.cx>
Fri, 5 Dec 2008 21:43:08 +0000 (22:43 +0100)
committerVincent Bernat <bernat@luffy.cx>
Fri, 5 Dec 2008 21:43:08 +0000 (22:43 +0100)
CHANGELOG
src/lldp.c
src/lldp.h
src/lldpctl.c
src/lldpd.h

index 411fd44fa1d939223cede93821e566ec67cbc493..6b1aba3e161c5c1dab275a2f6df200ccfa78fb39 100644 (file)
--- 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 <bernat@luffy.cx>
index bd36c13751d2e6f2edbcc2c0eda10b8463502cde..25186c79455c888d40dba5a2c8737a80b3e53e85 100644 (file)
@@ -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);
index a16d26dd35abad754c47c443ee59805c98f20321..7f74f9add6a84a44d221fc7b5a96bb536503a991 100644 (file)
@@ -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 */
 
 
index 2c24cb3ce030d412cd7cd1320da7d6b879a73b6b..ea78ee09c07ab1a3cd231cc7b4d00315fed157fc 100644 (file)
@@ -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 ||
index 6312c1dfb3101bbdb235e207a0615f7149857460..bb5377b463a8c25daacb26856559900efa3ccff4 100644 (file)
@@ -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;