Signed-off-by: Changliang Wu <[email protected]>
---
NEWS | 2 +
lib/lldp/lldp-const.h | 5 +
lib/lldp/lldp.c | 164 +++++++++++++++++++-
lib/lldp/lldpd-structs.h | 69 +++++++++
lib/ovs-lldp.c | 316 +++++++++++++++++++++++++++++++++++++++
5 files changed, 554 insertions(+), 2 deletions(-)
diff --git a/NEWS b/NEWS
index 931fe5c71..a1bb57262 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,8 @@ Post-v3.5.0
- ovs-appctl:
* Added JSON output support to the 'ovs/route/show' command.
* Added 'lldp/neighbor' command that displays lldp neighbor infomation.
+ - lldp:
+ * Added support for dot1 and dot3 TLVs.
- SSL/TLS:
* Support for deprecated TLSv1 and TLSv1.1 protocols on OpenFlow and
database connections is now removed.
diff --git a/lib/lldp/lldp-const.h b/lib/lldp/lldp-const.h
index 8c5c0733e..e03c77f71 100644
--- a/lib/lldp/lldp-const.h
+++ b/lib/lldp/lldp-const.h
@@ -98,6 +98,11 @@
#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
diff --git a/lib/lldp/lldp.c b/lib/lldp/lldp.c
index 6fdcfef56..c10bb27d9 100644
--- a/lib/lldp/lldp.c
+++ b/lib/lldp/lldp.c
@@ -18,6 +18,8 @@
*/
#include <config.h>
+#include "lldp-const.h"
+#include "lldp-tlv.h"
#include "lldpd.h"
#include <errno.h>
#include <time.h>
@@ -372,6 +374,12 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int
s,
void *b;
struct lldpd_aa_isid_vlan_maps_tlv *isid_vlan_map = NULL;
u_int8_t msg_auth_digest[LLDP_TLV_AA_ISID_VLAN_DIGEST_LENGTH];
+
+ struct lldpd_vlan *vlan = NULL;
+ int vlan_len;
+ struct lldpd_ppvid *ppvid;
+ struct lldpd_pi *pi = NULL;
+
struct lldpd_mgmt *mgmt;
u_int8_t addr_str_length, addr_str_buffer[32];
u_int8_t addr_family, addr_length, *addr_ptr, iface_subtype;
@@ -384,6 +392,9 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int
s,
port = xzalloc(sizeof *port);
ovs_list_init(&port->p_isid_vlan_maps);
+ ovs_list_init(&port->p_vlans);
+ ovs_list_init(&port->p_ppvids);
+ ovs_list_init(&port->p_pids);
length = s;
pos = (u_int8_t*) frame;
@@ -568,9 +579,158 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame,
int s,
PEEK_BYTES(orgid, sizeof orgid);
tlv_subtype = PEEK_UINT8;
if (memcmp(dot1, orgid, sizeof orgid) == 0) {
- hardware->h_rx_unrecognized_cnt++;
+ switch (tlv_subtype) {
+ case LLDP_TLV_DOT1_VLANNAME:
+ CHECK_TLV_SIZE(7, "VLAN");
+ vlan = xzalloc(sizeof *vlan);
+ vlan->v_vid = PEEK_UINT16;
+ vlan_len = PEEK_UINT8;
+ CHECK_TLV_SIZE(7 + vlan_len, "VLAN");
+ vlan->v_name = xzalloc(vlan_len + 1);
+ PEEK_BYTES(vlan->v_name, vlan_len);
+ ovs_list_push_back(&port->p_vlans, &vlan->v_entries);
+ vlan = NULL;
+ break;
+
+ case LLDP_TLV_DOT1_PVID:
+ CHECK_TLV_SIZE(6, "PVID");
+ port->p_pvid = PEEK_UINT16;
+ break;
+
+ case LLDP_TLV_DOT1_PPVID:
+ CHECK_TLV_SIZE(7, "PPVID");
+ /* validation needed */
+ /* PPVID has to be unique if more than
+ one PPVID TLVs are received -
+ discard if duplicate */
+ /* if support bit is not set and
+ enabled bit is set - PPVID TLV is
+ considered error and discarded */
+ /* if PPVID > 4096 - bad and discard */
+ ppvid = xzalloc(sizeof *ppvid);
+ ppvid->p_cap_status = PEEK_UINT8;
+ ppvid->p_ppvid = PEEK_UINT16;
+ ovs_list_push_back(&port->p_ppvids, &ppvid->p_entries);
+ break;
+
+ case LLDP_TLV_DOT1_PI:
+ /* validation needed */
+ /* PI has to be unique if more than
+ one PI TLVs are received - discard
+ if duplicate ?? */
+ pi = xzalloc(sizeof *pi);
+ pi->p_pi_len = PEEK_UINT8;
+ CHECK_TLV_SIZE(5 + pi->p_pi_len, "PI");
+ pi->p_pi = xzalloc(pi->p_pi_len);
+ PEEK_BYTES(pi->p_pi, pi->p_pi_len);
+ ovs_list_push_back(&port->p_pids, &pi->p_entries);
+ pi = NULL;
+ break;
+
+ default:
+ VLOG_INFO("unknown org tlv [%02x:%02x:%02x] received "
+ "on %s",
+ orgid[0], orgid[1], orgid[2],
+ hardware->h_ifname);
+ hardware->h_rx_unrecognized_cnt++;
+ }
} else if (memcmp(dot3, orgid, sizeof orgid) == 0) {
- hardware->h_rx_unrecognized_cnt++;
+ switch (tlv_subtype) {
+ case LLDP_TLV_DOT3_MAC:
+ CHECK_TLV_SIZE(9, "MAC/PHY");
+ port->p_macphy.autoneg_support = PEEK_UINT8;
+ port->p_macphy.autoneg_enabled =
+ (port->p_macphy.autoneg_support & 0x2) >> 1;
+ port->p_macphy.autoneg_support =
+ port->p_macphy.autoneg_support & 0x1;
+ port->p_macphy.autoneg_advertised = PEEK_UINT16;
+ port->p_macphy.mau_type = PEEK_UINT16;
+ break;
+
+ case LLDP_TLV_DOT3_LA:
+ CHECK_TLV_SIZE(9, "Link aggregation");
+ PEEK_DISCARD_UINT8;
+ port->p_aggregid = PEEK_UINT32;
+ break;
+
+ case LLDP_TLV_DOT3_MFS:
+ 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) >> 1;
+ port->p_power.enabled = (port->p_power.devicetype & 0x4) >>
+ 2;
+ port->p_power.paircontrol =
+ (port->p_power.devicetype & 0x8) >> 3;
+ 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;
+ /* 802.3at? */
+ if (tlv_size >= 12) {
+ port->p_power.powertype = PEEK_UINT8;
+ port->p_power.source =
+ (port->p_power.powertype & (1 << 5 | 1 << 4)) >> 4;
+ port->p_power.priority =
+ (port->p_power.powertype & (1 << 1 | 1 << 0));
+ port->p_power.powertype =
+ (port->p_power.powertype & (1 << 7))
+ ? LLDP_DOT3_POWER_8023AT_TYPE1
+ : LLDP_DOT3_POWER_8023AT_TYPE2;
+ port->p_power.requested = PEEK_UINT16;
+ port->p_power.allocated = PEEK_UINT16;
+ } 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:
+ VLOG_INFO("unknown org tlv [%02x:%02x:%02x] received "
+ "on %s",
+ orgid[0], orgid[1], orgid[2],
+ hardware->h_ifname);
+ hardware->h_rx_unrecognized_cnt++;
+ }
} else if (memcmp(med, orgid, sizeof orgid) == 0) {
/* LLDP-MED */
hardware->h_rx_unrecognized_cnt++;
diff --git a/lib/lldp/lldpd-structs.h b/lib/lldp/lldpd-structs.h
index fe5d5f9f8..1ec7fe777 100644
--- a/lib/lldp/lldpd-structs.h
+++ b/lib/lldp/lldpd-structs.h
@@ -45,6 +45,63 @@ lldpd_af(int af)
}
}
+struct lldpd_ppvid {
+ struct ovs_list p_entries;
+ u_int8_t p_cap_status;
+ u_int16_t p_ppvid;
+};
+
+struct lldpd_vlan {
+ struct ovs_list v_entries;
+ char *v_name;
+ u_int16_t v_vid;
+};
+
+struct lldpd_pi {
+ struct ovs_list p_entries;
+ char *p_pi;
+ int p_pi_len;
+};
+
+struct lldpd_dot3_macphy {
+ u_int8_t autoneg_support;
+ u_int8_t autoneg_enabled;
+ u_int16_t autoneg_advertised;
+ u_int16_t mau_type;
+};
+
+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;
+ u_int8_t powertype; /* If set to LLDP_DOT3_POWER_8023AT_OFF,
+ following fields have no meaning */
+ u_int8_t source;
+ 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;
+};
+
+
#define LLDPD_MGMT_MAXADDRSIZE 16 /* sizeof(struct in6_addr) */
struct lldpd_mgmt {
struct ovs_list m_entries;
@@ -98,6 +155,18 @@ struct lldpd_port {
char *p_descr;
u_int16_t p_mfs;
struct lldpd_aa_element_tlv p_element;
+
+ /* Dot3 stuff */
+ u_int32_t p_aggregid;
+ struct lldpd_dot3_macphy p_macphy;
+ struct lldpd_dot3_power p_power;
+
+ /* Dot1 stuff */
+ u_int16_t p_pvid;
+ struct ovs_list p_vlans; /* Contains "struct lldpd_vlan"s. */
+ struct ovs_list p_ppvids; /* Contains "struct lldpd_ppvid"s. */
+ struct ovs_list p_pids; /* Contains "struct lldpd_pi"s. */
+
struct ovs_list p_isid_vlan_maps; /* Contains "struct
lldpd_aa_isid_vlan_maps_tlv"s. */
};
diff --git a/lib/ovs-lldp.c b/lib/ovs-lldp.c
index 330cb16ba..4c2e7c3eb 100644
--- a/lib/ovs-lldp.c
+++ b/lib/ovs-lldp.c
@@ -313,6 +313,316 @@ aa_print_isid_status(struct ds *ds, struct lldp *lldp)
OVS_REQUIRES(mutex)
}
}
+static void
+lldp_print_neighbor_port_dot1(struct ds *ds, struct lldpd_port *port)
+{
+ struct lldpd_vlan *vlan;
+ struct lldpd_ppvid *ppvid;
+ struct lldpd_pi *pid;
+
+ LIST_FOR_EACH (vlan, v_entries, &port->p_vlans) {
+ ds_put_format(ds, " %-20s%d, %s", "VLAN:", vlan->v_vid,
+ port->p_pvid == vlan->v_vid ? "pvid: yes" : "pvid: no");
+ if (vlan->v_name) {
+ ds_put_format(ds, ", %s", vlan->v_name);
+ }
+ ds_put_format(ds, "\n");
+ }
+
+ LIST_FOR_EACH (ppvid, p_entries, &port->p_ppvids) {
+ ds_put_format(ds, " %-20s", "PPVID:");
+ if (ppvid->p_ppvid) {
+ ds_put_format(ds, ", %d ", ppvid->p_ppvid);
+ }
+ ds_put_format(
+ ds, "supported: %s,enabled %s\n",
+ (ppvid->p_cap_status & LLDP_PPVID_CAP_SUPPORTED) ? "yes" : "no",
+ (ppvid->p_cap_status & LLDP_PPVID_CAP_ENABLED) ? "yes" : "no");
+ }
+
+ LIST_FOR_EACH (pid, p_entries, &port->p_pids) {
+ if (pid->p_pi && pid->p_pi_len > 0) {
+ ds_put_format(ds, " %-20s", "PI:");
+ ds_put_buffer(ds, pid->p_pi, pid->p_pi_len);
+ ds_put_format(ds, "\n");
+ }
+ }
+}
+
+static void
+lldp_print_neighbor_port_dot1_json(struct json *interface_item_json,
+ struct lldpd_port *port)
+{
+ struct json *vlan_json_array = NULL;
+ struct json *vlan_json = NULL;
+ struct json *ppvid_json_array = NULL;
+ struct json *ppvid_json = NULL;
+ struct json *pi_json_array = NULL;
+ struct json *pi_json = NULL;
+
+ struct lldpd_vlan *vlan;
+ struct lldpd_ppvid *ppvid;
+ struct lldpd_pi *pid;
+
+ LIST_FOR_EACH (vlan, v_entries, &port->p_vlans) {
+ vlan_json = json_object_create();
+ json_object_put(vlan_json, "vlan-id",
+ json_integer_create(vlan->v_vid));
+ json_object_put(vlan_json, "pvid",
+ json_boolean_create(port->p_pvid == vlan->v_vid));
+ if (vlan->v_name) {
+ json_object_put(vlan_json, "value",
+ json_string_create(vlan->v_name));
+ }
+ if (ovs_list_size(&port->p_vlans) > 1) {
+ if (vlan_json_array == NULL) {
+ vlan_json_array = json_array_create_empty();
+ }
+ json_array_add(vlan_json_array, vlan_json);
+ }
+ }
+ if (vlan_json_array || vlan_json) {
+ json_object_put(interface_item_json, "vlan",
+ vlan_json_array ? vlan_json_array : vlan_json);
+ }
+
+ LIST_FOR_EACH (ppvid, p_entries, &port->p_ppvids) {
+ ppvid_json = json_object_create();
+ if (ppvid->p_ppvid) {
+ json_object_put(ppvid_json, "ppvid",
+ json_integer_create(ppvid->p_ppvid));
+ }
+ json_object_put(ppvid_json, "supported",
+ json_boolean_create(ppvid->p_cap_status &
+ LLDP_PPVID_CAP_SUPPORTED));
+ json_object_put(ppvid_json, "enabled",
+ json_boolean_create(ppvid->p_cap_status &
+ LLDP_PPVID_CAP_ENABLED));
+ if (ovs_list_size(&port->p_ppvids) > 1) {
+ if (ppvid_json_array == NULL) {
+ ppvid_json_array = json_array_create_empty();
+ }
+ json_array_add(ppvid_json_array, ppvid_json);
+ }
+ }
+ if (ppvid_json_array || ppvid_json) {
+ json_object_put(interface_item_json, "ppvid",
+ ppvid_json_array ? ppvid_json_array : ppvid_json);
+ }
+
+ LIST_FOR_EACH (pid, p_entries, &port->p_pids) {
+ if (pid->p_pi && pid->p_pi_len > 0) {
+ pi_json = json_object_create();
+ struct ds pi_ds = DS_EMPTY_INITIALIZER;
+ ds_put_buffer(&pi_ds, pid->p_pi, pid->p_pi_len);
+ json_object_put(ppvid_json, "ppvid",
+ json_string_create(ds_cstr_ro(&pi_ds)));
+ ds_destroy(&pi_ds);
+ if (ovs_list_size(&port->p_pids) > 1) {
+ if (pi_json_array == NULL) {
+ pi_json_array = json_array_create_empty();
+ }
+ json_array_add(pi_json_array, pi_json);
+ }
+ }
+ }
+ if (pi_json_array || pi_json) {
+ json_object_put(interface_item_json, "pi",
+ pi_json_array ? pi_json_array : pi_json);
+ }
+}
+
+static void
+lldp_dot3_autoneg_advertised(struct ds *ds, uint16_t pmd_auto_nego, int bithd,
+ int bitfd, const char *type)
+{
+ if (!((pmd_auto_nego & bithd) || (pmd_auto_nego & bitfd))) {
+ return;
+ }
+
+ ds_put_format(ds, " %-18s%s", "Adv:", type);
+ if (bithd != bitfd) {
+ ds_put_format(ds, ", HD: %s, FD: %s\n",
+ (pmd_auto_nego & bithd) ? "yes" : "no",
+ (pmd_auto_nego & bitfd) ? "yes" : "no");
+ }
+}
+
+static void
+lldp_dot3_autoneg_advertised_json(struct json **advertised_json,
+ uint16_t pmd_auto_nego, int bithd, int bitfd,
+ const char *type)
+{
+ if (!((pmd_auto_nego & bithd) || (pmd_auto_nego & bitfd))) {
+ return;
+ }
+
+ if (!*advertised_json) {
+ *advertised_json = json_array_create_empty();
+ }
+
+ struct json *advertised_item_json = json_object_create();
+ json_object_put(advertised_item_json, "type", json_string_create(type));
+ if (bithd != bitfd) {
+ json_object_put(advertised_item_json, "hd",
+ json_boolean_create((pmd_auto_nego & bithd) ? true
+ : false));
+ json_object_put(advertised_item_json, "fd",
+ json_boolean_create((pmd_auto_nego & bitfd) ? true
+ : false));
+ }
+ json_array_add(*advertised_json, advertised_item_json);
+}
+
+static void
+lldp_print_neighbor_port_dot3(struct ds *ds, struct lldpd_port *port)
+{
+ if (port->p_mfs) {
+ ds_put_format(ds, " %-20s%d\n", "MFS:", port->p_mfs);
+ }
+
+ long int autoneg_support, autoneg_enabled, autoneg_advertised, mautype;
+ autoneg_support = port->p_macphy.autoneg_support;
+ autoneg_enabled = port->p_macphy.autoneg_enabled;
+ autoneg_advertised = port->p_macphy.autoneg_advertised;
+ mautype = port->p_macphy.mau_type;
+ if (autoneg_support > 0 || autoneg_enabled > 0 || mautype > 0) {
+ ds_put_format(ds, " PMD autoneg: supported: %s, enabled: %s\n",
+ autoneg_support ? "yes" : "no",
+ autoneg_enabled ? "yes" : "no");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_10BASE_T,
+ LLDP_DOT3_LINK_AUTONEG_10BASET_FD,
+ "10Base-T");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
+ "100Base-T4");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_TX,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD,
+ "100Base-TX");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_T2,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_T2FD,
+ "100Base-T2");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_1000BASE_X,
+ LLDP_DOT3_LINK_AUTONEG_1000BASE_XFD,
+ "1000Base-X");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_1000BASE_T,
+ LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD,
+ "1000Base-T");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE,
+ LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE,
+ "FDX_PAUSE");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE,
+ LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE,
+ "FDX_APAUSE");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE,
+ LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE,
+ "FDX_SPAUSE");
+ lldp_dot3_autoneg_advertised(ds, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE,
+ LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE,
+ "FDX_BPAUSE");
+ ds_put_format(ds, " %-18s%ld\n", "MAU oper type:", mautype);
+ }
+
+ if (port->p_power.devicetype) {
+ ds_put_format(ds,
+ " MDI Power: supported: %s, enabled: %s, pair "
+ "control: %s\n",
+ port->p_power.supported ? "yes" : "no",
+ port->p_power.enabled ? "yes" : "no",
+ port->p_power.paircontrol ? "yes" : "no");
+ }
+}
+
+static void
+lldp_print_neighbor_port_dot3_json(struct json *port_json,
+ struct lldpd_port *port)
+{
+ if (port->p_mfs) {
+ json_object_put(port_json, "mfs", json_integer_create(port->p_mfs));
+ }
+
+ long int autoneg_support, autoneg_enabled, autoneg_advertised, mautype;
+ autoneg_support = port->p_macphy.autoneg_support;
+ autoneg_enabled = port->p_macphy.autoneg_enabled;
+ autoneg_advertised = port->p_macphy.autoneg_advertised;
+ mautype = port->p_macphy.mau_type;
+ if (autoneg_support > 0 || autoneg_enabled > 0 || mautype > 0) {
+ struct json *auto_nego_json = json_object_create();
+ json_object_put(auto_nego_json, "supported",
+ json_boolean_create(autoneg_support));
+ json_object_put(auto_nego_json, "enabled",
+ json_boolean_create(autoneg_enabled));
+
+ struct json *advertised_json = NULL;
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_10BASE_T,
+ LLDP_DOT3_LINK_AUTONEG_10BASET_FD,
+ "10Base-T");
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
+ "100Base-T4");
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_TX,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD,
+ "100Base-TX");
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_T2,
+ LLDP_DOT3_LINK_AUTONEG_100BASE_T2FD,
+ "100Base-T2");
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_1000BASE_X,
+ LLDP_DOT3_LINK_AUTONEG_1000BASE_XFD,
+ "1000Base-X");
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_1000BASE_T,
+ LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD,
+ "1000Base-T");
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE,
+ LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE,
+ "FDX_PAUSE");
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE,
+ LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE,
+ "FDX_APAUSE");
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE,
+ LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE,
+ "FDX_SPAUSE");
+ lldp_dot3_autoneg_advertised_json(&advertised_json, autoneg_advertised,
+ LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE,
+ LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE,
+ "FDX_BPAUSE");
+ json_object_put(auto_nego_json, "current",
+ json_integer_create(mautype));
+
+ json_object_put(port_json, "auto-negotiation", auto_nego_json);
+ }
+
+ if (port->p_power.devicetype) {
+ struct json *power_json = json_object_create();
+
+ json_object_put(power_json, "supported",
+ json_boolean_create(port->p_power.supported));
+ json_object_put(power_json, "enabled",
+ json_boolean_create(port->p_power.enabled));
+ json_object_put(power_json, "paircontrol",
+ json_boolean_create(port->p_power.paircontrol));
+ json_object_put(port_json, "power", power_json);
+ }
+}
+
static void
lldp_print_neighbor(struct ds *ds, struct lldp *lldp) OVS_REQUIRES(mutex)
{
@@ -422,6 +732,9 @@ lldp_print_neighbor(struct ds *ds, struct lldp *lldp)
OVS_REQUIRES(mutex)
ds_put_format(ds, " %-20s%s\n", "PortDescr:",
strlen(port->p_descr) ? port->p_descr : none_str);
ds_put_format(ds, " %-20s%d\n", "TTL:", port->p_chassis->c_ttl);
+
+ lldp_print_neighbor_port_dot3(ds, port);
+ lldp_print_neighbor_port_dot1(ds, port);
}
}
}
@@ -595,6 +908,9 @@ lldp_print_neighbor_json(struct json *interface_json,
struct lldp *lldp)
json_object_put(port_json, "ttl",
json_integer_create(port->p_chassis->c_ttl));
+ lldp_print_neighbor_port_dot1_json(interface_item_json, port);
+ lldp_print_neighbor_port_dot3_json(port_json, port);
+
json_object_put(interface_item_json, "chassis", chassis_json);
json_object_put(interface_item_json, "port", port_json);
--
2.43.5
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev