mld.c
Go to the documentation of this file.
1 /**
2  * @file mld.c
3  * @brief MLD (Multicast Listener Discovery for IPv6)
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  * @section Description
28  *
29  * MLD is used by an IPv6 router to discover the presence of multicast
30  * listeners on its directly attached links, and to discover specifically
31  * which multicast addresses are of interest to those neighboring nodes.
32  * Refer to the following RFCs for complete details:
33  * - RFC 2710: Multicast Listener Discovery (MLD) for IPv6
34  * - RFC 3810: Multicast Listener Discovery Version 2 (MLDv2) for IPv6
35  *
36  * @author Oryx Embedded SARL (www.oryx-embedded.com)
37  * @version 2.4.0
38  **/
39 
40 //Switch to the appropriate trace level
41 #define TRACE_LEVEL MLD_TRACE_LEVEL
42 
43 //Dependencies
44 #include "core/net.h"
45 #include "core/ip.h"
46 #include "ipv6/ipv6.h"
47 #include "ipv6/icmpv6.h"
48 #include "ipv6/mld.h"
49 #include "mibs/ip_mib_module.h"
50 #include "debug.h"
51 
52 //Check TCP/IP stack configuration
53 #if (IPV6_SUPPORT == ENABLED && MLD_SUPPORT == ENABLED)
54 
55 //Tick counter to handle periodic operations
57 
58 
59 /**
60  * @brief MLD initialization
61  * @param[in] interface Underlying network interface
62  * @return Error code
63  **/
64 
66 {
67  //Successful initialization
68  return NO_ERROR;
69 }
70 
71 
72 /**
73  * @brief Start listening to the address on the interface
74  * @param[in] interface Underlying network interface
75  * @param[in] entry IPv6 filter entry identifying the address to listen to
76  * @return Error code
77  **/
78 
80 {
81  //The link-scope all-nodes address (ff02::1) is handled as a special
82  //case. The host starts in Idle Listener state for that address on
83  //every interface and never transitions to another state
85  {
86  //Clear flag
87  entry->flag = FALSE;
88  //Enter the Idle Listener state
90  }
91  else
92  {
93  //Link is up?
94  if(interface->linkState)
95  {
96  //Send a Multicast Listener Report message for the group on the interface
97  mldSendListenerReport(interface, &entry->addr);
98 
99  //Set flag
100  entry->flag = TRUE;
101  //Start timer
103  //Enter the Delaying Listener state
105  }
106  //Link is down?
107  else
108  {
109  //Clear flag
110  entry->flag = FALSE;
111  //Enter the Idle Listener state
113  }
114  }
115 
116  //Successful processing
117  return NO_ERROR;
118 }
119 
120 
121 /**
122  * @brief Stop listening to the address on the interface
123  * @param[in] interface Underlying network interface
124  * @param[in] entry IPv6 filter entry identifying the multicast address to leave
125  * @return Error code
126  **/
127 
129 {
130  //Check link state
131  if(interface->linkState)
132  {
133  //Send a Multicast Listener Done message if the flag is set
134  if(entry->flag)
135  mldSendListenerDone(interface, &entry->addr);
136  }
137 
138  //Switch to the Non-Listener state
139  entry->state = MLD_STATE_NON_LISTENER;
140 
141  //Successful processing
142  return NO_ERROR;
143 }
144 
145 
146 /**
147  * @brief MLD timer handler
148  *
149  * This routine must be periodically called by the TCP/IP stack to
150  * handle MLD related timers
151  *
152  * @param[in] interface Underlying network interface
153  **/
154 
155 void mldTick(NetInterface *interface)
156 {
157  uint_t i;
158  systime_t time;
159  Ipv6FilterEntry *entry;
160 
161  //Get current time
162  time = osGetSystemTime();
163 
164  //Go through the multicast filter table
165  for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++)
166  {
167  //Point to the current entry
168  entry = &interface->ipv6Context.multicastFilter[i];
169 
170  //Valid entry?
171  if(entry->refCount > 0)
172  {
173  //Delaying Listener state?
174  if(entry->state == MLD_STATE_DELAYING_LISTENER)
175  {
176  //Timer expired?
177  if(timeCompare(time, entry->timer) >= 0)
178  {
179  //Send a Multicast Listener Report message
180  mldSendListenerReport(interface, &entry->addr);
181 
182  //Set flag
183  entry->flag = TRUE;
184  //Switch to the Idle Listener state
186  }
187  }
188  }
189  }
190 }
191 
192 
193 /**
194  * @brief Callback function for link change event
195  * @param[in] interface Underlying network interface
196  **/
197 
199 {
200  uint_t i;
201  systime_t time;
202  Ipv6FilterEntry *entry;
203 
204  //Get current time
205  time = osGetSystemTime();
206 
207  //Link up event?
208  if(interface->linkState)
209  {
210  //Go through the multicast filter table
211  for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++)
212  {
213  //Point to the current entry
214  entry = &interface->ipv6Context.multicastFilter[i];
215 
216  //Valid entry?
217  if(entry->refCount > 0)
218  {
219  //The link-scope all-nodes address (ff02::1) is handled as a special
220  //case. The host starts in Idle Listener state for that address on
221  //every interface and never transitions to another state
223  {
224  //Send an unsolicited Multicast Listener Report message for that group
225  mldSendListenerReport(interface, &entry->addr);
226 
227  //Set flag
228  entry->flag = TRUE;
229  //Start timer
231  //Enter the Delaying Listener state
233  }
234  }
235  }
236  }
237  //Link down event?
238  else
239  {
240  //Go through the multicast filter table
241  for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++)
242  {
243  //Point to the current entry
244  entry = &interface->ipv6Context.multicastFilter[i];
245 
246  //Valid entry?
247  if(entry->refCount > 0)
248  {
249  //Clear flag
250  entry->flag = FALSE;
251  //Enter the Idle Listener state
253  }
254  }
255  }
256 }
257 
258 
259 /**
260  * @brief Process incoming Multicast Listener Query message
261  * @param[in] interface Underlying network interface
262  * @param[in] pseudoHeader IPv6 pseudo header
263  * @param[in] buffer Multi-part buffer containing the incoming MLD message
264  * @param[in] offset Offset to the first byte of the MLD message
265  * @param[in] hopLimit Hop Limit field from IPv6 header
266  **/
267 
269  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
270  size_t offset, uint8_t hopLimit)
271 {
272  uint_t i;
273  size_t length;
274  systime_t time;
277  Ipv6FilterEntry *entry;
278 
279  //Retrieve the length of the MLD message
280  length = netBufferGetLength(buffer) - offset;
281 
282  //The message must be at least 24 octets long
283  if(length < sizeof(MldMessage))
284  return;
285 
286  //Point to the beginning of the MLD message
287  message = netBufferAt(buffer, offset);
288  //Sanity check
289  if(message == NULL)
290  return;
291 
292  //Debug message
293  TRACE_INFO("MLD message received (%" PRIuSIZE " bytes)...\r\n", length);
294  //Dump message contents for debugging purpose
296 
297  //Make sure the source address of the message is a valid link-local address
298  if(!ipv6IsLinkLocalUnicastAddr(&pseudoHeader->srcAddr))
299  return;
300 
301  //Check the Hop Limit field
302  if(hopLimit != MLD_HOP_LIMIT)
303  return;
304 
305  //Get current time
306  time = osGetSystemTime();
307 
308  //The Max Resp Delay field specifies the maximum time allowed
309  //before sending a responding report
310  maxRespDelay = message->maxRespDelay * 10;
311 
312  //Go through the multicast filter table
313  for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++)
314  {
315  //Point to the current entry
316  entry = &interface->ipv6Context.multicastFilter[i];
317 
318  //Valid entry?
319  if(entry->refCount > 0)
320  {
321  //The link-scope all-nodes address (ff02::1) is handled as a special
322  //case. The host starts in Idle Listener state for that address on
323  //every interface and never transitions to another state
325  {
326  //A General Query is used to learn which multicast addresses have listeners
327  //on an attached link. A Multicast-Address-Specific Query is used to learn
328  //if a particular multicast address has any listeners on an attached link
329  if(ipv6CompAddr(&message->multicastAddr, &IPV6_UNSPECIFIED_ADDR) ||
330  ipv6CompAddr(&message->multicastAddr, &entry->addr))
331  {
332  //Delaying Listener state?
333  if(entry->state == MLD_STATE_DELAYING_LISTENER)
334  {
335  //The timer has not yet expired?
336  if(timeCompare(time, entry->timer) < 0)
337  {
338  //If a timer for the address is already running, it is reset to
339  //the new random value only if the requested Max Response Delay
340  //is less than the remaining value of the running timer
341  if(maxRespDelay < (entry->timer - time))
342  {
343  //Restart delay timer
345  }
346  }
347  }
348  //Idle Listener state?
349  else if(entry->state == MLD_STATE_IDLE_LISTENER)
350  {
351  //Switch to the Delaying Listener state
353  //Delay the response by a random amount of time
355  }
356  }
357  }
358  }
359  }
360 }
361 
362 
363 /**
364  * @brief Process incoming Multicast Listener Report message
365  * @param[in] interface Underlying network interface
366  * @param[in] pseudoHeader IPv6 pseudo header
367  * @param[in] buffer Multi-part buffer containing the incoming MLD message
368  * @param[in] offset Offset to the first byte of the MLD message
369  * @param[in] hopLimit Hop Limit field from IPv6 header
370  **/
371 
373  const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer,
374  size_t offset, uint8_t hopLimit)
375 {
376  uint_t i;
377  size_t length;
379  Ipv6FilterEntry *entry;
380 
381  //Retrieve the length of the MLD message
382  length = netBufferGetLength(buffer) - offset;
383 
384  //The message must be at least 24 octets long
385  if(length < sizeof(MldMessage))
386  return;
387 
388  //Point to the beginning of the MLD message
389  message = netBufferAt(buffer, offset);
390  //Sanity check
391  if(message == NULL)
392  return;
393 
394  //Debug message
395  TRACE_INFO("MLD message received (%" PRIuSIZE " bytes)...\r\n", length);
396  //Dump message contents for debugging purpose
398 
399  //Make sure the source address of the message is a valid link-local address
400  if(!ipv6IsLinkLocalUnicastAddr(&pseudoHeader->srcAddr))
401  return;
402  //Check the Hop Limit field
403  if(hopLimit != MLD_HOP_LIMIT)
404  return;
405 
406  //Go through the multicast filter table
407  for(i = 0; i < IPV6_MULTICAST_FILTER_SIZE; i++)
408  {
409  //Point to the current entry
410  entry = &interface->ipv6Context.multicastFilter[i];
411 
412  //Valid entry?
413  if(entry->refCount > 0)
414  {
415  //Report messages are ignored for multicast addresses
416  //in the Non-Listener or Idle Listener state
417  if(entry->state == MLD_STATE_DELAYING_LISTENER)
418  {
419  //The Multicast Listener Report message matches the current entry?
420  if(ipv6CompAddr(&message->multicastAddr, &entry->addr))
421  {
422  //Clear flag
423  entry->flag = FALSE;
424  //Switch to the Idle Listener state
426  }
427  }
428  }
429  }
430 }
431 
432 
433 /**
434  * @brief Send Multicast Listener Report message
435  * @param[in] interface Underlying network interface
436  * @param[in] ipAddr IPv6 address specifying the multicast address
437  * @return Error code
438  **/
439 
441 {
442  error_t error;
443  size_t offset;
445  NetBuffer *buffer;
446  Ipv6PseudoHeader pseudoHeader;
447  NetTxAncillary ancillary;
448 
449  //Make sure the specified address is a valid multicast address
451  return ERROR_INVALID_ADDRESS;
452 
453  //The link-scope all-nodes address (ff02::1) is handled as a special
454  //case. The host never sends a report for that address
456  return ERROR_INVALID_ADDRESS;
457 
458  //Allocate a memory buffer to hold a MLD message
459  buffer = ipAllocBuffer(sizeof(MldMessage), &offset);
460  //Failed to allocate memory?
461  if(buffer == NULL)
462  return ERROR_OUT_OF_MEMORY;
463 
464  //Point to the beginning of the MLD message
465  message = netBufferAt(buffer, offset);
466 
467  //Format the Multicast Listener Report message
469  message->code = 0;
470  message->checksum = 0;
471  message->maxRespDelay = 0;
472  message->reserved = 0;
473  message->multicastAddr = *ipAddr;
474 
475  //Format IPv6 pseudo header
476  pseudoHeader.srcAddr = interface->ipv6Context.addrList[0].addr;
477  pseudoHeader.destAddr = *ipAddr;
478  pseudoHeader.length = HTONS(sizeof(MldMessage));
479  pseudoHeader.reserved[0] = 0;
480  pseudoHeader.reserved[1] = 0;
481  pseudoHeader.reserved[2] = 0;
482  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
483 
484  //Message checksum calculation
485  message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
486  sizeof(Ipv6PseudoHeader), buffer, offset, sizeof(MldMessage));
487 
488  //Total number of ICMP messages which this entity attempted to send
489  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
490 
491  //Increment per-message type ICMP counter
492  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[
494 
495  //Debug message
496  TRACE_INFO("Sending MLD message (%" PRIuSIZE " bytes)...\r\n", sizeof(MldMessage));
497  //Dump message contents for debugging purpose
499 
500  //Additional options can be passed to the stack along with the packet
501  ancillary = NET_DEFAULT_TX_ANCILLARY;
502 
503  //All MLD messages must be sent with an IPv6 Hop Limit of 1 (refer to
504  //RFC 3810, section 5)
505  ancillary.ttl = MLD_HOP_LIMIT;
506 
507  //The Multicast Listener Report message is sent to the multicast address
508  //being reported
509  error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset,
510  &ancillary);
511 
512  //Free previously allocated memory
513  netBufferFree(buffer);
514  //Return status code
515  return error;
516 }
517 
518 
519 /**
520  * @brief Send Multicast Listener Done message
521  * @param[in] interface Underlying network interface
522  * @param[in] ipAddr IPv6 address specifying the multicast address being left
523  * @return Error code
524  **/
525 
527 {
528  error_t error;
529  size_t offset;
531  NetBuffer *buffer;
532  Ipv6PseudoHeader pseudoHeader;
533  NetTxAncillary ancillary;
534 
535  //Make sure the specified address is a valid multicast address
537  return ERROR_INVALID_ADDRESS;
538 
539  //The link-scope all-nodes address (ff02::1) is handled as a special
540  //case. The host never sends a report for that address
542  return ERROR_INVALID_ADDRESS;
543 
544  //Allocate a memory buffer to hold a MLD message
545  buffer = ipAllocBuffer(sizeof(MldMessage), &offset);
546  //Failed to allocate memory?
547  if(buffer == NULL)
548  return ERROR_OUT_OF_MEMORY;
549 
550  //Point to the beginning of the MLD message
551  message = netBufferAt(buffer, offset);
552 
553  //Format the Multicast Listener Done message
555  message->code = 0;
556  message->checksum = 0;
557  message->maxRespDelay = 0;
558  message->reserved = 0;
559  message->multicastAddr = *ipAddr;
560 
561  //Format IPv6 pseudo header
562  pseudoHeader.srcAddr = interface->ipv6Context.addrList[0].addr;
563  pseudoHeader.destAddr = IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR;
564  pseudoHeader.length = HTONS(sizeof(MldMessage));
565  pseudoHeader.reserved[0] = 0;
566  pseudoHeader.reserved[1] = 0;
567  pseudoHeader.reserved[2] = 0;
568  pseudoHeader.nextHeader = IPV6_ICMPV6_HEADER;
569 
570  //Message checksum calculation
571  message->checksum = ipCalcUpperLayerChecksumEx(&pseudoHeader,
572  sizeof(Ipv6PseudoHeader), buffer, offset, sizeof(MldMessage));
573 
574  //Total number of ICMP messages which this entity attempted to send
575  IP_MIB_INC_COUNTER32(icmpv6Stats.icmpStatsOutMsgs, 1);
576 
577  //Increment per-message type ICMP counter
578  IP_MIB_INC_COUNTER32(icmpv6MsgStatsTable.icmpMsgStatsOutPkts[
580 
581  //Debug message
582  TRACE_INFO("Sending MLD message (%" PRIuSIZE " bytes)...\r\n", sizeof(MldMessage));
583  //Dump message contents for debugging purpose
585 
586  //Additional options can be passed to the stack along with the packet
587  ancillary = NET_DEFAULT_TX_ANCILLARY;
588 
589  //All MLD messages must be sent with an IPv6 Hop Limit of 1 (refer to
590  //RFC 3810, section 5)
591  ancillary.ttl = MLD_HOP_LIMIT;
592 
593  //The Multicast Listener Done message is sent to the all-routers multicast
594  //address
595  error = ipv6SendDatagram(interface, &pseudoHeader, buffer, offset,
596  &ancillary);
597 
598  //Free previously allocated memory
599  netBufferFree(buffer);
600  //Return status code
601  return error;
602 }
603 
604 
605 /**
606  * @brief Dump MLD message for debugging purpose
607  * @param[in] message Pointer to the MLD message
608  **/
609 
611 {
612  //Dump MLD message
613  TRACE_DEBUG(" Type = %" PRIu8 "\r\n", message->type);
614  TRACE_DEBUG(" Code = %" PRIu8 "\r\n", message->code);
615  TRACE_DEBUG(" Checksum = 0x%04" PRIX16 "\r\n", ntohs(message->checksum));
616  TRACE_DEBUG(" Max Resp Delay = %" PRIu16 "\r\n", message->maxRespDelay);
617  TRACE_DEBUG(" Multicast Address = %s\r\n", ipv6AddrToString(&message->multicastAddr, NULL));
618 }
619 
620 #endif
uint8_t message[]
Definition: chap.h:154
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
#define HTONS(value)
Definition: cpu_endian.h:410
#define ntohs(value)
Definition: cpu_endian.h:421
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint32_t time
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
ICMPv6 (Internet Control Message Protocol Version 6)
@ ICMPV6_TYPE_MULTICAST_LISTENER_DONE_V1
Definition: icmpv6.h:61
@ ICMPV6_TYPE_MULTICAST_LISTENER_REPORT_V1
Definition: icmpv6.h:60
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:744
uint16_t ipCalcUpperLayerChecksumEx(const void *pseudoHeader, size_t pseudoHeaderLen, const NetBuffer *buffer, size_t offset, size_t length)
Calculate IP upper-layer checksum over a multi-part buffer.
Definition: ip.c:719
IPv4 and IPv6 common routines.
IP MIB module.
#define IP_MIB_INC_COUNTER32(name, value)
Definition: ip_mib_module.h:46
Ipv4Addr ipAddr
Definition: ipcp.h:105
const Ipv6Addr IPV6_LINK_LOCAL_ALL_NODES_ADDR
Definition: ipv6.c:73
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2376
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
const Ipv6Addr IPV6_LINK_LOCAL_ALL_ROUTERS_ADDR
Definition: ipv6.c:77
error_t ipv6SendDatagram(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv6 datagram.
Definition: ipv6.c:1667
IPv6 (Internet Protocol Version 6)
Ipv6Addr
Definition: ipv6.h:251
uint8_t hopLimit
Definition: ipv6.h:274
@ IPV6_ICMPV6_HEADER
Definition: ipv6.h:186
#define Ipv6PseudoHeader
Definition: ipv6.h:42
#define ipv6IsMulticastAddr(ipAddr)
Definition: ipv6.h:132
#define ipv6IsLinkLocalUnicastAddr(ipAddr)
Definition: ipv6.h:124
#define IPV6_MULTICAST_FILTER_SIZE
Definition: ipv6.h:100
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:120
error_t mldSendListenerDone(NetInterface *interface, Ipv6Addr *ipAddr)
Send Multicast Listener Done message.
Definition: mld.c:526
error_t mldStartListening(NetInterface *interface, Ipv6FilterEntry *entry)
Start listening to the address on the interface.
Definition: mld.c:79
void mldProcessListenerQuery(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Process incoming Multicast Listener Query message.
Definition: mld.c:268
void mldLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: mld.c:198
void mldTick(NetInterface *interface)
MLD timer handler.
Definition: mld.c:155
void mldProcessListenerReport(NetInterface *interface, const Ipv6PseudoHeader *pseudoHeader, const NetBuffer *buffer, size_t offset, uint8_t hopLimit)
Process incoming Multicast Listener Report message.
Definition: mld.c:372
error_t mldStopListening(NetInterface *interface, Ipv6FilterEntry *entry)
Stop listening to the address on the interface.
Definition: mld.c:128
error_t mldInit(NetInterface *interface)
MLD initialization.
Definition: mld.c:65
systime_t mldTickCounter
Definition: mld.c:56
void mldDumpMessage(const MldMessage *message)
Dump MLD message for debugging purpose.
Definition: mld.c:610
error_t mldSendListenerReport(NetInterface *interface, Ipv6Addr *ipAddr)
Send Multicast Listener Report message.
Definition: mld.c:440
MLD (Multicast Listener Discovery for IPv6)
#define MLD_UNSOLICITED_REPORT_INTERVAL
Definition: mld.h:53
uint16_t maxRespDelay
Definition: mld.h:96
#define MLD_HOP_LIMIT
Definition: mld.h:59
MldMessage
Definition: mld.h:99
@ MLD_STATE_IDLE_LISTENER
Definition: mld.h:75
@ MLD_STATE_DELAYING_LISTENER
Definition: mld.h:74
@ MLD_STATE_NON_LISTENER
Definition: mld.h:73
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:415
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:71
uint32_t netGenerateRandRange(uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net_misc.c:914
#define NetTxAncillary
Definition: net_misc.h:36
#define timeCompare(t1, t2)
Definition: os_port.h:40
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t systime_t
System time.
IPv6 multicast filter entry.
Definition: ipv6.h:448
uint_t state
MLD node state.
Definition: ipv6.h:451
bool_t flag
MLD flag.
Definition: ipv6.h:452
systime_t timer
Delay timer.
Definition: ipv6.h:453
uint_t refCount
Reference count for the current entry.
Definition: ipv6.h:450
Ipv6Addr addr
Multicast address.
Definition: ipv6.h:449
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint8_t length
Definition: tcp.h:368