]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
Add support for 802.3at.
authorVincent Bernat <bernat@luffy.cx>
Sat, 5 Jun 2010 17:51:55 +0000 (19:51 +0200)
committerVincent Bernat <bernat@luffy.cx>
Tue, 26 Apr 2011 05:48:15 +0000 (07:48 +0200)
This includes send and receive support as well as SNMP support.
802.3at seems to not define OID that should be used as well as the
mapping for bit values. Therefore, the implementation is a wild guess
of what is consistent with 802.1ab.

CHANGELOG
man/lldpctl.8
src/agent.c
src/display.c
src/lldp.c
src/lldp.h
src/lldpctl.c
src/lldpd.h

index 50e1aaa4462060da7fb9de3bba071f9de631f7d2..8b3d7032070e97c38f3fe16651cd39867eda2659 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,7 +17,7 @@ lldpd (0.5.1)
     + Allow to set LLDP-MED network policy from lldpctl, thanks to a patch from
       Philipp Kempgen.
     + Allow to set LLDP-MED POE-MDI from lldpctl.
-    + Handle Dot3 POE-MDI TLV (802.3af).
+    + Handle Dot3 POE-MDI TLV (802.3af and 802.3at).
     + Allow to set Dot3 POE-MDI from lldpctl.
     + Add a summary of available options in "lldpd -h" and "lldpctl -h",
       thanks to a patch from Jorge Boncompte.
index c1f3ccd609dcd22b49783961c0872bb1f7a5a383..eb7040d53451dbc9571a53d52787cba3566e7701 100644 (file)
@@ -354,6 +354,17 @@ The format of this option is (without spaces):
 .Ar powerpairs
 :
 .Ar class
+[ :
+.Ar powertype
+:
+.Ar source
+:
+.Ar priority
+:
+.Ar requested
+:
+.Ar allocated
+]
 .Bl -tag -width "XX"
 .It Ar type
 Valid types are:
@@ -401,6 +412,24 @@ means that MDI power is enabled on the given port.
 .Ar paircontrol
 is used to indicate if the pair selection can be controlled on the
 given port.
+.Pp
+.Ar powertype ,
+.Ar source ,
+.Ar priority
+(and remaining values) are optional. They are only requested in
+conformance with 802.3at.
+.Ar type
+should be either 1 or 2. For the possible values of the next two
+fields, see the possible values of
+.Ar source
+and
+.Ar priority
+for LLDP-MED MDI/POE.
+.Ar requested
+and
+.Ar allocated
+are respectively the PD requested power value and the PSE allocated
+power value. This should be expressed in tenth of watts from 1 to 255.
 .El
 .Sh FILES
 .Bl -tag -width "/var/run/lldpd.socketXX" -compact
