]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
daemon/lldp: restore read support for 802.3BT
authorVincent Bernat <vincent@bernat.ch>
Sun, 15 Oct 2023 18:28:46 +0000 (20:28 +0200)
committerVincent Bernat <vincent@bernat.ch>
Sun, 15 Oct 2023 18:28:46 +0000 (20:28 +0200)
As it was said to work for most people, let's keep it. Just remove write
support for now.

NEWS
src/client/display.c
src/daemon/protocols/lldp.c
src/lib/Makefile.am
src/lib/atoms/dot3.c
src/lib/lldpctl.h
src/lldp-const.h
src/lldpd-structs.h
tests/integration/data/8023bt.pcap [new file with mode: 0644]
tests/integration/test_pcap.py

diff --git a/NEWS b/NEWS
index f0e0fb19624311e7804d70d386b83782fa5e4fac..767a4020d3989603e8e2bd2683a7953d0d5824ab 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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.
 
index d6338d0d55cf52648ee0c9ea1c231401c1121e02..a050432d611703477db748eb2b6a8164be61e097 100644 (file)
@@ -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);
index 647c6e970aab64912ae260d89374cc39aca9a2ed..64d344730dfc06861fd82d057ed38edd0622c53f 100644 (file)
@@ -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 */
index 2ed037bb162545ac54546a5c1b6367f953df32c2..6cc6bc4d3f81159b7b42eb36366efbf96243f26a 100644 (file)
@@ -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
index 202ac9b602bb087057af83f95bd2d192287ea027..f3f490ae038af5fd2123c256c94682bb23f66758 100644 (file)
@@ -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);
@@ -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;
@@ -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);
        }
index cea5706f897d8c24cbbe8e6baf9d74eddf275409..6c2844a3985b8a5a3e8e55ec1be36e5381401a72 100644 (file)
@@ -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 */
@@ -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. */
@@ -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.
index c3fc40e4e2abfd790b7ab7747d396bc6284654f1..454424d043fb00775bdfda64aac110ebfb8e1003 100644 (file)
 #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
index 10fcdf65455ad6d80cc60d4a3566de6657c3d3d9..5647c83f2bdb8774e48c80f80f872f79407123ed 100644 (file)
@@ -125,6 +125,22 @@ struct lldpd_dot3_power {
        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
diff --git a/tests/integration/data/8023bt.pcap b/tests/integration/data/8023bt.pcap
new file mode 100644 (file)
index 0000000..932b593
Binary files /dev/null and b/tests/integration/data/8023bt.pcap differ
index 3a61cea48711832a48f6f726e9f77fdb765cd81a..ef8ff01cd7b3f06dbcf3b172e4cc712846de98cd 100644 (file)
@@ -50,6 +50,46 @@ def test_cisco_sg200(request, lldpd1, lldpcli, namespaces):
         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"
 )