From befbdf892b0e4005be873b8628fa9f732d24b669 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Sat, 8 May 2010 17:25:35 +0200 Subject: [PATCH] Add initial Dot3/802.3at support This includes ability to receive and store Dot3 MDI power TLV, to display them with lldpctl and to export them through SNMP agent. There is no support for 802.3af yet. --- src/agent.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/display.c | 43 ++++++++++++++++++++++++++++++++++++ src/lldp.c | 19 ++++++++++++++-- src/lldp.h | 8 +++++++ src/lldpd.h | 13 ++++++++++- 5 files changed, 139 insertions(+), 5 deletions(-) diff --git a/src/agent.c b/src/agent.c index 5cfd11f4..660a27e4 100644 --- a/src/agent.c +++ b/src/agent.c @@ -419,7 +419,13 @@ header_tprvindexed_table(struct variable *vp, oid *name, size_t *length, #define LLDP_SNMP_REMOTE_DOT3_AGG_STATUS 14 #define LLDP_SNMP_REMOTE_DOT3_AGG_ID 15 #define LLDP_SNMP_REMOTE_DOT3_MFS 16 -#define LLDP_SNMP_REMOTE_DOT1_PVID 17 +#define LLDP_SNMP_REMOTE_DOT3_POWER_DEVICETYPE 17 +#define LLDP_SNMP_REMOTE_DOT3_POWER_SUPPORT 18 +#define LLDP_SNMP_REMOTE_DOT3_POWER_ENABLED 19 +#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 /* Local vlans */ #define LLDP_SNMP_LOCAL_DOT1_VLANNAME 1 /* Remote vlans */ @@ -1201,6 +1207,42 @@ agent_h_remote_port(struct variable *vp, oid *name, size_t *length, case LLDP_SNMP_REMOTE_DOT3_MFS: long_ret = port->p_mfs; return (u_char *)&long_ret; + case LLDP_SNMP_REMOTE_DOT3_POWER_DEVICETYPE: + if (port->p_power.devicetype) { + long_ret = (port->p_power.devicetype == LLDP_DOT3_POWER_PSE)?1:2; + return (u_char *)&long_ret; + } + break; + case LLDP_SNMP_REMOTE_DOT3_POWER_SUPPORT: + if (port->p_power.devicetype) { + long_ret = (port->p_power.supported)?1:2; + return (u_char *)&long_ret; + } + break; + case LLDP_SNMP_REMOTE_DOT3_POWER_ENABLED: + if (port->p_power.devicetype) { + long_ret = (port->p_power.enabled)?1:2; + return (u_char *)&long_ret; + } + break; + case LLDP_SNMP_REMOTE_DOT3_POWER_PAIRCONTROL: + if (port->p_power.devicetype) { + long_ret = (port->p_power.paircontrol)?1:2; + return (u_char *)&long_ret; + } + break; + case LLDP_SNMP_REMOTE_DOT3_POWER_PAIRS: + if (port->p_power.devicetype) { + long_ret = port->p_power.pairs; + return (u_char *)&long_ret; + } + break; + case LLDP_SNMP_REMOTE_DOT3_POWER_CLASS: + if (port->p_power.devicetype && port->p_power.class) { + long_ret = port->p_power.class; + return (u_char *)&long_ret; + } + break; #endif #ifdef ENABLE_DOT1 case LLDP_SNMP_REMOTE_DOT1_PVID: @@ -1210,7 +1252,10 @@ agent_h_remote_port(struct variable *vp, oid *name, size_t *length, default: break; } - return NULL; + if (!exact && (name[*length-1] < MAX_SUBID)) + return agent_h_remote_port(vp, name, length, + exact, var_len, write_method); + return NULL; } static u_char* @@ -1368,6 +1413,18 @@ static struct variable8 lldp_vars[] = { {1, 5, 4623, 1, 3, 1, 1, 3}}, {LLDP_SNMP_REMOTE_DOT3_AUTONEG_MAU, ASN_INTEGER, RONLY, agent_h_remote_port, 8, {1, 5, 4623, 1, 3, 1, 1, 4}}, + {LLDP_SNMP_REMOTE_DOT3_POWER_DEVICETYPE, ASN_INTEGER, RONLY, agent_h_remote_port, 8, + {1, 5, 4623, 1, 3, 2, 1, 1}}, + {LLDP_SNMP_REMOTE_DOT3_POWER_SUPPORT, ASN_INTEGER, RONLY, agent_h_remote_port, 8, + {1, 5, 4623, 1, 3, 2, 1, 2}}, + {LLDP_SNMP_REMOTE_DOT3_POWER_ENABLED, ASN_INTEGER, RONLY, agent_h_remote_port, 8, + {1, 5, 4623, 1, 3, 2, 1, 3}}, + {LLDP_SNMP_REMOTE_DOT3_POWER_PAIRCONTROL, ASN_INTEGER, RONLY, agent_h_remote_port, 8, + {1, 5, 4623, 1, 3, 2, 1, 4}}, + {LLDP_SNMP_REMOTE_DOT3_POWER_PAIRS, ASN_INTEGER, RONLY, agent_h_remote_port, 8, + {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_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, diff --git a/src/display.c b/src/display.c index 0010fee1..e3c1dd4b 100644 --- a/src/display.c +++ b/src/display.c @@ -242,6 +242,27 @@ static const struct value_string operational_mau_type_values[] = { { 53, "1000BasePX20U - One single-mode fiber EPON ONU, 20km" }, { 0, NULL } }; + +static const struct value_string port_dot3_power_devicetype_map[] = { + { LLDP_DOT3_POWER_PSE, "PSE" }, + { LLDP_DOT3_POWER_PD, "PD" }, + { 0, NULL } +}; + +static const struct value_string port_dot3_power_pairs_map[] = { + { LLDP_DOT3_POWERPAIRS_SIGNAL, "signal" }, + { LLDP_DOT3_POWERPAIRS_SPARE, "spare" }, + { 0, NULL } +}; + +static const struct value_string port_dot3_power_class_map[] = { + { 1, "class 0" }, + { 2, "class 1" }, + { 3, "class 2" }, + { 4, "class 3" }, + { 5, "class 4" }, + { 0, NULL } +}; #endif static const struct value_string chassis_capability_map[] = { @@ -881,6 +902,28 @@ display_port(struct writer * w, struct lldpd_port *port) map_lookup(operational_mau_type_values, port->p_macphy.mau_type)); tag_end(w); } + if (port->p_power.devicetype) { + tag_start(w, "power", "MDI Power"); + tag_attr(w, "supported", "supported", + port->p_power.supported?"yes":"no"); + tag_attr(w, "enabled", "enabled", + port->p_power.enabled?"yes":"no"); + tag_attr(w, "paircontrol", "pair control", + port->p_power.paircontrol?"yes":"no"); + tag_start(w, "device-type", "Device type"); + tag_data(w, map_lookup(port_dot3_power_devicetype_map, + port->p_power.devicetype)); + tag_end(w); + tag_start(w, "pairs", "Power pairs"); + tag_data(w, map_lookup(port_dot3_power_pairs_map, + port->p_power.pairs)); + tag_end(w); + tag_start(w, "class", "Class"); + tag_data(w, map_lookup(port_dot3_power_class_map, + port->p_power.class)); + tag_end(w); + tag_end(w); + } #endif tag_end(w); } diff --git a/src/lldp.c b/src/lldp.c index 09143f2c..d58f579b 100644 --- a/src/lldp.c +++ b/src/lldp.c @@ -567,9 +567,9 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, CHECK_TLV_SIZE(9, "MAC/PHY"); port->p_macphy.autoneg_support = PEEK_UINT8; port->p_macphy.autoneg_enabled = - port->p_macphy.autoneg_support && 0x2; + port->p_macphy.autoneg_support & 0x2; port->p_macphy.autoneg_support = - port->p_macphy.autoneg_support && 0x1; + port->p_macphy.autoneg_support & 0x1; port->p_macphy.autoneg_advertised = PEEK_UINT16; port->p_macphy.mau_type = PEEK_UINT16; @@ -583,6 +583,21 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, CHECK_TLV_SIZE(6, "MFS"); port->p_mfs = PEEK_UINT16; break; + case LLDP_TLV_DOT3_POWER: + CHECK_TLV_SIZE(7, "Power"); + port->p_power.devicetype = PEEK_UINT8; + port->p_power.supported = + port->p_power.devicetype & 0x2; + port->p_power.enabled = + port->p_power.devicetype & 0x4; + port->p_power.paircontrol = + port->p_power.devicetype & 0x8; + port->p_power.devicetype = + (port->p_power.devicetype & 0x1)? + LLDP_DOT3_POWER_PSE:LLDP_DOT3_POWER_PD; + port->p_power.pairs = PEEK_UINT8; + port->p_power.class = PEEK_UINT8; + break; default: /* Unknown Dot3 TLV, ignore it */ hardware->h_rx_unrecognized_cnt++; diff --git a/src/lldp.h b/src/lldp.h index f1b5f947..08f36ffa 100644 --- a/src/lldp.h +++ b/src/lldp.h @@ -119,6 +119,14 @@ enum { #define LLDP_DOT3_MAU_10GIGBASELW 39 #define LLDP_DOT3_MAU_10GIGBASESW 40 +/* Dot3 Power Devicetype */ +#define LLDP_DOT3_POWER_PSE 1 +#define LLDP_DOT3_POWER_PD 2 + +/* Dot3 Power Pairs (RFC 3621) */ +#define LLDP_DOT3_POWERPAIRS_SIGNAL 1 +#define LLDP_DOT3_POWERPAIRS_SPARE 2 + /* PMD Auto-Negotiation Advertised Capability field, from RFC 3636 */ #define LLDP_DOT3_LINK_AUTONEG_OTHER 0x8000 #define LLDP_DOT3_LINK_AUTONEG_10BASE_T 0x4000 diff --git a/src/lldpd.h b/src/lldpd.h index 89b0d3d2..f93478e8 100644 --- a/src/lldpd.h +++ b/src/lldpd.h @@ -110,6 +110,16 @@ struct lldpd_dot3_macphy { u_int16_t autoneg_advertised; u_int16_t mau_type; }; + +#define STRUCT_LLDPD_DOT3_POWER "(bbbbbb)" +struct lldpd_dot3_power { + u_int8_t devicetype; + u_int8_t supported; + u_int8_t enabled; + u_int8_t paircontrol; + u_int8_t pairs; + u_int8_t class; +}; #endif struct lldpd_chassis { @@ -165,10 +175,11 @@ struct lldpd_port { u_int8_t p_hidden_out:2; /* Considered as hidden for emission */ #ifdef ENABLE_DOT3 -#define STRUCT_LLDPD_PORT_DOT3 "l" STRUCT_LLDPD_DOT3_MACPHY +#define STRUCT_LLDPD_PORT_DOT3 "l" STRUCT_LLDPD_DOT3_MACPHY STRUCT_LLDPD_DOT3_POWER /* Dot3 stuff */ u_int32_t p_aggregid; struct lldpd_dot3_macphy p_macphy; + struct lldpd_dot3_power p_power; #else #define STRUCT_LLDPD_PORT_DOT3 "" #endif -- 2.39.5