|  | /** @file | 
|  | @brief LLDP definitions and handler | 
|  |  | 
|  | This is not to be included by the application. | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * Copyright (c) 2017 Intel Corporation | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #ifndef ZEPHYR_INCLUDE_NET_LLDP_H_ | 
|  | #define ZEPHYR_INCLUDE_NET_LLDP_H_ | 
|  |  | 
|  | /** | 
|  | * @brief LLDP definitions and helpers | 
|  | * @defgroup lldp Link Layer Discovery Protocol definitions and helpers | 
|  | * @ingroup networking | 
|  | * @{ | 
|  | */ | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | extern "C" { | 
|  | #endif | 
|  |  | 
|  | /** @cond INTERNAL_HIDDEN */ | 
|  |  | 
|  | #define LLDP_TLV_GET_LENGTH(type_length)	(type_length & BIT_MASK(9)) | 
|  | #define LLDP_TLV_GET_TYPE(type_length)		((uint8_t)(type_length >> 9)) | 
|  |  | 
|  | /* LLDP Definitions */ | 
|  |  | 
|  | /* According to the spec, End of LLDPDU TLV value is constant. */ | 
|  | #define NET_LLDP_END_LLDPDU_VALUE 0x0000 | 
|  |  | 
|  | /* | 
|  | * For the Chassis ID TLV Value, if subtype is a MAC address then we must | 
|  | * use values from CONFIG_NET_LLDP_CHASSIS_ID_MAC0 through | 
|  | * CONFIG_NET_LLDP_CHASSIS_ID_MAC5. If not, we use CONFIG_NET_LLDP_CHASSIS_ID. | 
|  | * | 
|  | * FIXME: implement a similar scheme for subtype 5 (network address). | 
|  | */ | 
|  | #if defined(CONFIG_NET_LLDP_CHASSIS_ID_SUBTYPE) | 
|  | #if (CONFIG_NET_LLDP_CHASSIS_ID_SUBTYPE == 4) | 
|  | #define NET_LLDP_CHASSIS_ID_VALUE		\ | 
|  | {					\ | 
|  | CONFIG_NET_LLDP_CHASSIS_ID_MAC0,	\ | 
|  | CONFIG_NET_LLDP_CHASSIS_ID_MAC1,	\ | 
|  | CONFIG_NET_LLDP_CHASSIS_ID_MAC2,	\ | 
|  | CONFIG_NET_LLDP_CHASSIS_ID_MAC3,	\ | 
|  | CONFIG_NET_LLDP_CHASSIS_ID_MAC4,	\ | 
|  | CONFIG_NET_LLDP_CHASSIS_ID_MAC5 	\ | 
|  | } | 
|  |  | 
|  | #define NET_LLDP_CHASSIS_ID_VALUE_LEN (6) | 
|  | #else | 
|  | #define NET_LLDP_CHASSIS_ID_VALUE CONFIG_NET_LLDP_CHASSIS_ID | 
|  | #define NET_LLDP_CHASSIS_ID_VALUE_LEN (sizeof(CONFIG_NET_LLDP_CHASSIS_ID) - 1) | 
|  | #endif | 
|  | #else | 
|  | #define NET_LLDP_CHASSIS_ID_VALUE 0 | 
|  | #define NET_LLDP_CHASSIS_ID_VALUE_LEN 0 | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * For the Port ID TLV Value, if subtype is a MAC address then we must | 
|  | * use values from CONFIG_NET_LLDP_PORT_ID_MAC0 through | 
|  | * CONFIG_NET_LLDP_PORT_ID_MAC5. If not, we use CONFIG_NET_LLDP_PORT_ID. | 
|  | * | 
|  | * FIXME: implement a similar scheme for subtype 4 (network address). | 
|  | */ | 
|  | #if defined(CONFIG_NET_LLDP_PORT_ID_SUBTYPE) | 
|  | #if (CONFIG_NET_LLDP_PORT_ID_SUBTYPE == 3) | 
|  | #define NET_LLDP_PORT_ID_VALUE		\ | 
|  | {				\ | 
|  | CONFIG_NET_LLDP_PORT_ID_MAC0,	\ | 
|  | CONFIG_NET_LLDP_PORT_ID_MAC1, \ | 
|  | CONFIG_NET_LLDP_PORT_ID_MAC2, \ | 
|  | CONFIG_NET_LLDP_PORT_ID_MAC3, \ | 
|  | CONFIG_NET_LLDP_PORT_ID_MAC4, \ | 
|  | CONFIG_NET_LLDP_PORT_ID_MAC5  \ | 
|  | } | 
|  |  | 
|  | #define NET_LLDP_PORT_ID_VALUE_LEN (6) | 
|  | #else | 
|  | #define NET_LLDP_PORT_ID_VALUE CONFIG_NET_LLDP_PORT_ID | 
|  | #define NET_LLDP_PORT_ID_VALUE_LEN (sizeof(CONFIG_NET_LLDP_PORT_ID) - 1) | 
|  | #endif | 
|  | #else | 
|  | #define NET_LLDP_PORT_ID_VALUE 0 | 
|  | #define NET_LLDP_PORT_ID_VALUE_LEN 0 | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * TLVs Length. | 
|  | * Note that TLVs that have a subtype must have a byte added to their length. | 
|  | */ | 
|  | #define NET_LLDP_CHASSIS_ID_TLV_LEN (NET_LLDP_CHASSIS_ID_VALUE_LEN + 1) | 
|  | #define NET_LLDP_PORT_ID_TLV_LEN (NET_LLDP_PORT_ID_VALUE_LEN + 1) | 
|  | #define NET_LLDP_TTL_TLV_LEN (2) | 
|  |  | 
|  | /* | 
|  | * Time to Live value. | 
|  | * Calculate based on section 9.2.5.22 from LLDP spec. | 
|  | * | 
|  | * FIXME: when the network interface is about to be ‘disabled’ TTL shall be set | 
|  | * to zero so LLDP Rx agents can invalidate the entry related to this node. | 
|  | */ | 
|  | #if defined(CONFIG_NET_LLDP_TX_INTERVAL) && defined(CONFIG_NET_LLDP_TX_HOLD) | 
|  | #define NET_LLDP_TTL \ | 
|  | MIN((CONFIG_NET_LLDP_TX_INTERVAL * CONFIG_NET_LLDP_TX_HOLD) + 1, 65535) | 
|  | #endif | 
|  |  | 
|  |  | 
|  | struct net_if; | 
|  |  | 
|  | /** @endcond */ | 
|  |  | 
|  | /** TLV Types. Please refer to table 8-1 from IEEE 802.1AB standard. */ | 
|  | enum net_lldp_tlv_type { | 
|  | LLDP_TLV_END_LLDPDU          = 0, /**< End Of LLDPDU (optional)      */ | 
|  | LLDP_TLV_CHASSIS_ID          = 1, /**< Chassis ID (mandatory)        */ | 
|  | LLDP_TLV_PORT_ID             = 2, /**< Port ID (mandatory)           */ | 
|  | LLDP_TLV_TTL                 = 3, /**< Time To Live (mandatory)      */ | 
|  | LLDP_TLV_PORT_DESC           = 4, /**< Port Description (optional)   */ | 
|  | LLDP_TLV_SYSTEM_NAME         = 5, /**< System Name (optional)        */ | 
|  | LLDP_TLV_SYSTEM_DESC         = 6, /**< System Description (optional) */ | 
|  | LLDP_TLV_SYSTEM_CAPABILITIES = 7, /**< System Capability (optional)  */ | 
|  | LLDP_TLV_MANAGEMENT_ADDR     = 8, /**< Management Address (optional) */ | 
|  | /* Types 9 - 126 are reserved. */ | 
|  | LLDP_TLV_ORG_SPECIFIC       = 127, /**< Org specific TLVs (optional) */ | 
|  | }; | 
|  |  | 
|  | /** Chassis ID TLV, see chapter 8.5.2 in IEEE 802.1AB */ | 
|  | struct net_lldp_chassis_tlv { | 
|  | /** 7 bits for type, 9 bits for length */ | 
|  | uint16_t type_length; | 
|  | /** ID subtype */ | 
|  | uint8_t subtype; | 
|  | /** Chassis ID value */ | 
|  | uint8_t value[NET_LLDP_CHASSIS_ID_VALUE_LEN]; | 
|  | } __packed; | 
|  |  | 
|  | /** Port ID TLV, see chapter 8.5.3 in IEEE 802.1AB */ | 
|  | struct net_lldp_port_tlv { | 
|  | /** 7 bits for type, 9 bits for length */ | 
|  | uint16_t type_length; | 
|  | /** ID subtype */ | 
|  | uint8_t subtype; | 
|  | /** Port ID value */ | 
|  | uint8_t value[NET_LLDP_PORT_ID_VALUE_LEN]; | 
|  | } __packed; | 
|  |  | 
|  | /** Time To Live TLV, see chapter 8.5.4 in IEEE 802.1AB */ | 
|  | struct net_lldp_time_to_live_tlv { | 
|  | /** 7 bits for type, 9 bits for length */ | 
|  | uint16_t type_length; | 
|  | /** Time To Live (TTL) value */ | 
|  | uint16_t ttl; | 
|  | } __packed; | 
|  |  | 
|  | /** | 
|  | * LLDP Data Unit (LLDPDU) shall contain the following ordered TLVs | 
|  | * as stated in "8.2 LLDPDU format" from the IEEE 802.1AB | 
|  | */ | 
|  | struct net_lldpdu { | 
|  | struct net_lldp_chassis_tlv chassis_id;	/**< Mandatory Chassis TLV */ | 
|  | struct net_lldp_port_tlv port_id;	/**< Mandatory Port TLV */ | 
|  | struct net_lldp_time_to_live_tlv ttl;	/**< Mandatory TTL TLV */ | 
|  | } __packed; | 
|  |  | 
|  | /** | 
|  | * @brief Set the LLDP data unit for a network interface. | 
|  | * | 
|  | * @param iface Network interface | 
|  | * @param lldpdu LLDP data unit struct | 
|  | * | 
|  | * @return 0 if ok, <0 if error | 
|  | */ | 
|  | int net_lldp_config(struct net_if *iface, const struct net_lldpdu *lldpdu); | 
|  |  | 
|  | /** | 
|  | * @brief Set the Optional LLDP TLVs for a network interface. | 
|  | * | 
|  | * @param iface Network interface | 
|  | * @param tlv LLDP optional TLVs following mandatory part | 
|  | * @param len Length of the optional TLVs | 
|  | * | 
|  | * @return 0 if ok, <0 if error | 
|  | */ | 
|  | int net_lldp_config_optional(struct net_if *iface, const uint8_t *tlv, | 
|  | size_t len); | 
|  |  | 
|  | /** | 
|  | * @brief Initialize LLDP engine. | 
|  | */ | 
|  | void net_lldp_init(void); | 
|  |  | 
|  | /** | 
|  | * @brief LLDP Receive packet callback | 
|  | * | 
|  | * Callback gets called upon receiving packet. It is responsible for | 
|  | * freeing packet or indicating to the stack that it needs to free packet | 
|  | * by returning correct net_verdict. | 
|  | * | 
|  | * Returns: | 
|  | *  - NET_DROP, if packet was invalid, rejected or we want the stack to free it. | 
|  | *    In this case the core stack will free the packet. | 
|  | *  - NET_OK, if the packet was accepted, in this case the ownership of the | 
|  | *    net_pkt goes to callback and core network stack will forget it. | 
|  | */ | 
|  | typedef enum net_verdict (*net_lldp_recv_cb_t)(struct net_if *iface, | 
|  | struct net_pkt *pkt); | 
|  |  | 
|  | /** | 
|  | * @brief Register LLDP Rx callback function | 
|  | * | 
|  | * @param iface Network interface | 
|  | * @param cb Callback function | 
|  | * | 
|  | * @return 0 if ok, < 0 if error | 
|  | */ | 
|  | int net_lldp_register_callback(struct net_if *iface, net_lldp_recv_cb_t cb); | 
|  |  | 
|  | /** | 
|  | * @brief Parse LLDP packet | 
|  | * | 
|  | * @param iface Network interface | 
|  | * @param pkt Network packet | 
|  | * | 
|  | * @return Return the policy for network buffer | 
|  | */ | 
|  | enum net_verdict net_lldp_recv(struct net_if *iface, struct net_pkt *pkt); | 
|  |  | 
|  | /** | 
|  | * @brief Set LLDP protocol data unit (LLDPDU) for the network interface. | 
|  | * | 
|  | * @param iface Network interface | 
|  | * | 
|  | * @return <0 if error, index in lldp array if iface is found there | 
|  | */ | 
|  | #if defined(CONFIG_NET_LLDP) | 
|  | int net_lldp_set_lldpdu(struct net_if *iface); | 
|  | #else | 
|  | #define net_lldp_set_lldpdu(iface) | 
|  | #endif | 
|  |  | 
|  | /** | 
|  | * @brief Unset LLDP protocol data unit (LLDPDU) for the network interface. | 
|  | * | 
|  | * @param iface Network interface | 
|  | */ | 
|  | #if defined(CONFIG_NET_LLDP) | 
|  | void net_lldp_unset_lldpdu(struct net_if *iface); | 
|  | #else | 
|  | #define net_lldp_unset_lldpdu(iface) | 
|  | #endif | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | } | 
|  | #endif | 
|  |  | 
|  | /** | 
|  | * @} | 
|  | */ | 
|  |  | 
|  | #endif /* ZEPHYR_INCLUDE_NET_LLDP_H_ */ |