1 /** @file
2  @brief LLDP definitions and handler
3 
4  This is not to be included by the application.
5  */
6 
7 /*
8  * Copyright (c) 2017 Intel Corporation
9  *
10  * SPDX-License-Identifier: Apache-2.0
11  */
12 
13 #ifndef ZEPHYR_INCLUDE_NET_LLDP_H_
14 #define ZEPHYR_INCLUDE_NET_LLDP_H_
15 
16 /**
17  * @brief LLDP definitions and helpers
18  * @defgroup lldp Link Layer Discovery Protocol definitions and helpers
19  * @since 1.13
20  * @version 0.8.0
21  * @ingroup networking
22  * @{
23  */
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 /** @cond INTERNAL_HIDDEN */
30 
31 #define LLDP_TLV_GET_LENGTH(type_length)	(type_length & BIT_MASK(9))
32 #define LLDP_TLV_GET_TYPE(type_length)		((uint8_t)(type_length >> 9))
33 
34 /* LLDP Definitions */
35 
36 /* According to the spec, End of LLDPDU TLV value is constant. */
37 #define NET_LLDP_END_LLDPDU_VALUE 0x0000
38 
39 /*
40  * For the Chassis ID TLV Value, if subtype is a MAC address then we must
41  * use values from CONFIG_NET_LLDP_CHASSIS_ID_MAC0 through
42  * CONFIG_NET_LLDP_CHASSIS_ID_MAC5. If not, we use CONFIG_NET_LLDP_CHASSIS_ID.
43  *
44  * FIXME: implement a similar scheme for subtype 5 (network address).
45  */
46 #if defined(CONFIG_NET_LLDP_CHASSIS_ID_SUBTYPE)
47 #if (CONFIG_NET_LLDP_CHASSIS_ID_SUBTYPE == 4)
48 #define NET_LLDP_CHASSIS_ID_VALUE		\
49 	{					\
50 	  CONFIG_NET_LLDP_CHASSIS_ID_MAC0,	\
51 	  CONFIG_NET_LLDP_CHASSIS_ID_MAC1,	\
52 	  CONFIG_NET_LLDP_CHASSIS_ID_MAC2,	\
53 	  CONFIG_NET_LLDP_CHASSIS_ID_MAC3,	\
54 	  CONFIG_NET_LLDP_CHASSIS_ID_MAC4,	\
55 	  CONFIG_NET_LLDP_CHASSIS_ID_MAC5 	\
56 	}
57 
58 #define NET_LLDP_CHASSIS_ID_VALUE_LEN (6)
59 #else
60 #define NET_LLDP_CHASSIS_ID_VALUE CONFIG_NET_LLDP_CHASSIS_ID
61 #define NET_LLDP_CHASSIS_ID_VALUE_LEN (sizeof(CONFIG_NET_LLDP_CHASSIS_ID) - 1)
62 #endif
63 #else
64 #define NET_LLDP_CHASSIS_ID_VALUE 0
65 #define NET_LLDP_CHASSIS_ID_VALUE_LEN 0
66 #endif
67 
68 /*
69  * For the Port ID TLV Value, if subtype is a MAC address then we must
70  * use values from CONFIG_NET_LLDP_PORT_ID_MAC0 through
71  * CONFIG_NET_LLDP_PORT_ID_MAC5. If not, we use CONFIG_NET_LLDP_PORT_ID.
72  *
73  * FIXME: implement a similar scheme for subtype 4 (network address).
74  */
75 #if defined(CONFIG_NET_LLDP_PORT_ID_SUBTYPE)
76 #if (CONFIG_NET_LLDP_PORT_ID_SUBTYPE == 3)
77 #define NET_LLDP_PORT_ID_VALUE		\
78 	{				\
79 	  CONFIG_NET_LLDP_PORT_ID_MAC0,	\
80 	  CONFIG_NET_LLDP_PORT_ID_MAC1, \
81 	  CONFIG_NET_LLDP_PORT_ID_MAC2, \
82 	  CONFIG_NET_LLDP_PORT_ID_MAC3, \
83 	  CONFIG_NET_LLDP_PORT_ID_MAC4, \
84 	  CONFIG_NET_LLDP_PORT_ID_MAC5  \
85 	}
86 
87 #define NET_LLDP_PORT_ID_VALUE_LEN (6)
88 #else
89 #define NET_LLDP_PORT_ID_VALUE CONFIG_NET_LLDP_PORT_ID
90 #define NET_LLDP_PORT_ID_VALUE_LEN (sizeof(CONFIG_NET_LLDP_PORT_ID) - 1)
91 #endif
92 #else
93 #define NET_LLDP_PORT_ID_VALUE 0
94 #define NET_LLDP_PORT_ID_VALUE_LEN 0
95 #endif
96 
97 /*
98  * TLVs Length.
99  * Note that TLVs that have a subtype must have a byte added to their length.
100  */
101 #define NET_LLDP_CHASSIS_ID_TLV_LEN (NET_LLDP_CHASSIS_ID_VALUE_LEN + 1)
102 #define NET_LLDP_PORT_ID_TLV_LEN (NET_LLDP_PORT_ID_VALUE_LEN + 1)
103 #define NET_LLDP_TTL_TLV_LEN (2)
104 
105 /*
106  * Time to Live value.
107  * Calculate based on section 9.2.5.22 from LLDP spec.
108  *
109  * FIXME: when the network interface is about to be ‘disabled’ TTL shall be set
110  * to zero so LLDP Rx agents can invalidate the entry related to this node.
111  */
112 #if defined(CONFIG_NET_LLDP_TX_INTERVAL) && defined(CONFIG_NET_LLDP_TX_HOLD)
113 #define NET_LLDP_TTL \
114 	MIN((CONFIG_NET_LLDP_TX_INTERVAL * CONFIG_NET_LLDP_TX_HOLD) + 1, 65535)
115 #endif
116 
117 
118 struct net_if;
119 
120 /** @endcond */
121 
122 /** TLV Types. Please refer to table 8-1 from IEEE 802.1AB standard. */
123 enum net_lldp_tlv_type {
124 	LLDP_TLV_END_LLDPDU          = 0, /**< End Of LLDPDU (optional)      */
125 	LLDP_TLV_CHASSIS_ID          = 1, /**< Chassis ID (mandatory)        */
126 	LLDP_TLV_PORT_ID             = 2, /**< Port ID (mandatory)           */
127 	LLDP_TLV_TTL                 = 3, /**< Time To Live (mandatory)      */
128 	LLDP_TLV_PORT_DESC           = 4, /**< Port Description (optional)   */
129 	LLDP_TLV_SYSTEM_NAME         = 5, /**< System Name (optional)        */
130 	LLDP_TLV_SYSTEM_DESC         = 6, /**< System Description (optional) */
131 	LLDP_TLV_SYSTEM_CAPABILITIES = 7, /**< System Capability (optional)  */
132 	LLDP_TLV_MANAGEMENT_ADDR     = 8, /**< Management Address (optional) */
133 	/* Types 9 - 126 are reserved. */
134 	LLDP_TLV_ORG_SPECIFIC       = 127, /**< Org specific TLVs (optional) */
135 };
136 
137 /** Chassis ID TLV, see chapter 8.5.2 in IEEE 802.1AB */
138 struct net_lldp_chassis_tlv {
139 	/** 7 bits for type, 9 bits for length */
140 	uint16_t type_length;
141 	/** ID subtype */
142 	uint8_t subtype;
143 	/** Chassis ID value */
144 	uint8_t value[NET_LLDP_CHASSIS_ID_VALUE_LEN];
145 } __packed;
146 
147 /** Port ID TLV, see chapter 8.5.3 in IEEE 802.1AB */
148 struct net_lldp_port_tlv {
149 	/** 7 bits for type, 9 bits for length */
150 	uint16_t type_length;
151 	/** ID subtype */
152 	uint8_t subtype;
153 	/** Port ID value */
154 	uint8_t value[NET_LLDP_PORT_ID_VALUE_LEN];
155 } __packed;
156 
157 /** Time To Live TLV, see chapter 8.5.4 in IEEE 802.1AB */
158 struct net_lldp_time_to_live_tlv {
159 	/** 7 bits for type, 9 bits for length */
160 	uint16_t type_length;
161 	/** Time To Live (TTL) value */
162 	uint16_t ttl;
163 } __packed;
164 
165 /**
166  * LLDP Data Unit (LLDPDU) shall contain the following ordered TLVs
167  * as stated in "8.2 LLDPDU format" from the IEEE 802.1AB
168  */
169 struct net_lldpdu {
170 	struct net_lldp_chassis_tlv chassis_id;	/**< Mandatory Chassis TLV */
171 	struct net_lldp_port_tlv port_id;	/**< Mandatory Port TLV */
172 	struct net_lldp_time_to_live_tlv ttl;	/**< Mandatory TTL TLV */
173 } __packed;
174 
175 /**
176  * @brief Set the LLDP data unit for a network interface.
177  *
178  * @param iface Network interface
179  * @param lldpdu LLDP data unit struct
180  *
181  * @return 0 if ok, <0 if error
182  */
183 int net_lldp_config(struct net_if *iface, const struct net_lldpdu *lldpdu);
184 
185 /**
186  * @brief Set the Optional LLDP TLVs for a network interface.
187  *
188  * @param iface Network interface
189  * @param tlv LLDP optional TLVs following mandatory part
190  * @param len Length of the optional TLVs
191  *
192  * @return 0 if ok, <0 if error
193  */
194 int net_lldp_config_optional(struct net_if *iface, const uint8_t *tlv,
195 			     size_t len);
196 
197 /**
198  * @brief Initialize LLDP engine.
199  */
200 void net_lldp_init(void);
201 
202 /**
203  * @brief LLDP Receive packet callback
204  *
205  * Callback gets called upon receiving packet. It is responsible for
206  * freeing packet or indicating to the stack that it needs to free packet
207  * by returning correct net_verdict.
208  *
209  * Returns:
210  *  - NET_DROP, if packet was invalid, rejected or we want the stack to free it.
211  *    In this case the core stack will free the packet.
212  *  - NET_OK, if the packet was accepted, in this case the ownership of the
213  *    net_pkt goes to callback and core network stack will forget it.
214  */
215 typedef enum net_verdict (*net_lldp_recv_cb_t)(struct net_if *iface,
216 					       struct net_pkt *pkt);
217 
218 /**
219  * @brief Register LLDP Rx callback function
220  *
221  * @param iface Network interface
222  * @param cb Callback function
223  *
224  * @return 0 if ok, < 0 if error
225  */
226 int net_lldp_register_callback(struct net_if *iface, net_lldp_recv_cb_t cb);
227 
228 /**
229  * @brief Parse LLDP packet
230  *
231  * @param iface Network interface
232  * @param pkt Network packet
233  *
234  * @return Return the policy for network buffer
235  */
236 enum net_verdict net_lldp_recv(struct net_if *iface, struct net_pkt *pkt);
237 
238 /**
239  * @brief Set LLDP protocol data unit (LLDPDU) for the network interface.
240  *
241  * @param iface Network interface
242  *
243  * @return <0 if error, index in lldp array if iface is found there
244  */
245 #if defined(CONFIG_NET_LLDP)
246 int net_lldp_set_lldpdu(struct net_if *iface);
247 #else
248 #define net_lldp_set_lldpdu(iface)
249 #endif
250 
251 /**
252  * @brief Unset LLDP protocol data unit (LLDPDU) for the network interface.
253  *
254  * @param iface Network interface
255  */
256 #if defined(CONFIG_NET_LLDP)
257 void net_lldp_unset_lldpdu(struct net_if *iface);
258 #else
259 #define net_lldp_unset_lldpdu(iface)
260 #endif
261 
262 #ifdef __cplusplus
263 }
264 #endif
265 
266 /**
267  * @}
268  */
269 
270 #endif /* ZEPHYR_INCLUDE_NET_LLDP_H_ */
271