index 882bb00b0ab220722783cee3960b3c29563a4556..47eeac85b291960dfdb4c54a2debb081c0450c7e 100644 (file)
@@ -407,7 +407,12 @@ header_tprvindexed_table(struct variable *vp, oid *name, size_t *length,
 #define LLDP_SNMP_LOCAL_DOT3_POWER_PAIRCONTROL 15
 #define LLDP_SNMP_LOCAL_DOT3_POWER_PAIRS 16
 #define LLDP_SNMP_LOCAL_DOT3_POWER_CLASS 17
-#define LLDP_SNMP_LOCAL_DOT1_PVID 18
+#define LLDP_SNMP_LOCAL_DOT3_POWER_TYPE 18
+#define LLDP_SNMP_LOCAL_DOT3_POWER_SOURCE 19
+#define LLDP_SNMP_LOCAL_DOT3_POWER_PRIORITY 20
+#define LLDP_SNMP_LOCAL_DOT3_POWER_REQUESTED 21
+#define LLDP_SNMP_LOCAL_DOT3_POWER_ALLOCATED 22
+#define LLDP_SNMP_LOCAL_DOT1_PVID 23
 /* Remote ports */
 #define LLDP_SNMP_REMOTE_CIDSUBTYPE 1
 #define LLDP_SNMP_REMOTE_CID 2
@@ -431,7 +436,12 @@ header_tprvindexed_table(struct variable *vp, oid *name, size_t *length,
 #define LLDP_SNMP_REMOTE_DOT3_POWER_PAIRCONTROL 20
 #define LLDP_SNMP_REMOTE_DOT3_POWER_PAIRS 21
 #define LLDP_SNMP_REMOTE_DOT3_POWER_CLASS 22
-#define LLDP_SNMP_REMOTE_DOT1_PVID 23
+#define LLDP_SNMP_REMOTE_DOT3_POWER_TYPE 23
+#define LLDP_SNMP_REMOTE_DOT3_POWER_SOURCE 24
+#define LLDP_SNMP_REMOTE_DOT3_POWER_PRIORITY 25
+#define LLDP_SNMP_REMOTE_DOT3_POWER_REQUESTED 26
+#define LLDP_SNMP_REMOTE_DOT3_POWER_ALLOCATED 27
+#define LLDP_SNMP_REMOTE_DOT1_PVID 28
 /* Local vlans */
 #define LLDP_SNMP_LOCAL_DOT1_VLANNAME 1
 /* Remote vlans */
@@ -1131,6 +1141,46 @@ agent_h_local_port(struct variable *vp, oid *name, size_t *length,
                        return (u_char *)&long_ret;
                }
                break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_TYPE:
+               if (hardware->h_lport.p_power.devicetype &&
+                   hardware->h_lport.p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       *var_len = 1;
+                       bit = (((hardware->h_lport.p_power.powertype ==
+                                   LLDP_DOT3_POWER_8023AT_TYPE1)?1:0) << 7) |
+                           (((hardware->h_lport.p_power.devicetype ==
+                                   LLDP_DOT3_POWER_PSE)?0:1) << 6);
+                       return (u_char *)&bit;
+               }
+               break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_SOURCE:
+               if (hardware->h_lport.p_power.devicetype &&
+                   hardware->h_lport.p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       *var_len = 1;
+                       bit = swap_bits(hardware->h_lport.p_power.source%(1<<2));
+                       return (u_char *)&bit;
+               }
+               break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_PRIORITY:
+               if (hardware->h_lport.p_power.devicetype &&
+                   hardware->h_lport.p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       long_ret = hardware->h_lport.p_power.priority;
+                       return (u_char *)&long_ret;
+               }
+               break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_REQUESTED:
+               if (hardware->h_lport.p_power.devicetype &&
+                   hardware->h_lport.p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       long_ret = hardware->h_lport.p_power.requested;
+                       return (u_char *)&long_ret;
+               }
+               break;
+       case LLDP_SNMP_LOCAL_DOT3_POWER_ALLOCATED:
+               if (hardware->h_lport.p_power.devicetype &&
+                   hardware->h_lport.p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       long_ret = hardware->h_lport.p_power.allocated;
+                       return (u_char *)&long_ret;
+               }
+               break;
 #endif
 #ifdef ENABLE_DOT1
        case LLDP_SNMP_LOCAL_DOT1_PVID:
@@ -1289,6 +1339,46 @@ agent_h_remote_port(struct variable *vp, oid *name, size_t *length,
                        return (u_char *)&long_ret;
                }
                break;
+       case LLDP_SNMP_REMOTE_DOT3_POWER_TYPE:
+               if (port->p_power.devicetype &&
+                   port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       *var_len = 1;
+                       bit = (((port->p_power.powertype ==
+                                   LLDP_DOT3_POWER_8023AT_TYPE1)?1:0) << 7) |
+                           (((port->p_power.devicetype ==
+                                   LLDP_DOT3_POWER_PSE)?0:1) << 6);
+                       return (u_char *)&bit;
+               }
+               break;
+       case LLDP_SNMP_REMOTE_DOT3_POWER_SOURCE:
+               if (port->p_power.devicetype &&
+                   port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       *var_len = 1;
+                       bit = swap_bits(port->p_power.source%(1<<2));
+                       return (u_char *)&bit;
+               }
+               break;
+       case LLDP_SNMP_REMOTE_DOT3_POWER_PRIORITY:
+               if (port->p_power.devicetype &&
+                   port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       long_ret = port->p_power.priority;
+                       return (u_char *)&long_ret;
+               }
+               break;
+       case LLDP_SNMP_REMOTE_DOT3_POWER_REQUESTED:
+               if (port->p_power.devicetype &&
+                   port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       long_ret = port->p_power.requested;
+                       return (u_char *)&long_ret;
+               }
+               break;
+       case LLDP_SNMP_REMOTE_DOT3_POWER_ALLOCATED:
+               if (port->p_power.devicetype &&
+                   port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       long_ret = port->p_power.allocated;
+                       return (u_char *)&long_ret;
+               }
+               break;
 #endif
 #ifdef ENABLE_DOT1
         case LLDP_SNMP_REMOTE_DOT1_PVID:
@@ -1441,6 +1531,16 @@ static struct variable8 lldp_vars[] = {
         {1, 5, 4623, 1, 2, 2, 1, 5}},
        {LLDP_SNMP_LOCAL_DOT3_POWER_CLASS, ASN_INTEGER, RONLY, agent_h_local_port, 8,
         {1, 5, 4623, 1, 2, 2, 1, 6}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_TYPE, ASN_OCTET_STR, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 7}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_SOURCE, ASN_OCTET_STR, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 8}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_PRIORITY, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 9}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_REQUESTED, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 10}},
