is enabled.
+ Stricter on LLDP incoming frames validation.
+ Add support for VLAN-aware bridges for Linux (no range support).
+ + Add support for 802.3BT (no SNMP support).
* Fix:
+ Don't clear chassis TLV on shutdown LLDPDU.
tag_end(w);
}
+ /* 802.3bt */
+ if (lldpctl_atom_get_int(dot3_power,
+ lldpctl_k_dot3_power_type_ext) > LLDP_DOT3_POWER_8023BT_OFF) {
+ tag_start(w, "requested-a", "Requested mode A");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_requested_a));
+ tag_end(w);
+ tag_start(w, "requested-b", "Requested mode B");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_requested_b));
+ tag_end(w);
+ tag_start(w, "allocated-a", "Allocated alternative A");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_allocated_a));
+ tag_end(w);
+ tag_start(w, "allocated-b", "Allocated alternative B");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_allocated_b));
+ tag_end(w);
+ tag_start(w, "pse-powering-status", "PSE powering status");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_pse_status));
+ tag_end(w);
+ tag_start(w, "pd-powering-status", "PD powering status");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_pd_status));
+ tag_end(w);
+ tag_start(w, "power-pairs-ext", "Power pairs extra");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_pse_pairs_ext));
+ tag_end(w);
+ tag_start(w, "power-class-ext-a", "Class extra A");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_class_a));
+ tag_end(w);
+ tag_start(w, "power-class-ext-b", "Class extra B");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_class_b));
+ tag_end(w);
+ tag_start(w, "power-class-ext", "Class extra");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_class_ext));
+ tag_end(w);
+ tag_start(w, "power-type-ext", "Power type extra");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_type_ext));
+ tag_end(w);
+ tag_start(w, "pd-load", "PD load");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_pd_load));
+ tag_end(w);
+ tag_start(w, "max-power", "PSE maximum available power");
+ tag_data(w, lldpctl_atom_get_str(dot3_power,
+ lldpctl_k_dot3_power_pse_max));
+ tag_end(w);
+ }
+
tag_end(w);
}
lldpctl_atom_dec_ref(dot3_power);
selected_port->p_power.allocated,
hardware->h_lport.p_power.allocated);
hardware->h_lport.p_power.allocated = selected_port->p_power.allocated;
+ hardware->h_lport.p_power.allocated_a = selected_port->p_power.allocated_a;
+ hardware->h_lport.p_power.allocated_b = selected_port->p_power.allocated_b;
levent_schedule_pdu(hardware);
}
/* Power */
if (port->p_power.devicetype) {
if (!(
- POKE_START_LLDP_TLV(LLDP_TLV_ORG) &&
+ (port->p_power.type_ext != LLDP_DOT3_POWER_8023BT_OFF ?
+ (tlv = pos, POKE_UINT16((LLDP_TLV_ORG << 9) | (0x1d))):
+ POKE_START_LLDP_TLV(LLDP_TLV_ORG)) &&
POKE_BYTES(dot3, sizeof(dot3)) &&
POKE_UINT8(LLDP_TLV_DOT3_POWER) &&
POKE_UINT8((
- (((2 - port->p_power.devicetype) %(1<< 1))<<0) |
- (( port->p_power.supported %(1<< 1))<<1) |
- (( port->p_power.enabled %(1<< 1))<<2) |
- (( port->p_power.paircontrol %(1<< 1))<<3))) &&
+ (((2 - port->p_power.devicetype) %(1<< 1))<<0) |
+ (( port->p_power.supported %(1<< 1))<<1) |
+ (( 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)))
goto toobig;
/* 802.3at */
if (port->p_power.powertype != LLDP_DOT3_POWER_8023AT_OFF) {
if (!(
- POKE_UINT8((
- (((port->p_power.powertype ==
+ POKE_UINT8(((((port->p_power.powertype ==
LLDP_DOT3_POWER_8023AT_TYPE1)?1:0) << 7) |
- (((port->p_power.devicetype ==
+ (((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)))
+ ((port->p_power.source %(1<< 2))<<4) |
+ ((port->p_power.pd_4pid %(1 << 1))<<2) |
+ ((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;
+ if (port->p_power.type_ext != LLDP_DOT3_POWER_8023BT_OFF) {
+ if (!(
+ POKE_UINT16(port->p_power.requested_a) &&
+ POKE_UINT16(port->p_power.requested_b) &&
+ POKE_UINT16(port->p_power.allocated_a) &&
+ POKE_UINT16(port->p_power.allocated_b) &&
+ POKE_UINT16((
+ (port->p_power.pse_status << 14) |
+ (port->p_power.pd_status << 12) |
+ (port->p_power.pse_pairs_ext << 10) |
+ (port->p_power.class_a << 7) |
+ (port->p_power.class_b << 4) |
+ (port->p_power.class_ext << 0))) &&
+ POKE_UINT8(
+ /* Adjust by -1 to enable 0 to mean no 802.3bt support */
+ ((port->p_power.type_ext -1) << 1) |
+ (port->p_power.pd_load << 0)) &&
+ POKE_UINT16(port->p_power.pse_max) &&
+ /* Send 0 for autoclass and power down requests */
+ POKE_UINT8(0) &&
+ POKE_UINT16(0) &&
+ POKE_UINT8(0)))
+ goto toobig;
+ }
+ if (!(POKE_END_LLDP_TLV))
+ goto toobig;
}
#endif
} else
port->p_power.powertype =
LLDP_DOT3_POWER_8023AT_OFF;
+ /* 802.3bt? */
+ if (tlv_size >= 29) {
+ port->p_power.requested_a = PEEK_UINT16;
+ port->p_power.requested_b = PEEK_UINT16;
+ port->p_power.allocated_a = PEEK_UINT16;
+ port->p_power.allocated_b = PEEK_UINT16;
+ port->p_power.pse_status = PEEK_UINT16;
+ port->p_power.pd_status =
+ (port->p_power.pse_status & (1<<13 | 1<<12)) >> 12;
+ port->p_power.pse_pairs_ext =
+ (port->p_power.pse_status & (1<<11 | 1<<10)) >> 10;
+ port->p_power.class_a =
+ (port->p_power.pse_status & (1<<9 | 1<<8 | 1<<7)) >> 7;
+ port->p_power.class_b =
+ (port->p_power.pse_status & (1<<6 | 1<<5 | 1<<4)) >> 4;
+ port->p_power.class_ext =
+ (port->p_power.pse_status & 0xf);
+ port->p_power.pse_status =
+ (port->p_power.pse_status & (1<<15 | 1<<14)) >> 14;
+ port->p_power.type_ext = PEEK_UINT8;
+ port->p_power.pd_load =
+ (port->p_power.type_ext & 0x1);
+ port->p_power.type_ext =
+ ((port->p_power.type_ext & (1<<3 | 1<<2 | 1<<1)) + 1);
+ port->p_power.pse_max = PEEK_UINT16;
+ } else {
+ port->p_power.type_ext =
+ LLDP_DOT3_POWER_8023BT_OFF;
+ }
break;
default:
/* Unknown Dot3 TLV, ignore it */
},
};
+static struct atom_map port_dot3_power_pd_4pid_map = {
+ .key = lldpctl_k_dot3_power_pd_4pid,
+ .map = {
+ { 0, "PD does not support powering both modes" },
+ { 1, "PD supports powering both modes" },
+ },
+};
+
+static struct atom_map port_dot3_power_pse_status_map = {
+ .key = lldpctl_k_dot3_power_pse_status,
+ .map = {
+ { 0, "Unknown" },
+ { 1, "2-pair powering" },
+ { 2, "4-pair powering dual-signature PD" },
+ { 3, "4-pair powering single-signature PD" },
+ },
+};
+
+static struct atom_map port_dot3_power_pd_status_map = {
+ .key = lldpctl_k_dot3_power_pd_status,
+ .map = {
+ { 0, "Unknown" },
+ { 1, "2-pair powered PD" },
+ { 2, "4-pair powered dual-signature PD" },
+ { 3, "4-pair powered single-signature PD" },
+ },
+};
+
+static struct atom_map port_dot3_power_pse_pairs_ext_map = {
+ .key = lldpctl_k_dot3_power_pse_pairs_ext,
+ .map = {
+ { 0, "Unknown" },
+ { 1, "Alternative A" },
+ { 2, "Alternative B" },
+ { 3, "Both alternatives" },
+ },
+};
+
+static struct atom_map port_dot3_power_class_a_map = {
+ .key = lldpctl_k_dot3_power_class_a,
+ .map = {
+ { 0, "Unknown" },
+ { 1, "Class 1" },
+ { 2, "Class 2" },
+ { 3, "Class 3" },
+ { 4, "Class 4" },
+ { 5, "Class 5" },
+ { 6, "Unknown" },
+ { 7, "Single-signature PD or 2-pair only PSE" },
+ },
+};
+
+static struct atom_map port_dot3_power_class_b_map = {
+ .key = lldpctl_k_dot3_power_class_b,
+ .map = {
+ { 0, "Unknown" },
+ { 1, "Class 1" },
+ { 2, "Class 2" },
+ { 3, "Class 3" },
+ { 4, "Class 4" },
+ { 5, "Class 5" },
+ { 6, "Unknown" },
+ { 7, "Single-signature PD or 2-pair only PSE" },
+ },
+};
+
+static struct atom_map port_dot3_power_class_ext_map = {
+ .key = lldpctl_k_dot3_power_class_ext,
+ .map = {
+ { 0, "Unknown" },
+ { 1, "Class 1" },
+ { 2, "Class 2" },
+ { 3, "Class 3" },
+ { 4, "Class 4" },
+ { 5, "Class 5" },
+ { 6, "Class 6" },
+ { 7, "Class 7" },
+ { 8, "Class 8" },
+ { 9, "Unknown" },
+ { 10, "Unknown" },
+ { 11, "Unknown" },
+ { 12, "Unknown" },
+ { 13, "Unknown" },
+ { 14, "Unknown" },
+ { 15, "Dual-signature PD" },
+ },
+};
+
+static struct atom_map port_dot3_power_type_ext_map = {
+ .key = lldpctl_k_dot3_power_type_ext,
+ .map = {
+ { LLDP_DOT3_POWER_8023BT_OFF, "802.3bt off" },
+ { 1, "Type 3 PSE" },
+ { 2, "Type 4 PSE" },
+ { 3, "Type 3 single-signature PD" },
+ { 4, "Type 3 dual-signature PD" },
+ { 5, "Type 4 single-signature PD" },
+ { 6, "Type 4 dual-signature PD" },
+ { 7, "Unknown" },
+ { 8, "Unknown" },
+ },
+};
+
+static struct atom_map port_dot3_power_pd_load_map = {
+ .key = lldpctl_k_dot3_power_pd_load,
+ .map = {
+ { 0, "PD is single- or dual-signature and power on the modes is not "
+ "electrically isolated." },
+ { 1, "PD is dual-signature and power on the modes is electrically "
+ "isolated" },
+ },
+};
+
+
ATOM_MAP_REGISTER(port_dot3_power_pairs_map, 4);
ATOM_MAP_REGISTER(port_dot3_power_class_map, 5);
ATOM_MAP_REGISTER(port_dot3_power_priority_map, 6);
case lldpctl_k_dot3_power_priority:
return map_lookup(port_dot3_power_priority_map.map,
port->p_power.priority);
+ case lldpctl_k_dot3_power_pd_4pid:
+ return map_lookup(port_dot3_power_pd_4pid_map.map,
+ port->p_power.pd_4pid);
+ case lldpctl_k_dot3_power_pse_status:
+ return map_lookup(port_dot3_power_pse_status_map.map,
+ port->p_power.pse_status);
+ case lldpctl_k_dot3_power_pd_status:
+ return map_lookup(port_dot3_power_pd_status_map.map,
+ port->p_power.pd_status);
+ case lldpctl_k_dot3_power_pse_pairs_ext:
+ return map_lookup(port_dot3_power_pse_pairs_ext_map.map,
+ port->p_power.pse_pairs_ext);
+ case lldpctl_k_dot3_power_class_a:
+ return map_lookup(port_dot3_power_class_a_map.map,
+ port->p_power.class_a);
+ case lldpctl_k_dot3_power_class_b:
+ return map_lookup(port_dot3_power_class_b_map.map,
+ port->p_power.class_b);
+ case lldpctl_k_dot3_power_class_ext:
+ return map_lookup(port_dot3_power_class_ext_map.map,
+ port->p_power.class_ext);
+ case lldpctl_k_dot3_power_type_ext:
+ return map_lookup(port_dot3_power_type_ext_map.map,
+ port->p_power.type_ext);
+ case lldpctl_k_dot3_power_pd_load:
+ return map_lookup(port_dot3_power_pd_load_map.map,
+ port->p_power.pd_load);
default:
SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
return NULL;
return port->p_power.requested * 100;
case lldpctl_k_dot3_power_allocated:
return port->p_power.allocated * 100;
+ /* 802.3bt additions */
+ case lldpctl_k_dot3_power_pd_4pid:
+ return port->p_power.pd_4pid;
+ case lldpctl_k_dot3_power_requested_a:
+ return port->p_power.requested_a * 100;
+ case lldpctl_k_dot3_power_requested_b:
+ return port->p_power.requested_b * 100;
+ case lldpctl_k_dot3_power_allocated_a:
+ return port->p_power.allocated_a * 100;
+ case lldpctl_k_dot3_power_allocated_b:
+ return port->p_power.allocated_b * 100;
+ case lldpctl_k_dot3_power_pse_status:
+ return port->p_power.pse_status;
+ case lldpctl_k_dot3_power_pd_status:
+ return port->p_power.pd_status;
+ case lldpctl_k_dot3_power_pse_pairs_ext:
+ return port->p_power.pse_pairs_ext;
+ case lldpctl_k_dot3_power_class_a:
+ return port->p_power.class_a;
+ case lldpctl_k_dot3_power_class_b:
+ return port->p_power.class_b;
+ case lldpctl_k_dot3_power_class_ext:
+ return port->p_power.class_ext;
+ case lldpctl_k_dot3_power_type_ext:
+ return port->p_power.type_ext;
+ case lldpctl_k_dot3_power_pd_load:
+ return port->p_power.pd_load;
+ case lldpctl_k_dot3_power_pse_max:
+ return port->p_power.pse_max * 100;
default:
return SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
}
if (value < 0) goto bad;
port->p_power.requested = value / 100;
return atom;
+ /* 802.3bt additions */
+ case lldpctl_k_dot3_power_pd_4pid:
+ port->p_power.pd_4pid = value;
+ return atom;
+ case lldpctl_k_dot3_power_requested_a:
+ port->p_power.requested_a = value / 100;
+ return atom;
+ case lldpctl_k_dot3_power_requested_b:
+ port->p_power.requested_b = value / 100;
+ return atom;
+ case lldpctl_k_dot3_power_allocated_a:
+ port->p_power.allocated_a = value / 100;
+ return atom;
+ case lldpctl_k_dot3_power_allocated_b:
+ port->p_power.allocated_b = value / 100;
+ return atom;
+ case lldpctl_k_dot3_power_pse_status:
+ port->p_power.pse_status = value;
+ return atom;
+ case lldpctl_k_dot3_power_pd_status:
+ port->p_power.pd_status = value;
+ return atom;
+ case lldpctl_k_dot3_power_pse_pairs_ext:
+ port->p_power.pse_pairs_ext = value;
+ return atom;
+ case lldpctl_k_dot3_power_class_a:
+ port->p_power.class_a = value;
+ return atom;
+ case lldpctl_k_dot3_power_class_b:
+ port->p_power.class_b = value;
+ return atom;
+ case lldpctl_k_dot3_power_class_ext:
+ port->p_power.class_ext = value;
+ return atom;
+ case lldpctl_k_dot3_power_type_ext:
+ port->p_power.type_ext = value;
+ return atom;
+ case lldpctl_k_dot3_power_pd_load:
+ port->p_power.pd_load = value;
+ return atom;
+ case lldpctl_k_dot3_power_pse_max:
+ port->p_power.pse_max = value / 100;
+ return atom;
default:
SET_ERROR(atom->conn, LLDPCTL_ERR_NOT_EXIST);
return NULL;
lldpctl_k_dot3_power_allocated, /**< `(I,W)` 802.3AT power allocated */
lldpctl_k_dot3_power_requested, /**< `(I,W)` 802.3AT power requested */
+ /* 802.3bt additions */
+ lldpctl_k_dot3_power_pd_4pid, /**< `(IS,W)` 802.3BT both modes supported? */
+ lldpctl_k_dot3_power_requested_a, /**< `(I,W)` 802.3BT power value requested for A */
+ lldpctl_k_dot3_power_requested_b, /**< `(I,W)` 802.3BT power value requested for B */
+ lldpctl_k_dot3_power_allocated_a, /**< `(I,W)` 802.3BT power value allocated for A */
+ lldpctl_k_dot3_power_allocated_b, /**< `(I,W)` 802.3BT power value allocated for B */
+ lldpctl_k_dot3_power_pse_status, /**< `(IS,W)` 802.3BT PSE powering status */
+ lldpctl_k_dot3_power_pd_status, /**< `(IS,W)` 802.3BT PD powering status */
+ lldpctl_k_dot3_power_pse_pairs_ext, /**< `(IS,W)` 802.3BT PSE power pairs */
+ lldpctl_k_dot3_power_class_a, /**< `(IS,W)` 802.3BT power class for A */
+ lldpctl_k_dot3_power_class_b, /**< `(IS,W)` 802.3BT power class for B */
+ lldpctl_k_dot3_power_class_ext, /**< `(IS,W)` 802.3BT power class */
+ lldpctl_k_dot3_power_type_ext, /**< `(IS,W)` 802.3BT power type */
+ lldpctl_k_dot3_power_pd_load, /**< `(IS,W)` 802.3BT dualsig isolated? */
+ lldpctl_k_dot3_power_pse_max, /**< `(I,W)` 802.3BT maximum available power */
+
lldpctl_k_port_vlan_pvid = 1500, /**< `(I)` Primary VLAN ID */
lldpctl_k_port_vlans, /**< `(AL)` List of VLAN */
lldpctl_k_vlan_id, /**< `(I)` VLAN ID */
#define LLDP_DOT3_POWER_8023AT_TYPE1 1
#define LLDP_DOT3_POWER_8023AT_TYPE2 2
+/* 802.3bt additions */
+#define LLDP_DOT3_POWER_8023BT_OFF 0
+#define LLDP_DOT3_POWER_8023BT_TYPE3 1
+#define LLDP_DOT3_POWER_8023BT_TYPE4 2
+
/* Dot3 power source */
#define LLDP_DOT3_POWER_SOURCE_UNKNOWN 0
#define LLDP_DOT3_POWER_SOURCE_PRIMARY 1
u_int8_t priority;
u_int16_t requested;
u_int16_t allocated;
+
+ /* For 802.3BT */
+ u_int8_t pd_4pid;
+ u_int16_t requested_a;
+ u_int16_t requested_b;
+ u_int16_t allocated_a;
+ u_int16_t allocated_b;
+ u_int16_t pse_status;
+ u_int8_t pd_status;
+ u_int8_t pse_pairs_ext;
+ u_int8_t class_a;
+ u_int8_t class_b;
+ u_int8_t class_ext;
+ u_int8_t type_ext;
+ u_int8_t pd_load;
+ u_int16_t pse_max;
};
MARSHAL(lldpd_dot3_power);
#endif