lldpd (1.0.18)
* Changes (breaking):
- + Remove support for 802.3bt (broken).
+ + Remove support for building 802.3bt TLVs (broken).
* Fix:
+ Fix memory leaks in EDP/FDP decoding when receiving some TLVs twice.
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);
} 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 */
# -version-number could be computed from -version-info, mostly major
# is `current` - `age`, minor is `age` and revision is `revision' and
# major.minor should be used when updating lldpctl.map.
-liblldpctl_la_LDFLAGS = $(AM_LDFLAGS) -version-info 14:0:10
+liblldpctl_la_LDFLAGS = $(AM_LDFLAGS) -version-info 13:1:9
liblldpctl_la_DEPENDENCIES = libfixedpoint.la
if HAVE_LD_VERSION_SCRIPT
},
};
+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" },
+ { 0, NULL},
+ },
+};
+
+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" },
+ { 0, NULL },
+ },
+};
+
+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" },
+ { 0, NULL },
+ },
+};
+
+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" },
+ { 0, NULL },
+ },
+};
+
+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" },
+ { 0, NULL },
+ },
+};
+
+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" },
+ { 0, NULL },
+ },
+};
+
+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" },
+ { 0, NULL },
+ },
+};
+
+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" },
+ { 0, NULL },
+ },
+};
+
+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 is not "
+ "electrically isolated" },
+ { 1, "PD is dual-signature and power is electrically "
+ "isolated" },
+ { 0, NULL },
+ },
+};
+
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);
}
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)` 802.3BT both modes supported? */
+ lldpctl_k_dot3_power_requested_a, /**< `(I)` 802.3BT power value requested for
+ A */
+ lldpctl_k_dot3_power_requested_b, /**< `(I)` 802.3BT power value requested for
+ B */
+ lldpctl_k_dot3_power_allocated_a, /**< `(I)` 802.3BT power value allocated for
+ A */
+ lldpctl_k_dot3_power_allocated_b, /**< `(I)` 802.3BT power value allocated for
+ B */
+ lldpctl_k_dot3_power_pse_status, /**< `(IS)` 802.3BT PSE powering status */
+ lldpctl_k_dot3_power_pd_status, /**< `(IS)` 802.3BT PD powering status */
+ lldpctl_k_dot3_power_pse_pairs_ext, /**< `(IS)` 802.3BT PSE power pairs */
+ lldpctl_k_dot3_power_class_a, /**< `(IS)` 802.3BT power class for A */
+ lldpctl_k_dot3_power_class_b, /**< `(IS)` 802.3BT power class for B */
+ lldpctl_k_dot3_power_class_ext, /**< `(IS)` 802.3BT power class */
+ lldpctl_k_dot3_power_type_ext, /**< `(IS)` 802.3BT power type */
+ lldpctl_k_dot3_power_pd_load, /**< `(IS)` 802.3BT dualsig isolated? */
+ lldpctl_k_dot3_power_pse_max, /**< `(I)` 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 */
`LLDP_MED_POW_PRIO_*` */
lldpctl_k_med_power_val, /**< `(I,W)` LLDP MED power value */
- lldpctl_k_mgmt_ip = 3000, /**< `(S)` IP address */
- lldpctl_k_mgmt_iface_index, /**< `(I)` Interface index */
+ lldpctl_k_mgmt_ip = 3000, /**< `(S)` IP address */
+ lldpctl_k_mgmt_iface_index = 30001, /**< `(I)` Interface index */
lldpctl_k_tx_cnt = 4000, /**< `(I)` tx cnt. Only works for a local port. */
lldpctl_k_rx_cnt, /**< `(I)` rx cnt. Only works for a local port. */
* reference count of the provided value is decremented. If you need to use it
* outside of the loop, you need to increment it.
*/
-#define lldpctl_atom_foreach(atom, value) \
- for (lldpctl_atom_iter_t *iter##_LINE_ = lldpctl_atom_iter(atom); \
- iter##_LINE_ && (value = lldpctl_atom_iter_value(atom, iter##_LINE_)); \
- iter##_LINE_ = lldpctl_atom_iter_next(atom, iter##_LINE_), \
- lldpctl_atom_dec_ref(value))
+#define lldpctl_atom_foreach(atom, value) \
+ for (lldpctl_atom_iter_t *iter##_LINE_ = lldpctl_atom_iter(atom); \
+ iter##_LINE_ && (value = lldpctl_atom_iter_value(atom, iter##_LINE_)); \
+ iter##_LINE_ = lldpctl_atom_iter_next(atom, iter##_LINE_), \
+ lldpctl_atom_dec_ref(value))
/**
* Create a new value for an iterable element.
#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
assert out == expected
+@pytest.mark.skipif("'Dot3' not in config.lldpd.features", readon="Dot3 not supported")
+def test_8023bt(lldpd1, lldpcli, namespaces):
+ with namespaces(2):
+ pytest.helpers.send_pcap("data/8023bt.pcap", "eth1")
+ with namespaces(1):
+ out = lldpcli("-f", "keyvalue", "show", "neighbors", "details")
+ for k in list(out.keys()):
+ if not k.startswith("lldp.eth0.port.power."):
+ del out[k]
+ assert out == {
+ "lldp.eth0.port.power.supported": "yes",
+ "lldp.eth0.port.power.enabled": "yes",
+ "lldp.eth0.port.power.paircontrol": "yes",
+ "lldp.eth0.port.power.device-type": "PSE",
+ "lldp.eth0.port.power.pairs": "signal",
+ "lldp.eth0.port.power.class": "class 4",
+ "lldp.eth0.port.power.power-type": "2",
+ "lldp.eth0.port.power.source": "PSE",
+ "lldp.eth0.port.power.priority": "low",
+ "lldp.eth0.port.power.requested": "71000",
+ "lldp.eth0.port.power.allocated": "51000",
+ "lldp.eth0.port.power.requested-a": "35500",
+ "lldp.eth0.port.power.requested-b": "35500",
+ "lldp.eth0.port.power.allocated-a": "25500",
+ "lldp.eth0.port.power.allocated-b": "25500",
+ "lldp.eth0.port.power.pse-powering-status": "4-pair powering single-signature PD",
+ "lldp.eth0.port.power.pd-powering-status": "unknown",
+ "lldp.eth0.port.power.power-pairs-ext": "both alternatives",
+ "lldp.eth0.port.power.power-class-ext-a": "class 4",
+ "lldp.eth0.port.power.power-class-ext-b": "class 4",
+ "lldp.eth0.port.power.power-class-ext": "dual-signature PD",
+ "lldp.eth0.port.power.power-type-ext": "type 3 PSE",
+ "lldp.eth0.port.power.pd-load": (
+ "PD is single- or dual-signature and power "
+ "is not electrically isolated"
+ ),
+ "lldp.eth0.port.power.max-power": "51000",
+ }
+
+
@pytest.mark.skipif(
"'LLDP-MED' not in config.lldpd.features", readon="LLDP-MED not supported"
)