+       {LLDP_SNMP_LOCAL_DOT3_POWER_ALLOCATED, ASN_INTEGER, RONLY, agent_h_local_port, 8,
+        {1, 5, 4623, 1, 2, 2, 1, 11}},
         {LLDP_SNMP_LOCAL_DOT3_AGG_STATUS, ASN_OCTET_STR, RONLY, agent_h_local_port, 8,
          {1, 5, 4623, 1, 2, 3, 1, 1}},
         {LLDP_SNMP_LOCAL_DOT3_AGG_ID, ASN_INTEGER, RONLY, agent_h_local_port, 8,
@@ -1483,6 +1583,16 @@ static struct variable8 lldp_vars[] = {
         {1, 5, 4623, 1, 3, 2, 1, 5}},
        {LLDP_SNMP_REMOTE_DOT3_POWER_CLASS, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
         {1, 5, 4623, 1, 3, 2, 1, 6}},
+       {LLDP_SNMP_REMOTE_DOT3_POWER_TYPE, ASN_OCTET_STR, RONLY, agent_h_remote_port, 8,
+        {1, 5, 4623, 1, 3, 2, 1, 7}},
+       {LLDP_SNMP_REMOTE_DOT3_POWER_SOURCE, ASN_OCTET_STR, RONLY, agent_h_remote_port, 8,
+        {1, 5, 4623, 1, 3, 2, 1, 8}},
+       {LLDP_SNMP_REMOTE_DOT3_POWER_PRIORITY, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
+        {1, 5, 4623, 1, 3, 2, 1, 9}},
+       {LLDP_SNMP_REMOTE_DOT3_POWER_REQUESTED, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
+        {1, 5, 4623, 1, 3, 2, 1, 10}},
+       {LLDP_SNMP_REMOTE_DOT3_POWER_ALLOCATED, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
+        {1, 5, 4623, 1, 3, 2, 1, 11}},
         {LLDP_SNMP_REMOTE_DOT3_AGG_STATUS, ASN_OCTET_STR, RONLY, agent_h_remote_port, 8,
          {1, 5, 4623, 1, 3, 3, 1, 1}},
         {LLDP_SNMP_REMOTE_DOT3_AGG_ID, ASN_INTEGER, RONLY, agent_h_remote_port, 8,
index e3c1dd4b894c715cca500a2100414c0a032f6725..cde5fa0250abab24341b92772a9d812db0aa2043 100644 (file)
@@ -263,6 +263,25 @@ static const struct value_string port_dot3_power_class_map[] = {
        { 5, "class 4" },
        { 0, NULL }
 };
+
+static const struct value_string port_dot3_power_pse_source_map[] = {
+       { LLDP_DOT3_POWER_SOURCE_BOTH, "PSE + Local" },
+       { LLDP_DOT3_POWER_SOURCE_PSE, "PSE" },
+       { 0, NULL }
+};
+
+static const struct value_string port_dot3_power_pd_source_map[] = {
+       { LLDP_DOT3_POWER_SOURCE_BACKUP, "Backup source" },
+       { LLDP_DOT3_POWER_SOURCE_PRIMARY, "Primary power source" },
+       { 0, NULL }
+};
+
+static const struct value_string port_dot3_power_priority_map[] = {
+       { LLDPMED_POW_PRIO_CRITICAL, "critical" },
+       { LLDPMED_POW_PRIO_HIGH,     "high" },
+       { LLDPMED_POW_PRIO_LOW,      "low" },
+       { 0, NULL },
+};
 #endif
 
 static const struct value_string chassis_capability_map[] = {
@@ -922,6 +941,35 @@ display_port(struct writer * w, struct lldpd_port *port)
                tag_data(w, map_lookup(port_dot3_power_class_map,
                        port->p_power.class));
                tag_end(w);
+
+               /* 802.3at */
+               if (port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       tag_start(w, "power-type", "Power type");
+                       tag_data(w, u2str(port->p_power.powertype));
+                       tag_end(w);
+
+                       tag_start(w, "source", "Power Source");
+                       tag_data(w, map_lookup(
+                                   (port->p_power.devicetype == LLDP_DOT3_POWER_PSE)?
+                                       port_dot3_power_pse_source_map:
+                                       port_dot3_power_pd_source_map,
+                                       port->p_power.source));
+                       tag_end(w);
+
+                       tag_start(w, "priority", "Power Priority");
+                       tag_data(w, map_lookup(port_dot3_power_priority_map,
+                               port->p_power.priority));
+                       tag_end(w);
+
+                       tag_start(w, "requested", "PD requested power Value");
+                       tag_data(w, u2str(port->p_power.requested * 100));
+                       tag_end(w);
+
+                       tag_start(w, "allocated", "PSE allocated power Value");
+                       tag_data(w, u2str(port->p_power.allocated * 100));
+                       tag_end(w);
+               }
+
                tag_end(w);
        }
 #endif
index b48b4759725dd99acbda73ffec5af14151c6a4d0..28680f2851d4f286e56a5bd448f197b1229014a8 100644 (file)
@@ -210,8 +210,23 @@ lldp_send(struct lldpd *global,
                                  (( port->p_power.enabled            %(1<< 1))<<2) |
                                  (( port->p_power.paircontrol        %(1<< 1))<<3))) &&
                      POKE_UINT8(port->p_power.pairs) &&
-                     POKE_UINT8(port->p_power.class) &&
-                     POKE_END_LLDP_TLV))
+                     POKE_UINT8(port->p_power.class)))
+                       goto toobig;
+               /* 802.3at */
+               if (port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
+                       if (!(
+                             POKE_UINT8((
+                                         (((port->p_power.powertype ==
+                                             LLDP_DOT3_POWER_8023AT_TYPE1)?1:0) << 7) |
+                                          (((port->p_power.devicetype ==
+                                             LLDP_DOT3_POWER_PSE)?0:1) << 6) |
+                                          ((port->p_power.source   %(1<< 2))<<4) |
+                                          ((port->p_power.priority %(1<< 2))<<0))) &&
+                             POKE_UINT16(port->p_power.requested) &&
+                             POKE_UINT16(port->p_power.allocated)))
+                               goto toobig;
+               }
+               if (!(POKE_END_LLDP_TLV))
                        goto toobig;
        }
 #endif
