lldp_ext_dot3.c
Go to the documentation of this file.
1 /**
2  * @file lldp_ext_dot3.c
3  * @brief IEEE 802.3 LLDP extension
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL LLDP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "lldp/lldp.h"
37 #include "lldp/lldp_ext_dot3.h"
38 #include "lldp/lldp_misc.h"
39 #include "lldp/lldp_debug.h"
40 #include "debug.h"
41 
42 //Check TCP/IP stack configuration
43 #if (LLDP_SUPPORT == ENABLED && LLDP_TX_MODE_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Set MAC/PHY configuration/status
48  * @param[in] context Pointer to the LLDP agent context
49  * @param[in] portIndex Port index
50  * @param[in] autoNegSupportStatus Bit-map that identifies the auto-negotiation
51  * support and current status of the local 802.3 LAN station
52  * @param[in] pmdAutoNegAdvCap PMD auto-negotiation advertised capability
53  * @param[in] operationalMauType MAU type of the sending device
54  * @return Error code
55  **/
56 
58  uint_t portIndex, uint8_t autoNegSupportStatus, uint16_t pmdAutoNegAdvCap,
59  uint16_t operationalMauType)
60 {
61  error_t error;
62  size_t n;
65 
66  //Make sure the LLDP agent context is valid
67  if(context == NULL)
68  {
70  }
71 
72  //Invalid port index?
73  if(portIndex < 1 || portIndex > context->numPorts)
74  {
75  return ERROR_INVALID_PORT;
76  }
77 
78  //Acquire exclusive access to the LLDP agent context
79  osAcquireMutex(&context->mutex);
80 
81  //Point to the port that matches the specified port index
82  port = &context->ports[portIndex - 1];
83 
84  //Point to the buffer where to format the TLV
85  tlv = (LldpDot3MacPhyConfigStatusTlv *) context->lldpdu.data;
86 
87  //Set auto-negotiation support/status
88  tlv->autoNegSupportStatus = autoNegSupportStatus;
89  //Set PMD auto-negotiation advertised capability
90  tlv->pmdAutoNegAdvCap = htons(pmdAutoNegAdvCap);
91  //Set operational MAU type
92  tlv->operationalMauType = htons(operationalMauType);
93 
94  //Calculate the length of the TLV
96 
97  //An LLDPDU should contain no more than one MAC/PHY Configuration/Status
98  //TLV (refer to IEEE 802.1AB-2005, section G.2.4)
99  error = lldpSetOrgDefTlv(&port->txInfo, LLDP_DOT3_OUI,
100  LLDP_DOT3_SUBTYPE_MAC_PHY_CONFIG_STATUS, 0, (uint8_t *) tlv, n, TRUE);
101 
102  //Check status code
103  if(!error)
104  {
105  //The somethingChangedLocal flag must be set whenever the value of an
106  //object has changed in the local system MIB
107  lldpSomethingChangedLocal(context);
108  }
109 
110  //Release exclusive access to the LLDP agent context
111  osReleaseMutex(&context->mutex);
112 
113  //Return status code
114  return error;
115 }
116 
117 
118 /**
119  * @brief Set power-via-MDI
120  * @param[in] context Pointer to the LLDP agent context
121  * @param[in] portIndex Port index
122  * @param[in] mdiPowerSupport Bit-map of the MDI power capabilities and status
123  * @param[in] psePowerPair PSE power pair
124  * @param[in] powerClass PSE power classification
125  * @param[in] dllClassExt DLL classification extension (optional parameter)
126  * @param[in] type34Ext Type 3 and Type 4 extension (optional parameter)
127  * @return Error code
128  **/
129 
131  uint_t portIndex, uint8_t mdiPowerSupport,
133  const LldpDot3DllClassExt *dllClassExt, const LldpDot3Type34Ext *type34Ext)
134 {
135  error_t error;
136  size_t n;
139 
140  //Make sure the LLDP agent context is valid
141  if(context == NULL)
142  {
144  }
145 
146  //Invalid port index?
147  if(portIndex < 1 || portIndex > context->numPorts)
148  {
149  return ERROR_INVALID_PORT;
150  }
151 
152  //Acquire exclusive access to the LLDP agent context
153  osAcquireMutex(&context->mutex);
154 
155  //Point to the port that matches the specified port index
156  port = &context->ports[portIndex - 1];
157 
158  //Point to the buffer where to format the TLV
159  tlv = (LldpDot3PowerViaMdiTlv *) context->lldpdu.data;
160 
161  //Set MDI power support
162  tlv->mdiPowerSupport = mdiPowerSupport;
163  //Set PSE power pair
164  tlv->psePowerPair = psePowerPair;
165  //Set power class
166  tlv->powerClass = powerClass;
167 
168  //Calculate the length of the TLV
169  n = sizeof(LldpDot3PowerViaMdiTlv);
170 
171  //The DLL classification extension is optional
172  if(dllClassExt != NULL)
173  {
174  LldpDot3DllClassExt *ext;
175 
176  //Point to the buffer where to format the extension
177  ext = (LldpDot3DllClassExt *) (context->lldpdu.data + n);
178 
179  //Format DLL classification extension
180  ext->powerType = dllClassExt->powerType;
181  ext->powerSource = dllClassExt->powerSource;
182  ext->powerPriority = dllClassExt->powerPriority;
183  ext->pdRequestedPower = htons(dllClassExt->pdRequestedPower);
184  ext->pseAllocatedPower = htons(dllClassExt->pseAllocatedPower);
185 
186  //Adjust the length of the TLV
187  n += sizeof(LldpDot3DllClassExt);
188  }
189 
190  //The Type 3 and Type 4 extension is optional
191  if(dllClassExt != NULL && type34Ext != NULL)
192  {
193  LldpDot3Type34Ext *ext;
194 
195  //Point to the buffer where to format the extension
196  ext = (LldpDot3Type34Ext *) (context->lldpdu.data + n);
197 
198  //Format Type 3 and Type 4 extension
199  ext->pdRequestedPowerA = htons(type34Ext->pdRequestedPowerA);
200  ext->pdRequestedPowerB = htons(type34Ext->pdRequestedPowerB);
201  ext->pseAllocatedPowerA = htons(type34Ext->pseAllocatedPowerA);
202  ext->pseAllocatedPowerB = htons(type34Ext->pseAllocatedPowerB);
203  ext->powerStatus = htons(type34Ext->powerStatus);
204  ext->systemSetup = type34Ext->systemSetup;
205  ext->pseMaxAvailablePower = htons(type34Ext->pseMaxAvailablePower);
206  ext->autoclass = type34Ext->autoclass;
207  osMemcpy(ext->powerDown, type34Ext->powerDown, 3);
208 
209  //Adjust the length of the TLV
210  n += sizeof(LldpDot3Type34Ext);
211  }
212 
213  //An LLDPDU should contain no more than one Power Via MDI TLV (refer to
214  //IEEE 802.1AB-2005, section G.3.4)
215  error = lldpSetOrgDefTlv(&port->txInfo, LLDP_DOT3_OUI,
216  LLDP_DOT3_SUBTYPE_POWER_VIA_MDI, 0, (uint8_t *) tlv, n, TRUE);
217 
218  //Check status code
219  if(!error)
220  {
221  //The somethingChangedLocal flag must be set whenever the value of an
222  //object has changed in the local system MIB
223  lldpSomethingChangedLocal(context);
224  }
225 
226  //Release exclusive access to the LLDP agent context
227  osReleaseMutex(&context->mutex);
228 
229  //Return status code
230  return error;
231 }
232 
233 
234 /**
235  * @brief Set Link aggregation
236  * @param[in] context Pointer to the LLDP agent context
237  * @param[in] portIndex Port index
238  * @param[in] aggregationStatus Bit-map of the link aggregation capabilities
239  * and the current aggregation status of the link
240  * @param[in] aggregatedPortId IEEE 802.3 aggregated port identifier,
241  * @return Error code
242  **/
243 
245  uint_t portIndex, uint8_t aggregationStatus, uint32_t aggregatedPortId)
246 {
247  error_t error;
248  size_t n;
251 
252  //Make sure the LLDP agent context is valid
253  if(context == NULL)
254  {
256  }
257 
258  //Invalid port index?
259  if(portIndex < 1 || portIndex > context->numPorts)
260  {
261  return ERROR_INVALID_PORT;
262  }
263 
264  //Acquire exclusive access to the LLDP agent context
265  osAcquireMutex(&context->mutex);
266 
267  //Point to the port that matches the specified port index
268  port = &context->ports[portIndex - 1];
269 
270  //Point to the buffer where to format the TLV
271  tlv = (LldpDot3LinkAggregationTlv *) context->lldpdu.data;
272 
273  //Set aggregation status
274  tlv->aggregationStatus = aggregationStatus;
275  //Set aggregated port ID
276  tlv->aggregatedPortId = htonl(aggregatedPortId);
277 
278  //Calculate the length of the TLV
279  n = sizeof(LldpDot3LinkAggregationTlv);
280 
281  //An LLDPDU should contain no more than one Link Aggregation TLV (refer
282  //to IEEE 802.1AB-2005, section G.4.3)
283  error = lldpSetOrgDefTlv(&port->txInfo, LLDP_DOT3_OUI,
284  LLDP_DOT3_SUBTYPE_LINK_AGGREGATION, 0, (uint8_t *) tlv, n, TRUE);
285 
286  //Check status code
287  if(!error)
288  {
289  //The somethingChangedLocal flag must be set whenever the value of an
290  //object has changed in the local system MIB
291  lldpSomethingChangedLocal(context);
292  }
293 
294  //Release exclusive access to the LLDP agent context
295  osReleaseMutex(&context->mutex);
296 
297  //Return status code
298  return error;
299 }
300 
301 
302 /**
303  * @brief Set maximum frame size
304  * @param[in] context Pointer to the LLDP agent context
305  * @param[in] portIndex Port index
306  * @param[in] maxFrameSize Maximum supported frame size, in octets
307  * @return Error code
308  **/
309 
311  uint_t portIndex, uint16_t maxFrameSize)
312 {
313  error_t error;
314  size_t n;
317 
318  //Make sure the LLDP agent context is valid
319  if(context == NULL)
320  {
322  }
323 
324  //Invalid port index?
325  if(portIndex < 1 || portIndex > context->numPorts)
326  {
327  return ERROR_INVALID_PORT;
328  }
329 
330  //Acquire exclusive access to the LLDP agent context
331  osAcquireMutex(&context->mutex);
332 
333  //Point to the port that matches the specified port index
334  port = &context->ports[portIndex - 1];
335 
336  //Point to the buffer where to format the TLV
337  tlv = (LldpDot3MaxFrameSizeTlv *) context->lldpdu.data;
338 
339  //Set maximum frame size
340  tlv->maxFrameSize = htons(maxFrameSize);
341 
342  //Calculate the length of the TLV
343  n = sizeof(LldpDot3MaxFrameSizeTlv);
344 
345  //An LLDPDU should contain no more than one Maximum Frame Size TLV (refer
346  //to IEEE 802.1AB-2005, section G.5.2)
347  error = lldpSetOrgDefTlv(&port->txInfo, LLDP_DOT3_OUI,
348  LLDP_DOT3_SUBTYPE_MAX_FRAME_SIZE, 0, (uint8_t *) tlv, n, TRUE);
349 
350  //Check status code
351  if(!error)
352  {
353  //The somethingChangedLocal flag must be set whenever the value of an
354  //object has changed in the local system MIB
355  lldpSomethingChangedLocal(context);
356  }
357 
358  //Release exclusive access to the LLDP agent context
359  osReleaseMutex(&context->mutex);
360 
361  //Return status code
362  return error;
363 }
364 
365 
366 /**
367  * @brief Set power-via-MDI measurements
368  * @param[in] context Pointer to the LLDP agent context
369  * @param[in] portIndex Port index
370  * @param[in] measurements Measured values
371  * @param[in] psePowerPriceIndex Index of the current price of electricity
372  * compared to what the PSE considers the nominal electricity price
373  * @return Error code
374  **/
375 
377  uint_t portIndex, uint8_t measurements[20], uint16_t psePowerPriceIndex)
378 {
379  error_t error;
380  size_t n;
383 
384  //Make sure the LLDP agent context is valid
385  if(context == NULL)
386  {
388  }
389 
390  //Invalid port index?
391  if(portIndex < 1 || portIndex > context->numPorts)
392  {
393  return ERROR_INVALID_PORT;
394  }
395 
396  //Acquire exclusive access to the LLDP agent context
397  osAcquireMutex(&context->mutex);
398 
399  //Point to the port that matches the specified port index
400  port = &context->ports[portIndex - 1];
401 
402  //Point to the buffer where to format the TLV
403  tlv = (LldpDot3PowerViaMdiMeasTlv *) context->lldpdu.data;
404 
405  //Copy measurements field
406  osMemcpy(tlv->measurements, measurements, 20);
407 
408  //Set PSE power price index
409  tlv->psePowerPriceIndex = htons(psePowerPriceIndex);
410 
411  //Calculate the length of the TLV
412  n = sizeof(LldpDot3PowerViaMdiMeasTlv);
413 
414  //An LLDPDU should contain no more than one Power Via MDI Measurements
415  //TLV (refer to IEEE 802.3bt, section 79.3.8.3)
416  error = lldpSetOrgDefTlv(&port->txInfo, LLDP_DOT3_OUI,
417  LLDP_DOT3_SUBTYPE_POWER_VIA_MDI_MEAS, 0, (uint8_t *) tlv, n, TRUE);
418 
419  //Check status code
420  if(!error)
421  {
422  //The somethingChangedLocal flag must be set whenever the value of an
423  //object has changed in the local system MIB
424  lldpSomethingChangedLocal(context);
425  }
426 
427  //Release exclusive access to the LLDP agent context
428  osReleaseMutex(&context->mutex);
429 
430  //Return status code
431  return error;
432 }
433 
434 
435 /**
436  * @brief Remove all IEEE 802.3 specific TLVs with specified subtype
437  * @param[in] context Pointer to the LLDP agent context
438  * @param[in] subtype TLV subtype
439  * @return Error code
440  **/
441 
444 {
445  error_t error;
446  uint_t i;
447  bool_t somethingChangedLocal;
448 
449  //Make sure the LLDP agent context is valid
450  if(context == NULL)
452 
453  //Acquire exclusive access to the LLDP agent context
454  osAcquireMutex(&context->mutex);
455 
456  //Clear flag
457  somethingChangedLocal = FALSE;
458 
459  //Loop through the ports
460  for(i = 0; i < context->numPorts; i++)
461  {
462  //Initialize status code
463  error = NO_ERROR;
464 
465  //Remove all TLVs that match the specified type
466  while(!error)
467  {
468  //Remove one TLV at a time
469  error = lldpDeleteOrgDefTlv(&context->ports[i].txInfo, LLDP_DOT3_OUI,
470  subtype, 0);
471 
472  //Check status code
473  if(!error)
474  {
475  somethingChangedLocal = TRUE;
476  }
477  }
478  }
479 
480  //Any change in the LLDP local system MIB?
481  if(somethingChangedLocal)
482  {
483  //The somethingChangedLocal flag must be set whenever the value of an
484  //object has changed in the local system MIB
485  lldpSomethingChangedLocal(context);
486 
487  //Successful processing
488  error = NO_ERROR;
489  }
490  else
491  {
492  //Report an error
493  error = ERROR_NOT_FOUND;
494  }
495 
496  //Release exclusive access to the LLDP agent context
497  osReleaseMutex(&context->mutex);
498 
499  //Return status code
500  return error;
501 }
502 
503 #endif
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define htonl(value)
Definition: cpu_endian.h:414
#define htons(value)
Definition: cpu_endian.h:413
Debugging facilities.
uint8_t n
uint16_t port
Definition: dns_common.h:267
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_PORT
Definition: error.h:104
@ ERROR_NOT_FOUND
Definition: error.h:147
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
LLDP (Link Layer Discovery Protocol)
#define LldpPortEntry
Definition: lldp.h:44
#define LldpAgentContext
Definition: lldp.h:40
Data logging functions for debugging purpose (LLDP)
error_t lldpDot3SetLocalPowerViaMdi(LldpAgentContext *context, uint_t portIndex, uint8_t mdiPowerSupport, LldpDot3PsePowerPair psePowerPair, LldpDot3PowerClass powerClass, const LldpDot3DllClassExt *dllClassExt, const LldpDot3Type34Ext *type34Ext)
Set power-via-MDI.
error_t lldpDot3SetLocalMaxFrameSize(LldpAgentContext *context, uint_t portIndex, uint16_t maxFrameSize)
Set maximum frame size.
error_t lldpDot3SetLocalMacPhyConfigStatus(LldpAgentContext *context, uint_t portIndex, uint8_t autoNegSupportStatus, uint16_t pmdAutoNegAdvCap, uint16_t operationalMauType)
Set MAC/PHY configuration/status.
Definition: lldp_ext_dot3.c:57
error_t lldpDot3SetLocalPowerViaMdiMeas(LldpAgentContext *context, uint_t portIndex, uint8_t measurements[20], uint16_t psePowerPriceIndex)
Set power-via-MDI measurements.
error_t lldpDot3SetLocalLinkAggregation(LldpAgentContext *context, uint_t portIndex, uint8_t aggregationStatus, uint32_t aggregatedPortId)
Set Link aggregation.
error_t lldpDot3DeleteLocalTlv(LldpAgentContext *context, LldpDot3Subtype subtype)
Remove all IEEE 802.3 specific TLVs with specified subtype.
IEEE 802.3 LLDP extension.
LldpDot3MaxFrameSizeTlv
uint16_t operationalMauType
uint32_t aggregatedPortId
LldpDot3Type34Ext
LldpDot3PsePowerPair
PSE power pair.
uint16_t psePowerPriceIndex
LldpDot3DllClassExt
LldpDot3PowerViaMdiMeasTlv
uint8_t powerClass
LldpDot3LinkAggregationTlv
uint16_t pmdAutoNegAdvCap
LldpDot3PowerClass
power class
uint8_t psePowerPair
LldpDot3PowerViaMdiTlv
LldpDot3MacPhyConfigStatusTlv
LldpDot3Subtype
IEEE 802.3 subtypes.
Definition: lldp_ext_dot3.h:49
@ LLDP_DOT3_SUBTYPE_POWER_VIA_MDI
Power Via MDI.
Definition: lldp_ext_dot3.h:52
@ LLDP_DOT3_SUBTYPE_LINK_AGGREGATION
Link Aggregation.
Definition: lldp_ext_dot3.h:53
@ LLDP_DOT3_SUBTYPE_POWER_VIA_MDI_MEAS
Power Via MDI Measurements.
Definition: lldp_ext_dot3.h:55
@ LLDP_DOT3_SUBTYPE_MAX_FRAME_SIZE
Maximum Frame Size.
Definition: lldp_ext_dot3.h:54
@ LLDP_DOT3_SUBTYPE_MAC_PHY_CONFIG_STATUS
MAC/PHY Configuration/Status.
Definition: lldp_ext_dot3.h:51
void lldpSomethingChangedLocal(LldpAgentContext *context)
Notify LLDP that an object in the LLDP local system MIB has changed.
Definition: lldp_misc.c:806
Helper functions for LLDP.
error_t lldpSetOrgDefTlv(LldpDataUnit *lldpdu, uint32_t oui, uint8_t subtype, uint_t index, const uint8_t *value, size_t length, bool_t replace)
Add or replace an organizationally specific TLV.
Definition: lldp_tlv.c:452
error_t lldpDeleteOrgDefTlv(LldpDataUnit *lldpdu, uint32_t oui, uint8_t subtype, uint_t index)
Remove an organizationally specific TLV from a LLDPDU.
Definition: lldp_tlv.c:719
@ LLDP_DOT3_OUI
IEEE 802.3.
Definition: lldp_tlv.h:189
uint8_t subtype
Definition: lldp_tlv.h:311
TCP/IP stack core.
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.