Skip to content

Commit

Permalink
daemon/lldp: restore read support for 802.3BT
Browse files Browse the repository at this point in the history
As it was said to work for most people, let's keep it. Just remove write
support for now.
  • Loading branch information
vincentbernat committed Oct 15, 2023
1 parent 24b30d0 commit 551717c
Show file tree
Hide file tree
Showing 10 changed files with 383 additions and 9 deletions.
2 changes: 1 addition & 1 deletion NEWS
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
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.

Expand Down
74 changes: 74 additions & 0 deletions src/client/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,80 @@ display_port(struct writer *w, lldpctl_atom_t *port, int details)
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);
Expand Down
41 changes: 41 additions & 0 deletions src/daemon/protocols/lldp.c
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,47 @@ lldp_decode(struct lldpd *cfg, char *frame, int s, struct lldpd_hardware *hardwa
} 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 */
Expand Down
2 changes: 1 addition & 1 deletion src/lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ CLEANFILES = atom-glue.c
# -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
Expand Down
178 changes: 178 additions & 0 deletions src/lib/atoms/dot3.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,128 @@ static struct atom_map port_dot3_power_priority_map = {
},
};

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);
Expand Down Expand Up @@ -109,6 +231,33 @@ _lldpctl_atom_get_str_dot3_power(lldpctl_atom_t *atom, lldpctl_key_t key)
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;
Expand Down Expand Up @@ -146,6 +295,35 @@ _lldpctl_atom_get_int_dot3_power(lldpctl_atom_t *atom, lldpctl_key_t key)
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);
}
Expand Down
34 changes: 27 additions & 7 deletions src/lib/lldpctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,26 @@ typedef enum {
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 */
Expand Down Expand Up @@ -865,8 +885,8 @@ typedef enum {
`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. */
Expand Down Expand Up @@ -1135,11 +1155,11 @@ lldpctl_atom_t *lldpctl_atom_iter_value(lldpctl_atom_t *atom,
* 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.
Expand Down
Loading

0 comments on commit 551717c

Please sign in to comment.