ethernet.c
Go to the documentation of this file.
1 /**
2  * @file ethernet.c
3  * @brief Ethernet
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL ETH_TRACE_LEVEL
31 
32 //Dependencies
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "core/net.h"
37 #include "core/nic.h"
38 #include "core/ethernet.h"
39 #include "core/socket.h"
40 #include "core/raw_socket.h"
41 #include "core/tcp_timer.h"
42 #include "ipv4/arp.h"
43 #include "ipv4/ipv4.h"
44 #include "ipv6/ipv6.h"
45 #include "mibs/mib2_module.h"
46 #include "mibs/if_mib_module.h"
47 #include "debug.h"
48 
49 //Check TCP/IP stack configuration
50 #if (ETH_SUPPORT == ENABLED)
51 
52 //Unspecified MAC address
53 const MacAddr MAC_UNSPECIFIED_ADDR = {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}};
54 //Broadcast MAC address
55 const MacAddr MAC_BROADCAST_ADDR = {{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}};
56 
57 //Padding bytes
58 const uint8_t ethPadding[64] =
59 {
60  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
68 };
69 
70 //A lookup table can be used to speed up CRC calculation
71 #if (ETH_FAST_CRC_SUPPORT == ENABLED)
72 
73 static const uint32_t crc32Table[256] =
74 {
75  0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
76  0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
77  0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
78  0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
79  0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
80  0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
81  0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
82  0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
83  0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
84  0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
85  0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
86  0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
87  0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
88  0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
89  0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
90  0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
91  0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
92  0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
93  0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
94  0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
95  0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
96  0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
97  0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
98  0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
99  0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
100  0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
101  0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
102  0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
103  0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
104  0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
105  0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
106  0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
107  0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
108  0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
109  0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
110  0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
111  0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
112  0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
113  0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
114  0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
115  0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
116  0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
117  0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
118  0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
119  0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
120  0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
121  0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
122  0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
123  0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
124  0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
125  0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
126  0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
127  0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
128  0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
129  0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
130  0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
131  0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
132  0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
133  0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
134  0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
135  0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
136  0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
137  0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
138  0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
139 };
140 
141 #endif
142 
143 
144 /**
145  * @brief Ethernet related initialization
146  * @param[in] interface Underlying network interface
147  * @return Error code
148  **/
149 
151 {
152  //Clear the MAC filter table contents
153  memset(interface->macAddrFilter, 0,
154  sizeof(interface->macAddrFilter));
155 
156  //Successful initialization
157  return NO_ERROR;
158 }
159 
160 
161 /**
162  * @brief Process an incoming Ethernet frame
163  * @param[in] interface Underlying network interface
164  * @param[in] frame Incoming Ethernet frame to process
165  * @param[in] length Total frame length
166  **/
167 
168 void ethProcessFrame(NetInterface *interface, uint8_t *frame, size_t length)
169 {
170  error_t error;
171  uint32_t crc;
172  uint16_t type;
173  uint8_t *data;
174  EthHeader *header;
175 #if (ETH_VMAN_SUPPORT == ENABLED)
176  uint16_t vmanId = 0;
177  VlanTag *vmanTag = NULL;
178 #endif
179 #if (IPV6_SUPPORT == ENABLED)
180  NetBuffer1 buffer;
181 #endif
182 
183  //Initialize status code
184  error = NO_ERROR;
185 
186  //Start of exception handling block
187  do
188  {
189  //Check whether the CRC is included in the received frame
190  if(!interface->nicDriver->autoCrcStrip)
191  {
192  //Malformed Ethernet frame?
193  if(length < (sizeof(EthHeader) + ETH_CRC_SIZE))
194  {
195  //Drop the received frame
196  error = ERROR_INVALID_LENGTH;
197  break;
198  }
199 
200  //CRC verification not supported by hardware?
201  if(!interface->nicDriver->autoCrcVerif)
202  {
203  //The value of the residue is 0x2144DF1C when no CRC errors are detected
204  if(ethCalcCrc(frame, length) != 0x2144DF1C)
205  {
206  //Drop the received frame
207  error = ERROR_WRONG_CHECKSUM;
208  break;
209  }
210  }
211 
212  //Retrieve CRC value
213  crc = LOAD32BE(frame + length - ETH_CRC_SIZE);
214  //Reseed the pseudo-random number generator
215  netInitRand(crc);
216 
217  //Strip CRC field from Ethernet frame
218  length -= ETH_CRC_SIZE;
219  }
220 
221 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
222  //Ethernet port multiplication using VLAN or tail tagging?
223  if(interface->port != 0)
224  {
225  //Sanity check
226  if(interface->phyDriver != NULL &&
227  interface->phyDriver->tagFrame != NULL)
228  {
229  //Decode VLAN or tail tag
230  error = interface->phyDriver->untagFrame(&interface, &frame,
231  &length);
232  //Any error to report?
233  if(error)
234  break;
235  }
236  }
237 #endif
238 
239  //Position to the beginning of the frame
240  header = (EthHeader *) frame;
241 
242  //Total number of octets received on the interface
243  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifInOctets, length);
244  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInOctets, length);
245  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCInOctets, length);
246 
247  //Malformed Ethernet frame?
248  if(length < sizeof(EthHeader))
249  {
250  //Drop the received frame
251  error = ERROR_INVALID_LENGTH;
252  break;
253  }
254 
255  //Debug message
256  TRACE_DEBUG("Ethernet frame received (%" PRIuSIZE " bytes)...\r\n", length);
257  //Dump Ethernet header contents for debugging purpose
258  ethDumpHeader(header);
259 
260 #if defined(ETH_FRAME_FORWARD_HOOK)
261  ETH_FRAME_FORWARD_HOOK(interface, header, length);
262 #endif
263 
264 #if (RAW_SOCKET_SUPPORT == ENABLED)
265  //Frame filtering based on destination MAC address
266  if(!ethCheckDestAddr(interface, &header->destAddr))
267  {
268  //Allow raw sockets to process Ethernet packets
269  rawSocketProcessEthPacket(interface, header, length);
270  }
271 #endif
272 
273  //Retrieve the value of the EtherType field
274  type = ntohs(header->type);
275 
276  //Point to the data payload
277  data = header->data;
278  //Calculate the length of the data payload
279  length -= sizeof(EthHeader);
280 
281 #if (ETH_VLAN_SUPPORT == ENABLED)
282 #if (ETH_VMAN_SUPPORT == ENABLED)
283  //VMAN tag found?
284  if(type == ETH_TYPE_VMAN)
285  {
286  //Malformed Ethernet frame?
287  if(length < sizeof(VlanTag))
288  {
289  //Drop the received frame
290  error = ERROR_INVALID_LENGTH;
291  break;
292  }
293 
294  //Point to the VMAN tag
295  vmanTag = (VlanTag *) data;
296 
297  //The VMAN identifier is encoded in a 12-bit field
298  vmanId = ntohs(vmanTag->tci) & VLAN_VID_MASK;
299  //The EtherType field indicates which protocol is encapsulated in the payload
300  type = ntohs(vmanTag->type);
301 
302  //Advance over the VMAN tag
303  data += sizeof(VlanTag);
304  length -= sizeof(VlanTag);
305  }
306 #endif
307 
308  //VLAN tag found?
309  if(type == ETH_TYPE_VLAN)
310  {
311  uint_t i;
312  uint16_t vlanId;
313  VlanTag *vlanTag;
314 
315  //Malformed Ethernet frame?
316  if(length < sizeof(VlanTag))
317  {
318  //Drop the received frame
319  error = ERROR_INVALID_LENGTH;
320  break;
321  }
322 
323  //Point to the VLAN tag
324  vlanTag = (VlanTag *) data;
325 
326  //The VLAN identifier is encoded in a 12-bit field
327  vlanId = ntohs(vlanTag->tci) & VLAN_VID_MASK;
328  //The EtherType field indicates which protocol is encapsulated in the payload
329  type = ntohs(vlanTag->type);
330 
331  //Advance over the VLAN tag
332  data += sizeof(VlanTag);
333  length -= sizeof(VlanTag);
334 
335  //802.1q allows a single physical interface to be bound to multiple
336  //virtual interfaces
337  for(i = 0; i < NET_INTERFACE_COUNT; i++)
338  {
339  //Check whether the current virtual interface is attached to the
340  //physical interface where the packet was received
341  if(netInterface[i].parent == interface || &netInterface[i] == interface)
342  {
343  //Check VLAN identifier
344  if(netInterface[i].vlanId != 0 && netInterface[i].vlanId == vlanId)
345  {
346 #if (ETH_VMAN_SUPPORT == ENABLED)
347  //Check VMAN identifier
348  if(vmanTag != NULL)
349  {
350  if(netInterface[i].vmanId != 0 && netInterface[i].vmanId == vmanId)
351  {
352  //Forward the packet to the relevant virtual interface
353  interface = &netInterface[i];
354  break;
355  }
356  }
357  else
358  {
359  if(netInterface[i].vmanId == 0)
360  {
361  //Forward the packet to the relevant virtual interface
362  interface = &netInterface[i];
363  break;
364  }
365  }
366 #else
367  //Forward the packet to the relevant virtual interface
368  interface = &netInterface[i];
369  break;
370 #endif
371  }
372  }
373  }
374 
375  //Drop incoming VLAN-tagged frames with unknown VLAN identifier
376  if(i >= NET_INTERFACE_COUNT)
377  {
378  //Drop the received frame
379  error = ERROR_WRONG_IDENTIFIER;
380  break;
381  }
382  }
383  else
384  {
385 #if (ETH_VMAN_SUPPORT == ENABLED)
386  //Sanity check
387  if(vmanTag != NULL)
388  {
389  //Drop the received frame
390  error = ERROR_WRONG_IDENTIFIER;
391  break;
392  }
393 #endif
394  //If the interface is configured to accept VLAN-tagged frames, then
395  //drop the incoming Ethernet frame
396  if(interface->vlanId != 0)
397  {
398  //Drop the received frame
399  error = ERROR_WRONG_IDENTIFIER;
400  break;
401  }
402  }
403 #endif
404 
405  //Frame filtering based on destination MAC address
406  if(ethCheckDestAddr(interface, &header->destAddr))
407  {
408  //Drop the received frame
409  error = ERROR_INVALID_ADDRESS;
410  break;
411  }
412 
413  //Update Ethernet statistics
414  ethUpdateInStats(interface, &header->destAddr);
415 
416  //Check Ethernet type field
417  switch(type)
418  {
419 #if (IPV4_SUPPORT == ENABLED)
420  //ARP packet received?
421  case ETH_TYPE_ARP:
422  //Process incoming ARP packet
423  arpProcessPacket(interface, (ArpPacket *) data, length);
424  break;
425  //IPv4 packet received?
426  case ETH_TYPE_IPV4:
427  //Process incoming IPv4 packet
428  ipv4ProcessPacket(interface, (Ipv4Header *) data, length);
429  break;
430 #endif
431 
432 #if (IPV6_SUPPORT == ENABLED)
433  //IPv6 packet received?
434  case ETH_TYPE_IPV6:
435  //The incoming Ethernet frame fits in a single chunk
436  buffer.chunkCount = 1;
437  buffer.maxChunkCount = 1;
438  buffer.chunk[0].address = data;
439  buffer.chunk[0].length = (uint16_t) length;
440  buffer.chunk[0].size = 0;
441 
442  //Process incoming IPv6 packet
443  ipv6ProcessPacket(interface, (NetBuffer *) &buffer, 0);
444  break;
445 #endif
446 
447  //Unknown packet received?
448  default:
449  //Drop the received frame
450  error = ERROR_INVALID_PROTOCOL;
451  break;
452  }
453 
454  //End of exception handling block
455  } while(0);
456 
457  //Invalid frame received?
458  if(error)
459  {
460  //Update Ethernet statistics
461  ethUpdateErrorStats(interface, error);
462  }
463 }
464 
465 
466 /**
467  * @brief Send an Ethernet frame
468  * @param[in] interface Underlying network interface
469  * @param[in] destAddr MAC address of the destination host
470  * @param[in] buffer Multi-part buffer containing the payload
471  * @param[in] offset Offset to the first payload byte
472  * @param[in] type Ethernet type
473  * @return Error code
474  **/
475 
477  NetBuffer *buffer, size_t offset, uint16_t type)
478 {
479  error_t error;
480  uint32_t crc;
481  size_t length;
482  MacAddr *srcAddr;
483  EthHeader *header;
484 
485 #if (ETH_VLAN_SUPPORT == ENABLED)
486  //Valid VLAN identifier assigned to the interface?
487  if(interface->vlanId != 0)
488  {
489  VlanTag *vlanTag;
490 
491  //Is there enough space for the VLAN tag?
492  if(offset < sizeof(VlanTag))
494 
495  //Make room for the VLAN tag
496  offset -= sizeof(VlanTag);
497  //Point to the VLAN tag
498  vlanTag = netBufferAt(buffer, offset);
499 
500  //The VLAN identifier is encoded in a 12-bit field
501  vlanTag->tci = htons(interface->vlanId & VLAN_VID_MASK);
502  //The EtherType field indicates which protocol is encapsulated in the payload
503  vlanTag->type = htons(type);
504 
505  //A distinct EtherType has been allocated for use in the TPID field
507 
508 #if (ETH_VMAN_SUPPORT == ENABLED)
509  //Valid VMAN identifier assigned to the interface?
510  if(interface->vmanId != 0)
511  {
512  //Is there enough space for the VMAN tag?
513  if(offset < sizeof(VlanTag))
515 
516  //Make room for the VMAN tag
517  offset -= sizeof(VlanTag);
518  //Point to the VMAN tag
519  vlanTag = netBufferAt(buffer, offset);
520 
521  //The VMAN identifier is encoded in a 12-bit field
522  vlanTag->tci = htons(interface->vmanId & VLAN_VID_MASK);
523  //The EtherType field indicates which protocol is encapsulated in the payload
524  vlanTag->type = htons(type);
525 
526  //A distinct EtherType has been allocated for use in the TPID field
528  }
529 #endif
530 
531  //Forward the frame to the network interface on top of which VLAN runs
532  interface = nicGetLogicalInterface(interface);
533  }
534 #endif
535 
536  //Get source MAC address
537  srcAddr = &interface->macAddr;
538 
539 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
540  //Ethernet port multiplication using VLAN or tail tagging?
541  if(interface->port != 0)
542  {
543  NetInterface *physicalInterface;
544 
545  //Point to the physical interface
546  physicalInterface = nicGetPhysicalInterface(interface);
547 
548  //Sanity check
549  if(physicalInterface->phyDriver != NULL &&
550  physicalInterface->phyDriver->tagFrame != NULL)
551  {
552  //Add VLAN or tail tag
553  error = physicalInterface->phyDriver->tagFrame(&interface,
554  buffer, &offset, &type);
555  //Any error to report?
556  if(error)
557  return error;
558  }
559  }
560 #endif
561 
562  //Is there enough space for the Ethernet header?
563  if(offset < sizeof(EthHeader))
565 
566  //Make room for the Ethernet header
567  offset -= sizeof(EthHeader);
568  //Retrieve the length of the frame
569  length = netBufferGetLength(buffer) - offset;
570 
571  //Position to the beginning of the frame
572  header = netBufferAt(buffer, offset);
573 
574  //Format Ethernet header
575  header->destAddr = *destAddr;
576  header->srcAddr = *srcAddr;
577  header->type = htons(type);
578 
579  //Valid NIC driver?
580  if(interface->nicDriver != NULL)
581  {
582  //Automatic padding not supported by hardware?
583  if(!interface->nicDriver->autoPadding)
584  {
585  //The host controller should manually add padding to the packet before
586  //transmitting it
587  error = ethPadFrame(buffer, &length);
588  //Any error to report?
589  if(error)
590  return error;
591  }
592 
593  //CRC calculation not supported by hardware?
594  if(!interface->nicDriver->autoCrcCalc)
595  {
596  //Compute CRC over the header and payload
597  crc = ethCalcCrcEx(buffer, offset, length);
598  //Convert from host byte order to little-endian byte order
599  crc = htole32(crc);
600 
601  //Append the calculated CRC value
602  error = netBufferAppend(buffer, &crc, sizeof(crc));
603  //Any error to report?
604  if(error)
605  return error;
606 
607  //Adjust frame length
608  length += sizeof(crc);
609  }
610  }
611 
612  //Update Ethernet statistics
613  ethUpdateOutStats(interface, &header->destAddr, length);
614 
615  //Debug message
616  TRACE_DEBUG("Sending Ethernet frame (%" PRIuSIZE " bytes)...\r\n", length);
617  //Dump Ethernet header contents for debugging purpose
618  ethDumpHeader(header);
619 
620  //Send the resulting packet over the specified link
621  error = nicSendPacket(interface, buffer, offset);
622  //Return status code
623  return error;
624 }
625 
626 
627 /**
628  * @brief Ethernet frame padding
629  * @param[in] buffer Multi-part buffer containing the Ethernet frame
630  * @param[in,out] length Length of the Ethernet frame, in bytes
631  * @return Error code
632  **/
633 
635 {
636  error_t error;
637  size_t n;
638 
639  //Ethernet frames have a minimum length of 64 byte
641  {
642  //Add padding as necessary
644 
645  //Append padding bytes
646  error = netBufferAppend(buffer, ethPadding, n);
647 
648  //Check status code
649  if(!error)
650  {
651  //Adjust frame length
652  *length += n;
653  }
654  }
655  else
656  {
657  //No padding needed
658  error = NO_ERROR;
659  }
660 
661  //Return status code
662  return error;
663 }
664 
665 
666 /**
667  * @brief Destination MAC address filtering
668  * @param[in] interface Underlying network interface
669  * @param[in] macAddr Destination MAC address to be checked
670  * @return Error code
671  **/
672 
673 error_t ethCheckDestAddr(NetInterface *interface, const MacAddr *macAddr)
674 {
675  error_t error;
676  uint_t i;
677  MacFilterEntry *entry;
678  NetInterface *logicalInterface;
679 
680  //Filter out any invalid addresses
681  error = ERROR_INVALID_ADDRESS;
682 
683  //Point to the logical interface
684  logicalInterface = nicGetLogicalInterface(interface);
685 
686  //Interface MAC address?
687  if(macCompAddr(macAddr, &logicalInterface->macAddr))
688  {
689  error = NO_ERROR;
690  }
691  //Broadcast address?
692  else if(macCompAddr(macAddr, &MAC_BROADCAST_ADDR))
693  {
694  error = NO_ERROR;
695  }
696  //Multicast address?
697  else if(macIsMulticastAddr(macAddr))
698  {
699  //Go through the MAC filter table
700  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
701  {
702  //Point to the current entry
703  entry = &interface->macAddrFilter[i];
704 
705  //Valid entry?
706  if(entry->refCount > 0)
707  {
708  //Check whether the destination MAC address matches
709  //a relevant multicast address
710  if(macCompAddr(&entry->addr, macAddr))
711  {
712  //The MAC address is acceptable
713  error = NO_ERROR;
714  //Stop immediately
715  break;
716  }
717  }
718  }
719  }
720 
721  //Return status code
722  return error;
723 }
724 
725 
726 /**
727  * @brief Add a unicast/multicast address to the MAC filter table
728  * @param[in] interface Underlying network interface
729  * @param[in] macAddr MAC address to accept
730  * @return Error code
731  **/
732 
733 error_t ethAcceptMacAddr(NetInterface *interface, const MacAddr *macAddr)
734 {
735  uint_t i;
736  MacFilterEntry *entry;
737  MacFilterEntry *firstFreeEntry;
738 
739  //Keep track of the first free entry
740  firstFreeEntry = NULL;
741 
742  //Go through the MAC filter table
743  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
744  {
745  //Point to the current entry
746  entry = &interface->macAddrFilter[i];
747 
748  //Valid entry?
749  if(entry->refCount > 0)
750  {
751  //Check whether the table already contains the specified MAC address
752  if(macCompAddr(&entry->addr, macAddr))
753  {
754  //Increment the reference count
755  entry->refCount++;
756  //No error to report
757  return NO_ERROR;
758  }
759  }
760  else
761  {
762  //Keep track of the first free entry
763  if(firstFreeEntry == NULL)
764  firstFreeEntry = entry;
765  }
766  }
767 
768  //Check whether the multicast filter table is full
769  if(firstFreeEntry == NULL)
770  {
771  //A new entry cannot be added
772  return ERROR_FAILURE;
773  }
774 
775  //Add a new entry to the table
776  firstFreeEntry->addr = *macAddr;
777  //Initialize the reference count
778  firstFreeEntry->refCount = 1;
779 
780  //Force the network interface controller to add the current
781  //entry to its MAC filter table
782  firstFreeEntry->addFlag = TRUE;
783  firstFreeEntry->deleteFlag = FALSE;
784 
785  //Update the MAC filter table
786  nicUpdateMacAddrFilter(interface);
787 
788  //Clear the flag
789  firstFreeEntry->addFlag = FALSE;
790 
791  //No error to report
792  return NO_ERROR;
793 }
794 
795 
796 /**
797  * @brief Remove a unicast/multicast address from the MAC filter table
798  * @param[in] interface Underlying network interface
799  * @param[in] macAddr MAC address to drop
800  * @return Error code
801  **/
802 
803 error_t ethDropMacAddr(NetInterface *interface, const MacAddr *macAddr)
804 {
805  uint_t i;
806  MacFilterEntry *entry;
807 
808  //Go through the MAC filter table
809  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
810  {
811  //Point to the current entry
812  entry = &interface->macAddrFilter[i];
813 
814  //Valid entry?
815  if(entry->refCount > 0)
816  {
817  //Specified MAC address found?
818  if(macCompAddr(&entry->addr, macAddr))
819  {
820  //Decrement the reference count
821  entry->refCount--;
822 
823  //Remove the entry if the reference count drops to zero
824  if(entry->refCount == 0)
825  {
826  //Force the network interface controller to remove the current
827  //entry from its MAC filter table
828  entry->deleteFlag = TRUE;
829 
830  //Update the MAC filter table
831  nicUpdateMacAddrFilter(interface);
832 
833  //Clear the flag
834  entry->deleteFlag = FALSE;
835  //Remove the multicast address from the list
836  entry->addr = MAC_UNSPECIFIED_ADDR;
837  }
838 
839  //No error to report
840  return NO_ERROR;
841  }
842  }
843  }
844 
845  //The specified MAC address does not exist
847 }
848 
849 
850 /**
851  * @brief Update Ethernet input statistics
852  * @param[in] interface Underlying network interface
853  * @param[in] destMacAddr Destination MAC address
854  **/
855 
856 void ethUpdateInStats(NetInterface *interface, const MacAddr *destMacAddr)
857 {
858  //Check whether the destination address is a unicast, broadcast or multicast address
859  if(macCompAddr(destMacAddr, &MAC_BROADCAST_ADDR))
860  {
861  //Number of non-unicast packets delivered to a higher-layer protocol
862  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifInNUcastPkts, 1);
863 
864  //Number of broadcast packets delivered to a higher-layer protocol
865  IF_MIB_INC_COUNTER32(ifXTable[interface->index].ifInBroadcastPkts, 1);
866  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCInBroadcastPkts, 1);
867  }
868  else if(macIsMulticastAddr(destMacAddr))
869  {
870  //Number of non-unicast packets delivered to a higher-layer protocol
871  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifInNUcastPkts, 1);
872 
873  //Number of multicast packets delivered to a higher-layer protocol
874  IF_MIB_INC_COUNTER32(ifXTable[interface->index].ifInMulticastPkts, 1);
875  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCInMulticastPkts, 1);
876  }
877  else
878  {
879  //Number of unicast packets delivered to a higher-layer protocol
880  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifInUcastPkts, 1);
881  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInUcastPkts, 1);
882  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCInUcastPkts, 1);
883  }
884 }
885 
886 
887 /**
888  * @brief Update Ethernet output statistics
889  * @param[in] interface Underlying network interface
890  * @param[in] destMacAddr Destination MAC address
891  * @param[in] length Length of the outgoing Ethernet frame
892  **/
893 
894 void ethUpdateOutStats(NetInterface *interface, const MacAddr *destMacAddr, size_t length)
895 {
896  //Total number of octets transmitted out of the interface
897  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifOutOctets, length);
898  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifOutOctets, length);
899  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCOutOctets, length);
900 
901  //Check whether the destination address is a unicast, broadcast or multicast address
902  if(macCompAddr(destMacAddr, &MAC_BROADCAST_ADDR))
903  {
904  //Number of non-unicast packets that higher-level protocols requested be transmitted
905  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifOutNUcastPkts, 1);
906 
907  //Number of broadcast packets that higher-level protocols requested be transmitted
908  IF_MIB_INC_COUNTER32(ifXTable[interface->index].ifOutBroadcastPkts, 1);
909  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCOutBroadcastPkts, 1);
910  }
911  else if(macIsMulticastAddr(destMacAddr))
912  {
913  //Number of non-unicast packets that higher-level protocols requested be transmitted
914  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifOutNUcastPkts, 1);
915 
916  //Number of multicast packets that higher-level protocols requested be transmitted
917  IF_MIB_INC_COUNTER32(ifXTable[interface->index].ifOutMulticastPkts, 1);
918  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCOutMulticastPkts, 1);
919  }
920  else
921  {
922  //Number of unicast packets that higher-level protocols requested be transmitted
923  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifOutUcastPkts, 1);
924  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifOutUcastPkts, 1);
925  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCOutUcastPkts, 1);
926  }
927 }
928 
929 
930 /**
931  * @brief Update Ethernet error statistics
932  * @param[in] interface Underlying network interface
933  * @param[in] error Status code describing the error
934  **/
935 
936 void ethUpdateErrorStats(NetInterface *interface, error_t error)
937 {
938  //Check error code
939  switch(error)
940  {
943  //Number of inbound packets which were chosen to be discarded even
944  //though no errors had been detected
945  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifInDiscards, 1);
946  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
947  break;
950  //Number of inbound packets that contained errors
951  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifInErrors, 1);
952  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInErrors, 1);
953  break;
955  //Number of packets received via the interface which were discarded
956  //because of an unknown or unsupported protocol
957  MIB2_INC_COUNTER32(ifGroup.ifTable[interface->index].ifInUnknownProtos, 1);
958  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInUnknownProtos, 1);
959  break;
960  default:
961  //Just for sanity
962  break;
963  }
964 }
965 
966 
967 /**
968  * @brief Ethernet CRC calculation
969  * @param[in] data Pointer to the data over which to calculate the CRC
970  * @param[in] length Number of bytes to process
971  * @return Resulting CRC value
972  **/
973 
974 uint32_t ethCalcCrc(const void *data, size_t length)
975 {
976 //A lookup table can be used to speed up CRC calculation
977 #if (ETH_FAST_CRC_SUPPORT == ENABLED)
978  uint_t i;
979 
980  //Point to the data over which to calculate the CRC
981  const uint8_t *p = (uint8_t *) data;
982  //CRC preset value
983  uint32_t crc = 0xFFFFFFFF;
984 
985  //Loop through data
986  for(i = 0; i < length; i++)
987  {
988  //The message is processed byte by byte
989  crc = (crc >> 8) ^ crc32Table[(crc & 0xFF) ^ p[i]];
990  }
991 
992  //Return 1's complement value
993  return ~crc;
994 
995 //Bit by bit CRC calculation
996 #else
997  uint_t i;
998  uint_t j;
999 
1000  //Point to the data over which to calculate the CRC
1001  const uint8_t *p = (uint8_t *) data;
1002  //CRC preset value
1003  uint32_t crc = 0xFFFFFFFF;
1004 
1005  //Loop through data
1006  for(i = 0; i < length; i++)
1007  {
1008  //Update CRC value
1009  crc ^= p[i];
1010  //The message is processed bit by bit
1011  for(j = 0; j < 8; j++)
1012  {
1013  if(crc & 0x00000001)
1014  crc = (crc >> 1) ^ 0xEDB88320;
1015  else
1016  crc = crc >> 1;
1017  }
1018  }
1019 
1020  //Return 1's complement value
1021  return ~crc;
1022 #endif
1023 }
1024 
1025 
1026 /**
1027  * @brief Calculate CRC over a multi-part buffer
1028  * @param[in] buffer Pointer to the multi-part buffer
1029  * @param[in] offset Offset from the beginning of the buffer
1030  * @param[in] length Number of bytes to process
1031  * @return Resulting CRC value
1032  **/
1033 
1034 uint32_t ethCalcCrcEx(const NetBuffer *buffer, size_t offset, size_t length)
1035 {
1036  uint_t i;
1037  uint_t n;
1038  uint32_t crc;
1039  uint8_t *p;
1040 #if (ETH_FAST_CRC_SUPPORT == DISABLED)
1041  uint_t k;
1042 #endif
1043 
1044  //CRC preset value
1045  crc = 0xFFFFFFFF;
1046 
1047  //Loop through data chunks
1048  for(i = 0; i < buffer->chunkCount && length > 0; i++)
1049  {
1050  //Is there any data to process in the current chunk?
1051  if(offset < buffer->chunk[i].length)
1052  {
1053  //Point to the first data byte
1054  p = (uint8_t *) buffer->chunk[i].address + offset;
1055  //Compute the number of bytes to process
1056  n = MIN(buffer->chunk[i].length - offset, length);
1057  //Adjust byte counter
1058  length -= n;
1059 
1060  //Process current chunk
1061  while(n > 0)
1062  {
1063 #if (ETH_FAST_CRC_SUPPORT == ENABLED)
1064  //The message is processed byte by byte
1065  crc = (crc >> 8) ^ crc32Table[(crc & 0xFF) ^ *p];
1066 #else
1067  //Update CRC value
1068  crc ^= *p;
1069 
1070  //The message is processed bit by bit
1071  for(k = 0; k < 8; k++)
1072  {
1073  if(crc & 0x00000001)
1074  crc = (crc >> 1) ^ 0xEDB88320;
1075  else
1076  crc = crc >> 1;
1077  }
1078 #endif
1079  //Next byte
1080  p++;
1081  n--;
1082  }
1083 
1084  //Process the next block from the start
1085  offset = 0;
1086  }
1087  else
1088  {
1089  //Skip the current chunk
1090  offset -= buffer->chunk[i].length;
1091  }
1092  }
1093 
1094  //Return 1's complement value
1095  return ~crc;
1096 }
1097 
1098 
1099 /**
1100  * @brief Allocate a buffer to hold an Ethernet frame
1101  * @param[in] length Desired payload length
1102  * @param[out] offset Offset to the first byte of the payload
1103  * @return The function returns a pointer to the newly allocated
1104  * buffer. If the system is out of resources, NULL is returned
1105  **/
1106 
1107 NetBuffer *ethAllocBuffer(size_t length, size_t *offset)
1108 {
1109  size_t n;
1110  NetBuffer *buffer;
1111 
1112  //Ethernet frame overhead
1113  n = sizeof(EthHeader);
1114 
1115 #if (ETH_VLAN_SUPPORT == ENABLED)
1116  //VLAN tagging overhead (802.1q)
1117  n += sizeof(VlanTag);
1118 #endif
1119 
1120 #if (ETH_VMAN_SUPPORT == ENABLED)
1121  //VMAN tagging overhead (802.1ad)
1122  n += sizeof(VlanTag);
1123 #endif
1124 
1125 #if (ETH_PORT_TAGGING_SUPPORT == ENABLED)
1126  //Special VLAN tagging overhead
1127  n += sizeof(VlanTag);
1128 #endif
1129 
1130  //Allocate a buffer to hold the Ethernet header and the payload
1131  buffer = netBufferAlloc(length + n);
1132  //Failed to allocate buffer?
1133  if(buffer == NULL)
1134  return NULL;
1135 
1136  //Offset to the first byte of the payload
1137  *offset = n;
1138 
1139  //Return a pointer to the freshly allocated buffer
1140  return buffer;
1141 }
1142 
1143 
1144 /**
1145  * @brief Convert a string representation of a MAC address to a binary MAC address
1146  * @param[in] str NULL-terminated string representing the MAC address
1147  * @param[out] macAddr Binary representation of the MAC address
1148  * @return Error code
1149  **/
1150 
1151 error_t macStringToAddr(const char_t *str, MacAddr *macAddr)
1152 {
1153  error_t error;
1154  int_t i = 0;
1155  int_t value = -1;
1156 
1157  //Parse input string
1158  while(1)
1159  {
1160  //Hexadecimal digit found?
1161  if(isxdigit((uint8_t) *str))
1162  {
1163  //First digit to be decoded?
1164  if(value < 0)
1165  value = 0;
1166 
1167  //Update the value of the current byte
1168  if(isdigit((uint8_t) *str))
1169  value = (value * 16) + (*str - '0');
1170  else if(isupper((uint8_t) *str))
1171  value = (value * 16) + (*str - 'A' + 10);
1172  else
1173  value = (value * 16) + (*str - 'a' + 10);
1174 
1175  //Check resulting value
1176  if(value > 0xFF)
1177  {
1178  //The conversion failed
1179  error = ERROR_INVALID_SYNTAX;
1180  break;
1181  }
1182  }
1183  //Dash or colon separator found?
1184  else if((*str == '-' || *str == ':') && i < 6)
1185  {
1186  //Each separator must be preceded by a valid number
1187  if(value < 0)
1188  {
1189  //The conversion failed
1190  error = ERROR_INVALID_SYNTAX;
1191  break;
1192  }
1193 
1194  //Save the current byte
1195  macAddr->b[i++] = value;
1196  //Prepare to decode the next byte
1197  value = -1;
1198  }
1199  //End of string detected?
1200  else if(*str == '\0' && i == 5)
1201  {
1202  //The NULL character must be preceded by a valid number
1203  if(value < 0)
1204  {
1205  //The conversion failed
1206  error = ERROR_INVALID_SYNTAX;
1207  }
1208  else
1209  {
1210  //Save the last byte of the MAC address
1211  macAddr->b[i] = value;
1212  //The conversion succeeded
1213  error = NO_ERROR;
1214  }
1215 
1216  //We are done
1217  break;
1218  }
1219  //Invalid character...
1220  else
1221  {
1222  //The conversion failed
1223  error = ERROR_INVALID_SYNTAX;
1224  break;
1225  }
1226 
1227  //Point to the next character
1228  str++;
1229  }
1230 
1231  //Return status code
1232  return error;
1233 }
1234 
1235 
1236 /**
1237  * @brief Convert a MAC address to a dash delimited string
1238  * @param[in] macAddr Pointer to the MAC address
1239  * @param[out] str NULL-terminated string representing the MAC address
1240  * @return Pointer to the formatted string
1241  **/
1242 
1243 char_t *macAddrToString(const MacAddr *macAddr, char_t *str)
1244 {
1245  static char_t buffer[18];
1246 
1247  //The str parameter is optional
1248  if(str == NULL)
1249  str = buffer;
1250 
1251  //Format MAC address
1252  sprintf(str, "%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8,
1253  macAddr->b[0], macAddr->b[1], macAddr->b[2], macAddr->b[3], macAddr->b[4], macAddr->b[5]);
1254 
1255  //Return a pointer to the formatted string
1256  return str;
1257 }
1258 
1259 
1260 /**
1261  * @brief Map a MAC address to the IPv6 modified EUI-64 identifier
1262  * @param[in] macAddr Host MAC address
1263  * @param[out] interfaceId IPv6 modified EUI-64 identifier
1264  **/
1265 
1266 void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
1267 {
1268  //Copy the Organization Unique Identifier (OUI)
1269  interfaceId->b[0] = macAddr->b[0];
1270  interfaceId->b[1] = macAddr->b[1];
1271  interfaceId->b[2] = macAddr->b[2];
1272 
1273  //The middle 16 bits are given the value 0xFFFE
1274  interfaceId->b[3] = 0xFF;
1275  interfaceId->b[4] = 0xFE;
1276 
1277  //Copy the right-most 24 bits of the MAC address
1278  interfaceId->b[5] = macAddr->b[3];
1279  interfaceId->b[6] = macAddr->b[4];
1280  interfaceId->b[7] = macAddr->b[5];
1281 
1282  //Modified EUI-64 format interface identifiers are
1283  //formed by inverting the Universal/Local bit
1285 }
1286 
1287 
1288 /**
1289  * @brief Dump Ethernet header for debugging purpose
1290  * @param[in] ethHeader Pointer to the Ethernet header
1291  **/
1292 
1293 void ethDumpHeader(const EthHeader *ethHeader)
1294 {
1295  //Dump Ethernet header contents
1296  TRACE_DEBUG(" Dest Addr = %s\r\n", macAddrToString(&ethHeader->destAddr, NULL));
1297  TRACE_DEBUG(" Src Addr = %s\r\n", macAddrToString(&ethHeader->srcAddr, NULL));
1298  TRACE_DEBUG(" Type = 0x%04" PRIX16 "\r\n", ntohs(ethHeader->type));
1299 }
1300 
1301 #endif
1302 #if (ETH_SUPPORT == ENABLED || IPV6_SUPPORT == ENABLED)
1303 
1304 //Unspecified EUI-64 address
1305 const Eui64 EUI64_UNSPECIFIED_ADDR = {{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}};
1306 
1307 
1308 /**
1309  * @brief Convert a string representation of an EUI-64 address to a binary EUI-64 address
1310  * @param[in] str NULL-terminated string representing the EUI-64 address
1311  * @param[out] eui64 Binary representation of the EUI-64 address
1312  * @return Error code
1313  **/
1314 
1316 {
1317  error_t error;
1318  int_t i = 0;
1319  int_t value = -1;
1320 
1321  //Parse input string
1322  while(1)
1323  {
1324  //Hexadecimal digit found?
1325  if(isxdigit((uint8_t) *str))
1326  {
1327  //First digit to be decoded?
1328  if(value < 0)
1329  value = 0;
1330 
1331  //Update the value of the current byte
1332  if(isdigit((uint8_t) *str))
1333  value = (value * 16) + (*str - '0');
1334  else if(isupper((uint8_t) *str))
1335  value = (value * 16) + (*str - 'A' + 10);
1336  else
1337  value = (value * 16) + (*str - 'a' + 10);
1338 
1339  //Check resulting value
1340  if(value > 0xFF)
1341  {
1342  //The conversion failed
1343  error = ERROR_INVALID_SYNTAX;
1344  break;
1345  }
1346  }
1347  //Dash or colon separator found?
1348  else if((*str == '-' || *str == ':') && i < 8)
1349  {
1350  //Each separator must be preceded by a valid number
1351  if(value < 0)
1352  {
1353  //The conversion failed
1354  error = ERROR_INVALID_SYNTAX;
1355  break;
1356  }
1357 
1358  //Save the current byte
1359  eui64->b[i++] = value;
1360  //Prepare to decode the next byte
1361  value = -1;
1362  }
1363  //End of string detected?
1364  else if(*str == '\0' && i == 7)
1365  {
1366  //The NULL character must be preceded by a valid number
1367  if(value < 0)
1368  {
1369  //The conversion failed
1370  error = ERROR_INVALID_SYNTAX;
1371  }
1372  else
1373  {
1374  //Save the last byte of the EUI-64 address
1375  eui64->b[i] = value;
1376  //The conversion succeeded
1377  error = NO_ERROR;
1378  }
1379 
1380  //We are done
1381  break;
1382  }
1383  //Invalid character...
1384  else
1385  {
1386  //The conversion failed
1387  error = ERROR_INVALID_SYNTAX;
1388  break;
1389  }
1390 
1391  //Point to the next character
1392  str++;
1393  }
1394 
1395  //Return status code
1396  return error;
1397 }
1398 
1399 
1400 /**
1401  * @brief Convert an EUI-64 address to a dash delimited string
1402  * @param[in] eui64 Pointer to the EUI-64 address
1403  * @param[out] str NULL-terminated string representing the EUI-64 address
1404  * @return Pointer to the formatted string
1405  **/
1406 
1407 char_t *eui64AddrToString(const Eui64 *eui64, char_t *str)
1408 {
1409  static char_t buffer[24];
1410 
1411  //The str parameter is optional
1412  if(str == NULL)
1413  str = buffer;
1414 
1415  //Format EUI-64 identifier
1416  sprintf(str, "%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8
1417  "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8 "-%02" PRIX8,
1418  eui64->b[0], eui64->b[1], eui64->b[2], eui64->b[3],
1419  eui64->b[4], eui64->b[5], eui64->b[6], eui64->b[7]);
1420 
1421  //Return a pointer to the formatted string
1422  return str;
1423 }
1424 
1425 #endif
ARP (Address Resolution Protocol)
MacAddr addr
MAC address.
Definition: ethernet.h:210
__start_packed struct @114 EthHeader
Ethernet frame header.
Interfaces Group MIB module.
char char_t
Definition: compiler_port.h:41
void ethUpdateOutStats(NetInterface *interface, const MacAddr *destMacAddr, size_t length)
Update Ethernet output statistics.
Definition: ethernet.c:894
bool_t addFlag
Definition: ethernet.h:212
char_t * eui64AddrToString(const Eui64 *eui64, char_t *str)
Convert an EUI-64 address to a dash delimited string.
Definition: ethernet.c:1407
#define VLAN_VID_MASK
Definition: ethernet.h:89
TCP/IP stack core.
#define ETH_MIN_FRAME_SIZE
Definition: ethernet.h:78
Debugging facilities.
uint_t chunkCount
Definition: net_mem.h:96
uint8_t p
Definition: ndp.h:295
uint_t maxChunkCount
Definition: net_mem.h:97
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
#define IF_MIB_INC_COUNTER32(name, value)
Definition: if_mib_module.h:45
Generic error code.
Definition: error.h:43
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:98
error_t macStringToAddr(const char_t *str, MacAddr *macAddr)
Convert a string representation of a MAC address to a binary MAC address.
Definition: ethernet.c:1151
bool_t deleteFlag
Definition: ethernet.h:213
error_t ethCheckDestAddr(NetInterface *interface, const MacAddr *macAddr)
Destination MAC address filtering.
Definition: ethernet.c:673
MIB-II module.
Invalid parameter.
Definition: error.h:45
#define IF_MIB_INC_COUNTER64(name, value)
Definition: if_mib_module.h:46
void ipv6ProcessPacket(NetInterface *interface, NetBuffer *ipPacket, size_t ipPacketOffset)
Incoming IPv6 packet processing.
Definition: ipv6.c:885
error_t nicSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet to the network controller.
Definition: nic.c:148
char_t type
#define LOAD32BE(p)
Definition: cpu_endian.h:192
#define htons(value)
Definition: cpu_endian.h:390
#define MIB2_INC_COUNTER32(name, value)
Definition: mib2_module.h:154
__start_packed struct @166 ArpPacket
ARP packet.
void * address
Definition: net_mem.h:76
void arpProcessPacket(NetInterface *interface, ArpPacket *arpPacket, size_t length)
Incoming ARP packet processing.
Definition: arp.c:534
error_t eui64StringToAddr(const char_t *str, Eui64 *eui64)
Convert a string representation of an EUI-64 address to a binary EUI-64 address.
Definition: ethernet.c:1315
uint32_t ethCalcCrcEx(const NetBuffer *buffer, size_t offset, size_t length)
Calculate CRC over a multi-part buffer.
Definition: ethernet.c:1034
#define TRUE
Definition: os_port.h:48
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
__start_packed struct @113 Eui64
EUI-64 identifier.
Ethernet.
ChunkDesc chunk[]
Definition: net_mem.h:90
uint16_t size
Definition: net_mem.h:78
void ethDumpHeader(const EthHeader *ethHeader)
Dump Ethernet header for debugging purpose.
Definition: ethernet.c:1293
#define ntohs(value)
Definition: cpu_endian.h:396
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
Definition: ethernet.c:634
signed int int_t
Definition: compiler_port.h:42
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:411
#define NET_INTERFACE_COUNT
Definition: net.h:108
TCP/IP raw sockets.
#define htole32(value)
Definition: cpu_endian.h:404
IPv4 (Internet Protocol Version 4)
ChunkDesc chunk[1]
Definition: net_mem.h:98
error_t ethDropMacAddr(NetInterface *interface, const MacAddr *macAddr)
Remove a unicast/multicast address from the MAC filter table.
Definition: ethernet.c:803
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
#define MIN(a, b)
Definition: os_port.h:60
error_t ethInit(NetInterface *interface)
Ethernet related initialization.
Definition: ethernet.c:150
Eui64 interfaceId
Definition: ipv6cp.h:67
NetInterface netInterface[NET_INTERFACE_COUNT]
Definition: net.c:74
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
void ethUpdateErrorStats(NetInterface *interface, error_t error)
Update Ethernet error statistics.
Definition: ethernet.c:936
const MacAddr MAC_BROADCAST_ADDR
Definition: ethernet.c:55
error_t ethSendFrame(NetInterface *interface, const MacAddr *destAddr, NetBuffer *buffer, size_t offset, uint16_t type)
Send an Ethernet frame.
Definition: ethernet.c:476
NetBuffer * netBufferAlloc(size_t length)
Allocate a multi-part buffer.
Definition: net_mem.c:241
const uint8_t ethPadding[64]
Definition: ethernet.c:58
void macAddrToEui64(const MacAddr *macAddr, Eui64 *interfaceId)
Map a MAC address to the IPv6 modified EUI-64 identifier.
Definition: ethernet.c:1266
error_t ethAcceptMacAddr(NetInterface *interface, const MacAddr *macAddr)
Add a unicast/multicast address to the MAC filter table.
Definition: ethernet.c:733
IPv6 (Internet Protocol Version 6)
Success.
Definition: error.h:42
void ethUpdateInStats(NetInterface *interface, const MacAddr *destMacAddr)
Update Ethernet input statistics.
Definition: ethernet.c:856
const Eui64 EUI64_UNSPECIFIED_ADDR
Definition: ethernet.c:1305
error_t nicUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
Definition: nic.c:204
uint16_t length
Definition: net_mem.h:77
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:211
error_t
Error codes.
Definition: error.h:40
#define ETH_CRC_SIZE
Definition: ethernet.h:84
NetInterface * nicGetPhysicalInterface(NetInterface *interface)
Retrieve physical interface.
Definition: nic.c:85
unsigned int uint_t
Definition: compiler_port.h:43
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:584
__start_packed struct @112 MacAddr
MAC address.
uint8_t data[]
Definition: dtls_misc.h:167
#define PRIuSIZE
Definition: compiler_port.h:72
#define NetInterface
Definition: net.h:34
NetBuffer * ethAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an Ethernet frame.
Definition: ethernet.c:1107
uint8_t value[]
Definition: dtls_misc.h:141
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:95
MacAddr srcAddr
Definition: ethernet.h:181
#define Ipv4Header
Definition: ipv4.h:34
char_t * macAddrToString(const MacAddr *macAddr, char_t *str)
Convert a MAC address to a dash delimited string.
Definition: ethernet.c:1243
error_t netInitRand(uint32_t seed)
Seed pseudo-random number generator.
Definition: net.c:1508
NetInterface * nicGetLogicalInterface(NetInterface *interface)
Retrieve logical interface.
Definition: nic.c:60
__start_packed struct @115 VlanTag
VLAN tag.
void rawSocketProcessEthPacket(NetInterface *interface, EthHeader *ethFrame, size_t length)
Process incoming Ethernet packet.
Definition: raw_socket.c:269
Socket API.
void ethProcessFrame(NetInterface *interface, uint8_t *frame, size_t length)
Process an incoming Ethernet frame.
Definition: ethernet.c:168
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
uint32_t ethCalcCrc(const void *data, size_t length)
Ethernet CRC calculation.
Definition: ethernet.c:974
#define FALSE
Definition: os_port.h:44
Network interface controller abstraction layer.
TCP timer management.
void ipv4ProcessPacket(NetInterface *interface, Ipv4Header *packet, size_t length)
Incoming IPv4 packet processing.
Definition: ipv4.c:440
MacAddr destAddr
Definition: ethernet.h:180
uint_t chunkCount
Definition: net_mem.h:88
MAC filter table entry.
Definition: ethernet.h:208
#define TRACE_DEBUG(...)
Definition: debug.h:98