Changliang Wu <changliang...@smartx.com> writes:

> Signed-off-by: Changliang Wu <changliang...@smartx.com>
> ---
>  NEWS                     |   1 +
>  lib/lldp/lldp-const.h    |  41 +++---
>  lib/lldp/lldp.c          |  76 +++++++++-
>  lib/lldp/lldpd-structs.h |  24 ++++
>  lib/ovs-lldp.c           | 303 +++++++++++++++++++++++++++++++++++++++
>  5 files changed, 427 insertions(+), 18 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index c66b41e64..72e0f495e 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -16,6 +16,7 @@ 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.
> +       Support for lldp dot1 and dot3 tlv.

This should be its own section
    - 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..7b9c74149 100644
> --- a/lib/lldp/lldp-const.h
> +++ b/lib/lldp/lldp-const.h
> @@ -85,6 +85,11 @@
>  #define LLDP_DOT3_MAU_10GIGBASELW  39
>  #define LLDP_DOT3_MAU_10GIGBASESW  40
>  
> +#define LLDP_DOT3_POWER_PORT_CLASS    (1 << 0)
> +#define LLDP_DOT3_POWER_SUPPORT       (1 << 1)
> +#define LLDP_DOT3_POWER_ENABLED       (1 << 2)
> +#define LLDP_DOT3_POWER_PAIRCONTROL   (1 << 3)
> +
>  /* Dot3 Power Devicetype */
>  #define LLDP_DOT3_POWER_PSE 1
>  #define LLDP_DOT3_POWER_PD  2
> @@ -112,23 +117,27 @@
>  #define LLDP_DOT3_POWER_PRIO_HIGH     2
>  #define LLDP_DOT3_POWER_PRIO_LOW      3
>  
> +/* Auto-Negotiation Support/Status field, from RFC 4836 */
> +#define LLDP_DOT3_LINK_AUTONEG_SUPPORT  (1 << 0)
> +#define LLDP_DOT3_LINK_AUTONEG_ENABLED  (1 << 1)
> +
>  /* PMD Auto-Negotiation Advertised Capability field, from RFC 3636 */
> -#define LLDP_DOT3_LINK_AUTONEG_OTHER        0x8000
> -#define LLDP_DOT3_LINK_AUTONEG_10BASE_T     0x4000
> -#define LLDP_DOT3_LINK_AUTONEG_10BASET_FD   0x2000
> -#define LLDP_DOT3_LINK_AUTONEG_100BASE_T4   0x1000
> -#define LLDP_DOT3_LINK_AUTONEG_100BASE_TX   0x0800
> -#define LLDP_DOT3_LINK_AUTONEG_100BASE_TXFD 0x0400
> -#define LLDP_DOT3_LINK_AUTONEG_100BASE_T2   0x0200
> -#define LLDP_DOT3_LINK_AUTONEG_100BASE_T2FD 0x0100
> -#define LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE    0x0080
> -#define LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE   0x0040
> -#define LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE   0x0020
> -#define LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE   0x0010
> -#define LLDP_DOT3_LINK_AUTONEG_1000BASE_X   0x0008
> -#define LLDP_DOT3_LINK_AUTONEG_1000BASE_XFD 0x0004
> -#define LLDP_DOT3_LINK_AUTONEG_1000BASE_T   0x0002
> -#define LLDP_DOT3_LINK_AUTONEG_1000BASE_TFD 0x0001
> +#define LLDP_DOT3_LINK_AUTONEG_OTHER          0x8000
> +#define LLDP_DOT3_LINK_AUTONEG_10BASE_T       0x4000
> +#define LLDP_DOT3_LINK_AUTONEG_10BASE_T_FD    0x2000
> +#define LLDP_DOT3_LINK_AUTONEG_100BASE_T4     0x1000
> +#define LLDP_DOT3_LINK_AUTONEG_100BASE_TX     0x0800
> +#define LLDP_DOT3_LINK_AUTONEG_100BASE_TX_FD  0x0400
> +#define LLDP_DOT3_LINK_AUTONEG_100BASE_T2     0x0200
> +#define LLDP_DOT3_LINK_AUTONEG_100BASE_T2_FD  0x0100
> +#define LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE      0x0080
> +#define LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE     0x0040
> +#define LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE     0x0020
> +#define LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE     0x0010
> +#define LLDP_DOT3_LINK_AUTONEG_1000BASE_X     0x0008
> +#define LLDP_DOT3_LINK_AUTONEG_1000BASE_X_FD  0x0004
> +#define LLDP_DOT3_LINK_AUTONEG_1000BASE_T     0x0002
> +#define LLDP_DOT3_LINK_AUTONEG_1000BASE_T_FD  0x0001

