lldp_ext_dot1.c
Go to the documentation of this file.
1 /**
2  * @file lldp_ext_dot1.c
3  * @brief IEEE 802.1 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_dot1.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 port VLAN ID
48  * @param[in] context Pointer to the LLDP agent context
49  * @param[in] portIndex Port index
50  * @param[in] pvid Port VLAN identifier
51  * @return Error code
52  **/
53 
55  uint_t portIndex, uint16_t pvid)
56 {
57  error_t error;
58  size_t n;
61 
62  //Make sure the LLDP agent context is valid
63  if(context == NULL)
64  {
66  }
67 
68  //Invalid port index?
69  if(portIndex < 1 || portIndex > context->numPorts)
70  {
71  return ERROR_INVALID_PORT;
72  }
73 
74  //Acquire exclusive access to the LLDP agent context
75  osAcquireMutex(&context->mutex);
76 
77  //Point to the port that matches the specified port index
78  port = &context->ports[portIndex - 1];
79 
80  //Point to the buffer where to format the TLV
81  tlv = (LldpDot1PortVlanIdTlv *) context->lldpdu.data;
82 
83  //Set PVID
84  tlv->pvid = htons(pvid);
85 
86  //Calculate the length of the TLV
87  n = sizeof(LldpDot1PortVlanIdTlv);
88 
89  //An LLDPDU should contain no more than one Port VLAN ID TLV (refer
90  //to IEEE 802.1AB-2005, section F.2.2)
91  error = lldpSetOrgDefTlv(&port->txInfo, LLDP_DOT1_OUI,
92  LLDP_DOT1_SUBTYPE_PORT_VLAN_ID, 0, (uint8_t *) tlv, n, TRUE);
93 
94  //Check status code
95  if(!error)
96  {
97  //The somethingChangedLocal flag must be set whenever the value of an
98  //object has changed in the local system MIB
100  }
101 
102  //Release exclusive access to the LLDP agent context
103  osReleaseMutex(&context->mutex);
104 
105  //Return status code
106  return error;
107 }
108 
109 
110 /**
111  * @brief Set port and protocol VLAN ID
112  * @param[in] context Pointer to the LLDP agent context
113  * @param[in] portIndex Port index
114  * @param[in] flags Bit-map indicating the port and protocol VLAN capability
115  * and status
116  * @param[in] ppvid PPVID number for this LAN station
117  * @return Error code
118  **/
119 
121  uint_t portIndex, uint8_t flags, uint16_t ppvid)
122 {
123  error_t error;
124  uint_t k;
125  size_t n;
126  bool_t replace;
129 
130  //Make sure the LLDP agent context is valid
131  if(context == NULL)
132  {
134  }
135 
136  //Invalid port index?
137  if(portIndex < 1 || portIndex > context->numPorts)
138  {
139  return ERROR_INVALID_PORT;
140  }
141 
142  //Acquire exclusive access to the LLDP agent context
143  osAcquireMutex(&context->mutex);
144 
145  //Point to the port that matches the specified port index
146  port = &context->ports[portIndex - 1];
147 
148  //Initialize status code
149  error = NO_ERROR;
150  //Initialize flag
151  replace = FALSE;
152 
153  //If more than one Port And Protocol VLAN ID TLV is defined for a port,
154  //the PPVID value shall be different from any other PPVID defined for the
155  //port (refer to IEEE 802.1AB-2005, section F.3.3)
156  for(k = 0; !error; k++)
157  {
158  //Extract the next Port And Protocol VLAN ID TLV from the local system MIB
159  error = lldpGetOrgDefTlv(&port->txInfo, LLDP_DOT1_OUI,
160  LLDP_DOT1_SUBTYPE_PORT_PROTO_VLAN_ID, k, (const uint8_t **) &tlv, &n);
161 
162  //TLV found?
163  if(!error)
164  {
165  //Sanity check
166  if(n >= sizeof(LldpDot1PortProtoVlanIdTlv))
167  {
168  //Check the value of the PPVID
169  if(ntohs(tlv->ppvid) == ppvid)
170  {
171  //Replace the existing TLV
172  replace = TRUE;
173  break;
174  }
175  else if(ntohs(tlv->ppvid) > ppvid)
176  {
177  //Insert a new TLV
178  break;
179  }
180  else
181  {
182  }
183  }
184  }
185  }
186 
187  //Check status code
188  if(error == NO_ERROR || error == ERROR_NOT_FOUND)
189  {
190  //Point to the buffer where to format the TLV
191  tlv = (LldpDot1PortProtoVlanIdTlv *) context->lldpdu.data;
192 
193  //Set flags
194  tlv->flags = flags;
195  //Set PPVID
196  tlv->ppvid = htons(ppvid);
197 
198  //Calculate the length of the TLV
199  n = sizeof(LldpDot1PortProtoVlanIdTlv);
200 
201  //Set the value of the specified TLV
202  error = lldpSetOrgDefTlv(&port->txInfo, LLDP_DOT1_OUI,
203  LLDP_DOT1_SUBTYPE_PORT_PROTO_VLAN_ID, k, (uint8_t *) tlv, n, replace);
204 
205  //Check status code
206  if(!error)
207  {
208  //The somethingChangedLocal flag must be set whenever the value of an
209  //object has changed in the local system MIB
210  lldpSomethingChangedLocal(context);
211  }
212  }
213 
214  //Release exclusive access to the LLDP agent context
215  osReleaseMutex(&context->mutex);
216 
217  //Return status code
218  return error;
219 }
220 
221 
222 /**
223  * @brief Set VLAN name
224  * @param[in] context Pointer to the LLDP agent context
225  * @param[in] portIndex Port index
226  * @param[in] vlanId VID number associated with the VLAN name
227  * @param[in] vlanName VLAN's name
228  * @return Error code
229  **/
230 
232  uint_t portIndex, uint16_t vlanId, const char_t *vlanName)
233 {
234  error_t error;
235  uint_t k;
236  size_t n;
237  bool_t replace;
239  LldpDot1VlanNameTlv *tlv;
240 
241  //Check parameters
242  if(context == NULL || vlanName == NULL)
243  {
245  }
246 
247  //Invalid port index?
248  if(portIndex < 1 || portIndex > context->numPorts)
249  {
250  return ERROR_INVALID_PORT;
251  }
252 
253  //Acquire exclusive access to the LLDP agent context
254  osAcquireMutex(&context->mutex);
255 
256  //Point to the port that matches the specified port index
257  port = &context->ports[portIndex - 1];
258 
259  //Get the length of the VLAN name
260  n = osStrlen(vlanName);
261 
262  //Check the length of the string
265  {
266  return ERROR_INVALID_LENGTH;
267  }
268 
269  //Initialize status code
270  error = NO_ERROR;
271  //Initialize flag
272  replace = FALSE;
273 
274  //If more than one VLAN Name TLV is defined for a port, the VLAN ID and the
275  //associated VLAN name combination shall be different from any other VLAN ID
276  //and VLAN name combination defined for the port (refer to IEEE 802.1AB-2005,
277  //section F.4.5)
278  for(k = 0; !error; k++)
279  {
280  //Extract the next VLAN Name TLV from the local system MIB
281  error = lldpGetOrgDefTlv(&port->txInfo, LLDP_DOT1_OUI,
282  LLDP_DOT1_SUBTYPE_VLAN_NAME, k, (const uint8_t **) &tlv, &n);
283 
284  //TLV found?
285  if(!error)
286  {
287  //Sanity check
288  if(n >= sizeof(LldpDot1VlanNameTlv))
289  {
290  //Check the value of the VLAN ID
291  if(ntohs(tlv->vlanId) == vlanId)
292  {
293  //Replace the existing TLV
294  replace = TRUE;
295  break;
296  }
297  else if(ntohs(tlv->vlanId) > vlanId)
298  {
299  //Insert a new TLV
300  break;
301  }
302  else
303  {
304  }
305  }
306  }
307  }
308 
309  //Check status code
310  if(error == NO_ERROR || error == ERROR_NOT_FOUND)
311  {
312  //Point to the buffer where to format the TLV
313  tlv = (LldpDot1VlanNameTlv *) context->lldpdu.data;
314 
315  //Set VLAN ID
316  tlv->vlanId = htons(vlanId);
317  //Set VLAN name length
318  tlv->vlanNameLen = n;
319  //Copy VLAN name
320  osMemcpy(tlv->vlanName, vlanName, n);
321 
322  //Calculate the length of the TLV
323  n += sizeof(LldpDot1VlanNameTlv);
324 
325  //Set the value of the specified TLV
326  error = lldpSetOrgDefTlv(&port->txInfo, LLDP_DOT1_OUI,
327  LLDP_DOT1_SUBTYPE_VLAN_NAME, k, (uint8_t *) tlv, n, replace);
328 
329  //Check status code
330  if(!error)
331  {
332  //The somethingChangedLocal flag must be set whenever the value of an
333  //object has changed in the local system MIB
334  lldpSomethingChangedLocal(context);
335  }
336  }
337 
338  //Release exclusive access to the LLDP agent context
339  osReleaseMutex(&context->mutex);
340 
341  //Return status code
342  return error;
343 }
344 
345 
346 /**
347  * @brief Set protocol identity
348  * @param[in] context Pointer to the LLDP agent context
349  * @param[in] portIndex Port index
350  * @param[in] protocolId First n octets of the protocol after the layer 2
351  * addresses
352  * @param[in] protocolIdLen Length of the protocol identity, in bytes
353  * @return Error code
354  **/
355 
357  uint_t portIndex, const uint8_t *protocolId, size_t protocolIdLen)
358 {
359  error_t error;
360  uint_t k;
361  size_t n;
362  bool_t replace;
365 
366  //Check parameters
367  if(context == NULL || protocolId == NULL)
368  {
370  }
371 
372  //Check the length of the protocol identity
373  if(protocolIdLen < LLDP_DOT1_MIN_PROTOCOL_ID_LEN ||
374  protocolIdLen > LLDP_DOT1_MAX_PROTOCOL_ID_LEN)
375  {
376  return ERROR_INVALID_LENGTH;
377  }
378 
379  //Invalid port index?
380  if(portIndex < 1 || portIndex > context->numPorts)
381  {
382  return ERROR_INVALID_PORT;
383  }
384 
385  //Acquire exclusive access to the LLDP agent context
386  osAcquireMutex(&context->mutex);
387 
388  //Point to the port that matches the specified port index
389  port = &context->ports[portIndex - 1];
390 
391  //Initialize status code
392  error = NO_ERROR;
393  //Initialize flag
394  replace = FALSE;
395 
396  //If more than one Protocol Identity TLV is defined for a port, the protocol
397  //identity field value shall be different from any other Protocol Identity
398  //TLV defined for the port (refer to IEEE 802.1AB-2005, section F.5.4)
399  for(k = 0; !error; k++)
400  {
401  //Extract the next Protocol Identity TLV from the local system MIB
402  error = lldpGetOrgDefTlv(&port->txInfo, LLDP_DOT1_OUI,
403  LLDP_DOT1_SUBTYPE_PROTOCOL_ID, k, (const uint8_t **) &tlv, &n);
404 
405  //TLV found?
406  if(!error)
407  {
408  //Sanity check
409  if(n >= sizeof(LldpDot1ProtocolIdTlv))
410  {
411  //Compare protocol identity fields
412  if(n == (protocolIdLen + sizeof(LldpDot1ProtocolIdTlv)) &&
413  osMemcmp(tlv->protocolId, protocolId, n) == 0)
414  {
415  //Replace the existing TLV
416  replace = TRUE;
417  break;
418  }
419  }
420  }
421  }
422 
423  //Check status code
424  if(error == NO_ERROR || error == ERROR_NOT_FOUND)
425  {
426  //Point to the buffer where to format the TLV
427  tlv = (LldpDot1ProtocolIdTlv *) context->lldpdu.data;
428 
429  //Set protocol identity length
430  tlv->protocolIdLen = protocolIdLen;
431  //Copy protocol identity
432  osMemcpy(tlv->protocolId, protocolId, protocolIdLen);
433 
434  //Calculate the length of the TLV
435  n = sizeof(LldpDot1ProtocolIdTlv) + protocolIdLen;
436 
437  //Set the value of the specified TLV
438  error = lldpSetOrgDefTlv(&port->txInfo, LLDP_DOT1_OUI,
439  LLDP_DOT1_SUBTYPE_PROTOCOL_ID, k, (uint8_t *) tlv, n, replace);
440 
441  //Check status code
442  if(!error)
443  {
444  //The somethingChangedLocal flag must be set whenever the value of an
445  //object has changed in the local system MIB
446  lldpSomethingChangedLocal(context);
447  }
448  }
449 
450  //Release exclusive access to the LLDP agent context
451  osReleaseMutex(&context->mutex);
452 
453  //Return status code
454  return error;
455 }
456 
457 
458 /**
459  * @brief Remove all IEEE 802.1 specific TLVs with specified subtype
460  * @param[in] context Pointer to the LLDP agent context
461  * @param[in] subtype TLV subtype
462  * @return Error code
463  **/
464 
467 {
468  error_t error;
469  uint_t i;
470  bool_t somethingChangedLocal;
471 
472  //Make sure the LLDP agent context is valid
473  if(context == NULL)
475 
476  //Acquire exclusive access to the LLDP agent context
477  osAcquireMutex(&context->mutex);
478 
479  //Clear flag
480  somethingChangedLocal = FALSE;
481 
482  //Loop through the ports
483  for(i = 0; i < context->numPorts; i++)
484  {
485  //Initialize status code
486  error = NO_ERROR;
487 
488  //Remove all TLVs that match the specified type
489  while(!error)
490  {
491  //Remove one TLV at a time
492  error = lldpDeleteOrgDefTlv(&context->ports[i].txInfo, LLDP_DOT1_OUI,
493  subtype, 0);
494 
495  //Check status code
496  if(!error)
497  {
498  somethingChangedLocal = TRUE;
499  }
500  }
501  }
502 
503  //Any change in the LLDP local system MIB?
504  if(somethingChangedLocal)
505  {
506  //The somethingChangedLocal flag must be set whenever the value of an
507  //object has changed in the local system MIB
508  lldpSomethingChangedLocal(context);
509 
510  //Successful processing
511  error = NO_ERROR;
512  }
513  else
514  {
515  //Report an error
516  error = ERROR_NOT_FOUND;
517  }
518 
519  //Release exclusive access to the LLDP agent context
520  osReleaseMutex(&context->mutex);
521 
522  //Return status code
523  return error;
524 }
525 
526 #endif
unsigned int uint_t
Definition: compiler_port.h:50
char char_t
Definition: compiler_port.h:48
int bool_t
Definition: compiler_port.h:53
#define htons(value)
Definition: cpu_endian.h:413
#define ntohs(value)
Definition: cpu_endian.h:421
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_LENGTH
Definition: error.h:111
@ 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 lldpDot1SetLocalPortProtoVlanId(LldpAgentContext *context, uint_t portIndex, uint8_t flags, uint16_t ppvid)
Set port and protocol VLAN ID.
error_t lldpDot1SetLocalVlanName(LldpAgentContext *context, uint_t portIndex, uint16_t vlanId, const char_t *vlanName)
Set VLAN name.
error_t lldpDot1SetLocalPortVlanId(LldpAgentContext *context, uint_t portIndex, uint16_t pvid)
Set port VLAN ID.
Definition: lldp_ext_dot1.c:54
error_t lldpDot1SetLocalProtocolId(LldpAgentContext *context, uint_t portIndex, const uint8_t *protocolId, size_t protocolIdLen)
Set protocol identity.
error_t lldpDot1DeleteLocalTlv(LldpAgentContext *context, LldpDot1Subtype subtype)
Remove all IEEE 802.1 specific TLVs with specified subtype.
IEEE 802.1 LLDP extension.
#define LLDP_DOT1_MIN_VLAN_NAME_LEN
Definition: lldp_ext_dot1.h:39
uint8_t protocolId[]
uint16_t ppvid
char_t vlanName[]
LldpDot1PortVlanIdTlv
Definition: lldp_ext_dot1.h:95
LldpDot1ProtocolIdTlv
#define LLDP_DOT1_MAX_PROTOCOL_ID_LEN
Definition: lldp_ext_dot1.h:46
LldpDot1VlanNameTlv
LldpDot1Subtype
IEEE 802.1 subtypes.
Definition: lldp_ext_dot1.h:59
@ LLDP_DOT1_SUBTYPE_PROTOCOL_ID
Protocol Identity.
Definition: lldp_ext_dot1.h:64
@ LLDP_DOT1_SUBTYPE_VLAN_NAME
VLAN Name.
Definition: lldp_ext_dot1.h:63
@ LLDP_DOT1_SUBTYPE_PORT_PROTO_VLAN_ID
Port And Protocol VLAN ID.
Definition: lldp_ext_dot1.h:62
@ LLDP_DOT1_SUBTYPE_PORT_VLAN_ID
Port VLAN ID.
Definition: lldp_ext_dot1.h:61
#define LLDP_DOT1_MAX_VLAN_NAME_LEN
Definition: lldp_ext_dot1.h:41
LldpDot1PortProtoVlanIdTlv
#define LLDP_DOT1_MIN_PROTOCOL_ID_LEN
Definition: lldp_ext_dot1.h:44
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 lldpGetOrgDefTlv(LldpDataUnit *lldpdu, uint32_t oui, uint8_t subtype, uint_t index, const uint8_t **value, size_t *length)
Search an LLDPDU for an organizationally specific TLV.
Definition: lldp_tlv.c:651
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_DOT1_OUI
IEEE 802.1.
Definition: lldp_tlv.h:188
uint8_t subtype
Definition: lldp_tlv.h:311
TCP/IP stack core.
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define osMemcmp(p1, p2, length)
Definition: os_port.h:153
#define osStrlen(s)
Definition: os_port.h:165
#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.
uint8_t flags
Definition: tcp.h:351