@@ -613,6 +628,22 @@ lldp_decode(struct lldpd *cfg, char *frame, int s,
                                                LLDP_DOT3_POWER_PSE:LLDP_DOT3_POWER_PD;
                                        port->p_power.pairs = PEEK_UINT8;
                                        port->p_power.class = PEEK_UINT8;
+                                       /* 802.3at? */
+                                       if (tlv_size >= 12) {
+                                               port->p_power.powertype = PEEK_UINT8;
+                                               port->p_power.source =
+                                                   (port->p_power.powertype & (1<<5 | 1<<4)) >> 4;
+                                               port->p_power.priority =
+                                                   (port->p_power.powertype & (1<<1 | 1<<0));
+                                               port->p_power.powertype =
+                                                   (port->p_power.powertype & (1<<7))?
+                                                   LLDP_DOT3_POWER_8023AT_TYPE1:
+                                                   LLDP_DOT3_POWER_8023AT_TYPE2;
+                                               port->p_power.requested = PEEK_UINT16;
+                                               port->p_power.allocated = PEEK_UINT16;
+                                       } else
+                                               port->p_power.powertype =
+                                                   LLDP_DOT3_POWER_8023AT_OFF;
                                        break;
                                default:
                                        /* Unknown Dot3 TLV, ignore it */
index 08f36ffa01eab902121d3098b67160c83d9a54ea..06a15d67cf451fb558697bb834a7148674abebae 100644 (file)
@@ -127,6 +127,24 @@ enum {
 #define LLDP_DOT3_POWERPAIRS_SIGNAL 1
 #define LLDP_DOT3_POWERPAIRS_SPARE 2
 
+/* Dot3 Power type (for 802.3at) */
+#define LLDP_DOT3_POWER_8023AT_OFF 0
+#define LLDP_DOT3_POWER_8023AT_TYPE1 1
+#define LLDP_DOT3_POWER_8023AT_TYPE2 2
+
+/* Dot3 power source */
+#define LLDP_DOT3_POWER_SOURCE_UNKNOWN 0
+#define LLDP_DOT3_POWER_SOURCE_PRIMARY 1
+#define LLDP_DOT3_POWER_SOURCE_PSE 1
+#define LLDP_DOT3_POWER_SOURCE_BACKUP 2
+#define LLDP_DOT3_POWER_SOURCE_BOTH 3
+
+/* Dot3 power priority */
+#define LLDP_DOT3_POWER_PRIO_UNKNOWN 0
+#define LLDP_DOT3_POWER_PRIO_CRITICAL 1
+#define LLDP_DOT3_POWER_PRIO_HIGH 2
+#define LLDP_DOT3_POWER_PRIO_LOW 3
+
 /* PMD Auto-Negotiation Advertised Capability field, from RFC 3636 */
 #define LLDP_DOT3_LINK_AUTONEG_OTHER           0x8000
 #define LLDP_DOT3_LINK_AUTONEG_10BASE_T                0x4000
index 91bcd158ba1356f44825767720a6517d7e54ec23..bab295dee9b986e26c09174e9100cbcc5a539580 100644 (file)
@@ -464,22 +464,18 @@ static int
 lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
 {
        const char *e;
-       int device_type = 0;
-       int supported   = 0;
-       int enabled     = 0;
-       int paircontrol = 0;
-       int powerpairs  = 0;
-       int class       = 0;
+       struct lldpd_dot3_power target;
 
        if (strlen(poe) == 0)
                return 0;
        e = poe;
+       memset(&target, 0, sizeof(target));
 
        /* Device type */
        if (!strncmp(e, "PD", 2))
-               device_type = LLDP_DOT3_POWER_PD;
+               target.devicetype = LLDP_DOT3_POWER_PD;
        else if (!strncmp(e, "PSE", 3))
-               device_type = LLDP_DOT3_POWER_PSE;
+               target.devicetype = LLDP_DOT3_POWER_PSE;
        else {
                LLOG_WARNX("Device type should be either 'PD' or 'PSE'.");
                goto invalid_dot3_poe;
@@ -490,9 +486,9 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
                LLOG_WARNX("Expected power support.");
                goto invalid_dot3_poe;
        }
-       supported = atoi(++e);
-       if (supported < 0 || supported > 1) {
-               LLOG_WARNX("Power support should be 1 or 0, not %d", supported);
+       target.supported = atoi(++e);
+       if (target.supported > 1) {
+               LLOG_WARNX("Power support should be 1 or 0, not %d", target.supported);
                goto invalid_dot3_poe;
        }
 
@@ -501,9 +497,9 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
                LLOG_WARNX("Expected power ability.");
                goto invalid_dot3_poe;
        }
-       enabled = atoi(++e);
-       if (enabled < 0 || enabled > 1) {
-               LLOG_WARNX("Power ability should be 1 or 0, not %d", enabled);
+       target.enabled = atoi(++e);
+       if (target.enabled > 1) {
+               LLOG_WARNX("Power ability should be 1 or 0, not %d", target.enabled);
                goto invalid_dot3_poe;
        }
 
@@ -512,9 +508,10 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
                LLOG_WARNX("Expected power pair control ability.");
                goto invalid_dot3_poe;
        }
-       paircontrol = atoi(++e);
-       if (paircontrol < 0 || paircontrol > 1) {
-               LLOG_WARNX("Power pair control ability should be 1 or 0, not %d", paircontrol);
+       target.paircontrol = atoi(++e);
+       if (target.paircontrol > 1) {
+               LLOG_WARNX("Power pair control ability should be 1 or 0, not %d",
+                   target.paircontrol);
                goto invalid_dot3_poe;
        }
 
@@ -523,9 +520,9 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
                LLOG_WARNX("Expected power pairs.");
                goto invalid_dot3_poe;
        }
-       powerpairs = atoi(++e);
-       if (powerpairs < 1 || powerpairs > 2) {
-               LLOG_WARNX("Power pairs should be 1 or 2, not %d.", powerpairs);
+       target.pairs = atoi(++e);
+       if (target.pairs < 1 || target.pairs > 2) {
+               LLOG_WARNX("Power pairs should be 1 or 2, not %d.", target.pairs);
                goto invalid_dot3_poe;
        }
 
@@ -534,18 +531,58 @@ lldpd_parse_dot3_power(struct lldpd_port *port, const char *poe)
                LLOG_WARNX("Expected power class.");
                goto invalid_dot3_poe;
        }
-       class = atoi(++e);
-       if (class < 0 || class > 5) {
-               LLOG_WARNX("Power class out of range (%d).", class);
+       target.class = atoi(++e);
+       if (target.class > 5) {
+               LLOG_WARNX("Power class out of range (%d).", target.class);
+               goto invalid_dot3_poe;
+       }
+       /* 802.3at */
+       if ((e = strchr(e, ':')) == NULL) {
+               target.powertype = LLDP_DOT3_POWER_8023AT_OFF;
+               goto no8023at;
+       }
+       /* 802.3at: Power type */
+       target.powertype = atoi(++e);
+       if ((target.powertype != LLDP_DOT3_POWER_8023AT_TYPE1) &&
+           (target.powertype != LLDP_DOT3_POWER_8023AT_TYPE2)) {
+               LLOG_WARNX("Incorrect power type (%d).", target.powertype);
+               goto invalid_dot3_poe;
+       }
+       /* 802.3at: Source */
+       if ((e = strchr(e, ':')) == NULL) {
+               LLOG_WARNX("Expected power source.");
+               goto invalid_dot3_poe;
+       }
+       target.source = atoi(++e);
+       if (target.source > 3) {
+               LLOG_WARNX("Power source out of range (%d).", target.source);
+               goto invalid_dot3_poe;
+       }
+       /* 802.3at: priority */
+       if ((e = strchr(e, ':')) == NULL) {
+               LLOG_WARNX("Expected power priority.");
+               goto invalid_dot3_poe;
+       }
+       target.priority = atoi(++e);
+       if (target.priority > 3) {
+               LLOG_WARNX("Power priority out of range (%d).", target.priority);
+               goto invalid_dot3_poe;
+       }
+       /* 802.3at: requested */
+       if ((e = strchr(e, ':')) == NULL) {
+               LLOG_WARNX("Expected requested power value.");
+               goto invalid_dot3_poe;
+       }
+       target.requested = atoi(++e);
+       /* 802.3at: allocated */
+       if ((e = strchr(e, ':')) == NULL) {
+               LLOG_WARNX("Expected allocated power value.");
                goto invalid_dot3_poe;
        }
+       target.allocated = atoi(++e);
 
-       port->p_power.devicetype = device_type;
-       port->p_power.supported = supported;
-       port->p_power.enabled = enabled;
-       port->p_power.paircontrol = paircontrol;
-       port->p_power.pairs = powerpairs;
-       port->p_power.class = class;
+ no8023at:
+       memcpy(&port->p_power, &target, sizeof(target));
        return 0;
 
  invalid_dot3_poe:
index 20770bc260d643327d030d09123e55c059261247..f03bd14281ed9b1cb96f2b498847010a2aeccb98 100644 (file)
@@ -111,7 +111,7 @@ struct lldpd_dot3_macphy {
        u_int16_t                mau_type;
 };
 
-#define STRUCT_LLDPD_DOT3_POWER "(bbbbbb)"
+#define STRUCT_LLDPD_DOT3_POWER "(bbbbbbbbbww)"
 struct lldpd_dot3_power {
        u_int8_t                devicetype;
        u_int8_t                supported;
@@ -119,6 +119,12 @@ struct lldpd_dot3_power {
        u_int8_t                paircontrol;
        u_int8_t                pairs;
        u_int8_t                class;
+       u_int8_t                powertype; /* If set to LLDP_DOT3_POWER_8023AT_OFF,
+                                             following fields have no meaning */
+       u_int8_t                source;
+       u_int8_t                priority;
+       u_int16_t               requested;
+       u_int16_t               allocated;
 };
 #endif