Why did you rename these constants?  Please keep them as in lldpd.

>  /* Capabilities */
>  #define LLDP_CAP_OTHER     0x01
> diff --git a/lib/lldp/lldp.c b/lib/lldp/lldp.c
> index 6fdcfef56..136247100 100644
> --- a/lib/lldp/lldp.c
> +++ b/lib/lldp/lldp.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <config.h>
> +#include "lldp-tlv.h"
>  #include "lldpd.h"
>  #include <errno.h>
>  #include <time.h>
> @@ -567,10 +568,81 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, 
> int s,
>              CHECK_TLV_SIZE(1 + sizeof orgid, "Organisational");
>              PEEK_BYTES(orgid, sizeof orgid);
>              tlv_subtype = PEEK_UINT8;
> +            uint8_t tlv_org_size;
>              if (memcmp(dot1, orgid, sizeof orgid) == 0) {
> -                hardware->h_rx_unrecognized_cnt++;
> +                switch (tlv_subtype) {
> +                case LLDP_TLV_DOT1_PVID:
> +                    CHECK_TLV_SIZE(2, "Dot1 Port VLAN ID");
> +                    port->p_dot1.pvid = PEEK_UINT16;
> +                    port->p_dot1_enable |= (1 << LLDP_TLV_DOT1_PVID);
> +                    break;
> +                case LLDP_TLV_DOT1_PPVID:
> +                    CHECK_TLV_SIZE(2, "Dot1 Port And Protocol VLAN ID");
> +                    port->p_dot1.ppvid = PEEK_UINT16;
> +                    port->p_dot1_enable |= (1 << LLDP_TLV_DOT1_PPVID);
> +                    break;
> +                case LLDP_TLV_DOT1_VLANNAME:
> +                case LLDP_TLV_DOT1_PI:
> +                    if (tlv_subtype == LLDP_TLV_DOT1_VLANNAME) {
> +                        CHECK_TLV_SIZE(2, "DOT1 VLAN ID");
> +                        port->p_dot1.vlan_id = PEEK_UINT16;
> +                        port->p_dot1_enable |= (1 << LLDP_TLV_DOT1_VLANNAME);
> +                    }
> +                    CHECK_TLV_SIZE(1, "DOT1 VLAN Name/PI Length");
> +                    tlv_org_size = PEEK_UINT8;
> +                    if (tlv_org_size < 1) {
> +                        VLOG_DBG("empty dot1 vlan name/pi tlv received on 
> %s",
> +                                 hardware->h_ifname);
> +                        goto malformed;
> +                    }
> +                    CHECK_TLV_SIZE(tlv_org_size, "DOT1 VLAN Name/PI");
> +                    b = xzalloc(tlv_org_size + 1);
> +                    PEEK_BYTES(b, tlv_org_size);
> +                    if (tlv_subtype == LLDP_TLV_DOT1_VLANNAME) {
> +                        free(port->p_dot1.vlan_name);
> +                        port->p_dot1.vlan_name = b;
> +                    } else if (tlv_subtype == LLDP_TLV_DOT1_PI) {
> +                        free(port->p_dot1.pi);
> +                        port->p_dot1.pi = b;
> +                        port->p_dot1_enable |= (1 << LLDP_TLV_DOT1_PI);
> +                    }

This code introduces two subtle memory leaks.  The first is when
tlv_subtype is not recognized, and the second is if multiple instances
of the DOT1 TLVs are included.  Both need to be addressed.

Further, this code does not mirror lldpd at all.  Why change from the
lldpd implementation?

I raised the issue back when you first mentioned adding support for dot1
and dot3 TLVs and I asked whether it would be better to try and work
with lldpd folks to export their protocol handling as a library we could
use.  That would mean we wouldn't be introducing these kinds of issues
from the lldpd side, and we could retain an upgrade path that would be
independent of the OVS tree.  That might be the better approach here.

> +                    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(5, "DOT3 MAC");
> +                    port->p_dot3.auto_nego = PEEK_UINT8;
> +                    port->p_dot3.pmd_auto_nego = PEEK_UINT16;
> +                    port->p_dot3.mau = PEEK_UINT16;
> +                    port->p_dot3_enable |= (1 << LLDP_TLV_DOT3_MAC);
> +                    break;
> +                case LLDP_TLV_DOT3_POWER:
> +                    CHECK_TLV_SIZE(3, "DOT3 MDI");
> +                    port->p_dot3.mdi = PEEK_UINT8;
> +                    port->p_dot3.pse = PEEK_UINT8;
> +                    port->p_dot3.power_class = PEEK_UINT8;
> +                    port->p_dot3_enable |= (1 << LLDP_TLV_DOT3_POWER);
> +                    break;
> +                case LLDP_TLV_DOT3_LA: break;
> +                case LLDP_TLV_DOT3_MFS:
> +                    CHECK_TLV_SIZE(3, "DOT3 MFS");
> +                    port->p_dot3.mfs = PEEK_UINT16;
> +                    port->p_dot3_enable |= (1 << LLDP_TLV_DOT3_MFS);
> +                    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..bb8939db1 100644
> --- a/lib/lldp/lldpd-structs.h
> +++ b/lib/lldp/lldpd-structs.h
> @@ -79,6 +79,24 @@ struct lldpd_chassis {
>  /* WARNING: any change to this structure should also be reflected into
>     `lldpd_copy_chassis()` which is not using marshaling. */
>  
> +struct lldpd_tlv_dot1 {
> +    u_int16_t       pvid;       /* Port VLAN identifier */
> +    u_int16_t       ppvid;      /* Port and protocol VLAN identifier */
> +    char            *vlan_name; /* VLAN Name in LLDP_TLV_DOT1_VLANNAME */
> +    u_int16_t       vlan_id;    /* VLAN ID in LLDP_TLV_DOT1_VLANNAME */
> +    char            *pi;        /* protocol identity */
> +};
> +
> +struct lldpd_tlv_dot3 {
> +    u_int8_t  auto_nego;     /* auto-negotiation support/status  */
> +    u_int16_t pmd_auto_nego; /* PMD auto-negotiation advertised capability */
> +    u_int16_t mau;           /* Operational MAU type */
> +    u_int8_t  mdi;           /* MDI power support */
> +    u_int8_t  pse;           /* PSE power pair */
> +    u_int8_t  power_class;   /* Port class */
> +    u_int16_t mfs;           /* Maximum 802.3 frame size */
> +};
> +
>  struct lldpd_port {
>      struct ovs_list      p_entries;
>      struct lldpd_chassis *p_chassis; /* Attached chassis */
> @@ -98,6 +116,12 @@ struct lldpd_port {
>      char                 *p_descr;
>      u_int16_t            p_mfs;
>      struct lldpd_aa_element_tlv        p_element;
> +    /* Bitmask for dot1 tlv received */
> +    u_int16_t                          p_dot1_enable;
> +    struct lldpd_tlv_dot1              p_dot1;
> +    /* Bitmask for dot3 tlv received */
> +    u_int16_t                          p_dot3_enable;
> +    struct lldpd_tlv_dot3              p_dot3;
>      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 da8faf873..b1febb355 100644
> --- a/lib/ovs-lldp.c
> +++ b/lib/ovs-lldp.c
> @@ -313,6 +313,303 @@ 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)
> +{
> +    if (port->p_dot1_enable &
> +        ((1 << LLDP_TLV_DOT1_PVID) | (1 << LLDP_TLV_DOT1_VLANNAME))) {
> +        ds_put_format(ds, "  VLAN: \t");
> +    }
> +    if (port->p_dot1_enable & (1 << LLDP_TLV_DOT1_PVID)) {
> +        ds_put_format(ds, "  %d, ", port->p_dot1.pvid);
> +        if (!(port->p_dot1_enable & (1 << LLDP_TLV_DOT1_VLANNAME)) &&
> +            port->p_dot1.pvid > 0) {
> +            ds_put_format(ds, "pvid: yes");
> +        }
> +    }
> +    if (port->p_dot1_enable & (1 << LLDP_TLV_DOT1_VLANNAME)) {
> +        ds_put_format(ds, "pvid: %s",
> +                      port->p_dot1.pvid == port->p_dot1.vlan_id ? "yes"
> +                                                                : "no");
> +        if (port->p_dot1.vlan_name) {
> +            ds_put_format(ds, ", %s", port->p_dot1.vlan_name);
> +        }
> +    }
> +    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 = NULL;
> +    if (port->p_dot1_enable & (1 << LLDP_TLV_DOT1_PVID)) {
> +        if (!vlan_json) {
> +            vlan_json = json_object_create();
> +        }
> +        json_object_put(vlan_json, "vlan-id",
> +                        json_integer_create(port->p_dot1.pvid));
> +
> +        if (!(port->p_dot1_enable & (1 << LLDP_TLV_DOT1_VLANNAME)) &&
> +            port->p_dot1.pvid > 0) {
> +            json_object_put(vlan_json, "pvid", json_boolean_create(true));
> +        }
> +    }
> +    if (port->p_dot1_enable & (1 << LLDP_TLV_DOT1_VLANNAME)) {
> +        if (!vlan_json) {
> +            vlan_json = json_object_create();
> +        }
> +        json_object_put(
> +            vlan_json, "pvid",
> +            json_boolean_create(
> +                port->p_dot1.pvid == port->p_dot1.vlan_id ? true : false));
> +        if (port->p_dot1.vlan_name) {
> +            json_object_put(vlan_json, "value",
> +                            json_string_create(port->p_dot1.vlan_name));
> +        }
> +    }
> +    if (vlan_json) {
> +        json_object_put(interface_item_json, "vlan", vlan_json);
> +    }
> +
> +    if (port->p_dot1_enable & (1 << LLDP_TLV_DOT1_PPVID)) {
> +        struct json *ppid_json = json_object_create();
> +        json_object_put(ppid_json, "supported",
> +                        port->p_dot1.ppvid & LLDP_PPVID_CAP_SUPPORTED
> +                            ? json_boolean_create(true)
> +                            : json_boolean_create(false));
> +        json_object_put(ppid_json, "enabled",
> +                        port->p_dot1.ppvid & LLDP_PPVID_CAP_ENABLED
> +                            ? json_boolean_create(true)
> +                            : json_boolean_create(false));
> +        json_object_put(interface_item_json, "ppid", ppid_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, "      Adv:\t %s", 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_dot3_enable & (1 << LLDP_TLV_DOT3_MFS)) {
> +        ds_put_format(ds, "    MFS:\t %d\n", port->p_dot3.mfs);
> +    }
> +
> +    if (port->p_dot3_enable & (1 << LLDP_TLV_DOT3_MAC)) {
> +        ds_put_format(
> +            ds, "    PMD autoneg:  supported: %s, enabled: %s\n",
> +            port->p_dot3.auto_nego & LLDP_DOT3_LINK_AUTONEG_SUPPORT ? "yes"
> +                                                                    : "no",
> +            port->p_dot3.auto_nego & LLDP_DOT3_LINK_AUTONEG_ENABLED ? "yes"
> +                                                                    : "no");
> +
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_10BASE_T,
> +                                     LLDP_DOT3_LINK_AUTONEG_10BASE_T_FD,
> +                                     "10Base-T");
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
> +                                     LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
> +                                     "100Base-T4");
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_100BASE_TX,
> +                                     LLDP_DOT3_LINK_AUTONEG_100BASE_TX_FD,
> +                                     "100Base-TX");
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_100BASE_T2,
> +                                     LLDP_DOT3_LINK_AUTONEG_100BASE_T2_FD,
> +                                     "100Base-T2");
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_1000BASE_X,
> +                                     LLDP_DOT3_LINK_AUTONEG_1000BASE_X_FD,
> +                                     "1000Base-X");
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_1000BASE_T,
> +                                     LLDP_DOT3_LINK_AUTONEG_1000BASE_T_FD,
> +                                     "1000Base-T");
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE,
> +                                     LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE,
> +                                     "FDX_PAUSE");
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE,
> +                                     LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE,
> +                                     "FDX_APAUSE");
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE,
> +                                     LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE,
> +                                     "FDX_SPAUSE");
> +        lldp_dot3_autoneg_advertised(ds, port->p_dot3.pmd_auto_nego,
> +                                     LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE,
> +                                     LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE,
> +                                     "FDX_BPAUSE");
> +
> +        ds_put_format(ds, "      MAU oper type:\t %d\n", port->p_dot3.mau);
> +    }
> +
> +    if (port->p_dot3_enable & (1 << LLDP_TLV_DOT3_POWER)) {
> +        ds_put_format(
> +            ds,
> +            "    MDI Power:\t supported: %s, enabled: %s, pair control: 
> %s\n",
> +            port->p_dot3.mdi & LLDP_DOT3_POWER_SUPPORT ? "yes" : "no",
> +            port->p_dot3.mdi & LLDP_DOT3_POWER_ENABLED ? "yes" : "no",
> +            port->p_dot3.mdi & LLDP_DOT3_POWER_PAIRCONTROL ? "yes" : "no");
> +
> +        ds_put_format(ds, "      Device type:\t %s\n",
> +                      port->p_dot3.mdi & LLDP_DOT3_POWER_PORT_CLASS ? "PSE"
> +                                                                    : "PD");
> +    }
> +}
> +
> +static void
> +lldp_print_neighbor_port_dot3_json(struct json *port_json,
> +                                   struct lldpd_port *port)
> +{
> +    if (port->p_dot3_enable & (1 << LLDP_TLV_DOT3_MAC)) {
> +        struct json *auto_nego_json = json_object_create();
> +        json_object_put(auto_nego_json, "supported",
> +                        port->p_dot3.auto_nego & 
> LLDP_DOT3_LINK_AUTONEG_SUPPORT
> +                            ? json_boolean_create(true)
> +                            : json_boolean_create(false));
> +        json_object_put(auto_nego_json, "enabled",
> +                        port->p_dot3.auto_nego & 
> LLDP_DOT3_LINK_AUTONEG_ENABLED
> +                            ? json_boolean_create(true)
> +                            : json_boolean_create(false));
> +
> +        struct json *advertised_json = NULL;
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_10BASE_T,
> +                                          LLDP_DOT3_LINK_AUTONEG_10BASE_T_FD,
> +                                          "10Base-T");
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
> +                                          LLDP_DOT3_LINK_AUTONEG_100BASE_T4,
> +                                          "100Base-T4");
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_100BASE_TX,
> +                                          
> LLDP_DOT3_LINK_AUTONEG_100BASE_TX_FD,
> +                                          "100Base-TX");
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_100BASE_T2,
> +                                          
> LLDP_DOT3_LINK_AUTONEG_100BASE_T2_FD,
> +                                          "100Base-T2");
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_1000BASE_X,
> +                                          
> LLDP_DOT3_LINK_AUTONEG_1000BASE_X_FD,
> +                                          "1000Base-X");
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_1000BASE_T,
> +                                          
> LLDP_DOT3_LINK_AUTONEG_1000BASE_T_FD,
> +                                          "1000Base-T");
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE,
> +                                          LLDP_DOT3_LINK_AUTONEG_FDX_PAUSE,
> +                                          "FDX_PAUSE");
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE,
> +                                          LLDP_DOT3_LINK_AUTONEG_FDX_APAUSE,
> +                                          "FDX_APAUSE");
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE,
> +                                          LLDP_DOT3_LINK_AUTONEG_FDX_SPAUSE,
> +                                          "FDX_SPAUSE");
> +        lldp_dot3_autoneg_advertised_json(&advertised_json,
> +                                          port->p_dot3.pmd_auto_nego,
> +                                          LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE,
> +                                          LLDP_DOT3_LINK_AUTONEG_FDX_BPAUSE,
> +                                          "FDX_BPAUSE");
> +        if (advertised_json) {
> +            json_object_put(auto_nego_json, "advertised", advertised_json);
> +        }
> +
> +        json_object_put(auto_nego_json, "current",
> +                        json_integer_create(port->p_dot3.mau));
> +
> +        json_object_put(port_json, "auto-negotiation", auto_nego_json);
> +    }
> +
> +    if (port->p_dot3_enable & (1 << LLDP_TLV_DOT3_POWER)) {
> +        struct json *power_json = json_object_create();
> +
> +        json_object_put(
> +            power_json, "device-type",
> +            json_string_create(
> +                port->p_dot3.mdi & LLDP_DOT3_POWER_PORT_CLASS ? "PSE" : 
> "PD"));
> +
> +        json_object_put(
> +            power_json, "supported",
> +            json_boolean_create(
> +                port->p_dot3.mdi & LLDP_DOT3_POWER_SUPPORT ? true : false));
> +
> +        json_object_put(
> +            power_json, "enabled",
> +            json_boolean_create(
> +                port->p_dot3.mdi & LLDP_DOT3_POWER_ENABLED ? true : false));
> +
> +        json_object_put(power_json, "paircontrol",
> +                        json_boolean_create(port->p_dot3.mdi &
> +                                                    
> LLDP_DOT3_POWER_PAIRCONTROL
> +                                                ? true
> +                                                : false));
> +
> +        json_object_put(port_json, "power", power_json);
> +    }
> +
> +    if (port->p_dot3_enable & (1 << LLDP_TLV_DOT3_MFS)) {
> +        json_object_put(port_json, "mfs",
> +                        json_integer_create(port->p_dot3.mfs));
> +    }
> +}
> +
>  static void
>  lldp_print_neighbor(struct ds *ds, struct lldp *lldp) OVS_REQUIRES(mutex)
>  {
> @@ -411,6 +708,9 @@ lldp_print_neighbor(struct ds *ds, struct lldp *lldp) 
> OVS_REQUIRES(mutex)
>                            strlen(port->p_descr) ? port->p_descr : none_str);
>              ds_put_format(ds, "    TTL:\t %d\n", port->p_chassis->c_ttl);
>  
> +            lldp_print_neighbor_port_dot3(ds, port);
> +            lldp_print_neighbor_port_dot1(ds, port);
> +
>              ds_put_format(ds, 
> "-----------------------------------------------"
>                                "--------------------------------\n");
>          }
> @@ -578,6 +878,9 @@ lldp_print_neighbor_json(struct json 
> *interface_array_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);

I didn't look at the json output side, because I think Eelco has some
opinions on how best to output those details.

But Ilya noted issues with the command outputs, so in the next round
that needs to be addressed.

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to