ethernet_misc.c
Go to the documentation of this file.
1 /**
2  * @file ethernet_misc.c
3  * @brief Helper functions for Ethernet
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2023 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.2.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL ETH_TRACE_LEVEL
33 
34 //Dependencies
35 #include <stdlib.h>
36 #include <string.h>
37 #include "core/net.h"
38 #include "core/nic.h"
39 #include "core/ethernet.h"
40 #include "core/ethernet_misc.h"
41 #include "core/socket.h"
42 #include "core/raw_socket.h"
43 #include "core/tcp_timer.h"
44 #include "ipv4/arp.h"
45 #include "ipv4/ipv4.h"
46 #include "ipv4/ipv4_misc.h"
47 #include "ipv6/ipv6.h"
48 #include "mibs/mib2_module.h"
49 #include "mibs/if_mib_module.h"
50 #include "debug.h"
51 
52 //Check TCP/IP stack configuration
53 #if (ETH_SUPPORT == ENABLED)
54 
55 //Padding bytes
56 const uint8_t ethPadding[64] =
57 {
58  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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 };
67 
68 //A lookup table can be used to speed up CRC calculation
69 #if (ETH_FAST_CRC_SUPPORT == ENABLED)
70 
71 static const uint32_t crc32Table[256] =
72 {
73  0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
74  0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
75  0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
76  0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
77  0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
78  0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
79  0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
80  0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
81  0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
82  0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
83  0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
84  0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
85  0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
86  0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
87  0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
88  0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
89  0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
90  0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
91  0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
92  0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
93  0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
94  0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
95  0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
96  0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
97  0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
98  0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
99  0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
100  0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
101  0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
102  0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
103  0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
104  0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
105  0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
106  0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
107  0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
108  0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
109  0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
110  0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
111  0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
112  0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
113  0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
114  0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
115  0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
116  0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
117  0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
118  0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
119  0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
120  0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
121  0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
122  0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
123  0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
124  0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
125  0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
126  0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
127  0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
128  0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
129  0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
130  0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
131  0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
132  0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
133  0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
134  0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
135  0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
136  0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
137 };
138 
139 #endif
140 
141 
142 /**
143  * @brief Ethernet frame padding
144  * @param[in] buffer Multi-part buffer containing the Ethernet frame
145  * @param[in,out] length Length of the Ethernet frame, in bytes
146  * @return Error code
147  **/
148 
150 {
151  error_t error;
152  size_t n;
153 
154  //Ethernet frames have a minimum length of 64 byte
156  {
157  //Add padding as necessary
159 
160  //Append padding bytes
161  error = netBufferAppend(buffer, ethPadding, n);
162 
163  //Check status code
164  if(!error)
165  {
166  //Adjust frame length
167  *length += n;
168  }
169  }
170  else
171  {
172  //No padding needed
173  error = NO_ERROR;
174  }
175 
176  //Return status code
177  return error;
178 }
179 
180 
181 /**
182  * @brief VLAN tag encoding
183  * @param[in] buffer Multi-part buffer containing the payload
184  * @param[in,out] offset Offset to the first payload byte
185  * @param[in] vlanId VLAN identifier
186  * @param[in] vlanPcp VLAN priority
187  * @param[in] vlanDei Drop eligible indicator
188  * @param[in] type Ethernet type
189  * @return Error code
190  **/
191 
192 error_t ethEncodeVlanTag(NetBuffer *buffer, size_t *offset, uint16_t vlanId,
193  int8_t vlanPcp, int8_t vlanDei, uint16_t type)
194 {
195  VlanTag *vlanTag;
196 
197  //Sanity check
198  if(*offset < sizeof(VlanTag))
200 
201  //Valid PCP value?
202  if(vlanPcp >= 0)
203  {
204  //The PCP field specifies the frame priority level. Different PCP values
205  //can be used to prioritize different classes of traffic
206  vlanId = (((uint16_t) vlanPcp << VLAN_PCP_POS) & VLAN_PCP_MASK) |
207  (vlanId & ~VLAN_PCP_MASK);
208  }
209 
210  //Valid DEI value?
211  if(vlanDei >= 0)
212  {
213  //The DEI flag may be used to indicate frames eligible to be dropped in
214  //the presence of congestion
215  vlanId = (((uint16_t) vlanDei << VLAN_DEI_POS) & VLAN_DEI_MASK) |
216  (vlanId & ~VLAN_DEI_MASK);
217  }
218 
219  //Make room for the VLAN tag
220  *offset -= sizeof(VlanTag);
221  //Point to the VLAN tag
222  vlanTag = netBufferAt(buffer, *offset);
223 
224  //The TCI field is divided into PCP, DEI, and VID
225  vlanTag->tci = htons(vlanId);
226 
227  //The EtherType field indicates which protocol is encapsulated in the
228  //payload
229  vlanTag->type = htons(type);
230 
231  //Successful processing
232  return NO_ERROR;
233 }
234 
235 
236 /**
237  * @brief VLAN tag decoding
238  * @param[in] frame Pointer to the received Ethernet frame
239  * @param[in] length Length of the frame, in bytes
240  * @param[out] vlanId VLAN identifier
241  * @param[out] type Ethernet type
242  * @return Error code
243  **/
244 
245 error_t ethDecodeVlanTag(const uint8_t *frame, size_t length, uint16_t *vlanId,
246  uint16_t *type)
247 {
248  VlanTag *vlanTag;
249 
250  //Malformed Ethernet frame?
251  if(length < sizeof(VlanTag))
252  {
253  //Drop the received frame
254  return ERROR_INVALID_LENGTH;
255  }
256 
257  //Point to the VLAN tag
258  vlanTag = (VlanTag *) frame;
259 
260  //The VID is encoded in a 12-bit field. The null VID indicates that the
261  //tag header contains only priority information (refer to IEEE 802.1Q,
262  //section 9.6)
263  *vlanId = ntohs(vlanTag->tci) & VLAN_VID_MASK;
264 
265  //The EtherType field indicates which protocol is encapsulated in the
266  //payload
267  *type = ntohs(vlanTag->type);
268 
269  //Successful processing
270  return NO_ERROR;
271 }
272 
273 
274 /**
275  * @brief Destination MAC address filtering
276  * @param[in] interface Underlying network interface
277  * @param[in] macAddr Destination MAC address to be checked
278  * @return Error code
279  **/
280 
281 error_t ethCheckDestAddr(NetInterface *interface, const MacAddr *macAddr)
282 {
283  error_t error;
284  uint_t i;
285  MacFilterEntry *entry;
286  NetInterface *logicalInterface;
287 
288  //Filter out any invalid addresses
289  error = ERROR_INVALID_ADDRESS;
290 
291  //Point to the logical interface
292  logicalInterface = nicGetLogicalInterface(interface);
293 
294  //Interface MAC address?
295  if(macCompAddr(macAddr, &logicalInterface->macAddr))
296  {
297  error = NO_ERROR;
298  }
299  //Broadcast address?
300  else if(macCompAddr(macAddr, &MAC_BROADCAST_ADDR))
301  {
302  error = NO_ERROR;
303  }
304  //Multicast address?
305  else if(macIsMulticastAddr(macAddr))
306  {
307 #if (IPV4_SUPPORT == ENABLED && IGMP_ROUTER_SUPPORT == ENABLED)
308  //Trap multicast packets when IGMP router is enabled
309  if(interface->igmpRouterContext != NULL &&
310  interface->igmpRouterContext->running)
311  {
312  error = NO_ERROR;
313  }
314  else
315 #endif
316  {
317  //Go through the MAC filter table
318  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
319  {
320  //Point to the current entry
321  entry = &interface->macAddrFilter[i];
322 
323  //Valid entry?
324  if(entry->refCount > 0)
325  {
326  //Check whether the destination MAC address matches
327  //a relevant multicast address
328  if(macCompAddr(&entry->addr, macAddr))
329  {
330  //The MAC address is acceptable
331  error = NO_ERROR;
332  //Stop immediately
333  break;
334  }
335  }
336  }
337  }
338  }
339 
340  //Return status code
341  return error;
342 }
343 
344 
345 /**
346  * @brief Trap IGMP packets
347  * @param[in] header Pointer to the Ethernet header
348  * @param[in] data Pointer to the payload data
349  * @param[in] length Length of the payload data, in bytes
350  * @return TRUE if the Ethernet frame contains an IGMP message, else FALSE
351  **/
352 
353 bool_t ethTrapIgmpPacket(EthHeader *header, uint8_t *data, size_t length)
354 {
355  bool_t flag;
356 
357  //Initialize flag
358  flag = FALSE;
359 
360 #if (IPV4_SUPPORT == ENABLED)
361  //Multicast IPv4 packet?
362  if(macIsMulticastAddr(&header->destAddr) &&
363  ntohs(header->type) == ETH_TYPE_IPV4)
364  {
365  //Check the length of the payload data
366  if(length >= sizeof(Ipv4Header))
367  {
368  //Check whether the IPv4 packet contains an IGMP message
369  flag = ipv4TrapIgmpPacket((Ipv4Header *) data);
370  }
371  }
372 #endif
373 
374  //Return TRUE if the Ethernet frame contains an IGMP message
375  return flag;
376 }
377 
378 
379 /**
380  * @brief Update Ethernet input statistics
381  * @param[in] interface Underlying network interface
382  * @param[in] destMacAddr Destination MAC address
383  **/
384 
385 void ethUpdateInStats(NetInterface *interface, const MacAddr *destMacAddr)
386 {
387  //Check whether the destination address is a unicast, broadcast or multicast address
388  if(macCompAddr(destMacAddr, &MAC_BROADCAST_ADDR))
389  {
390  //Number of non-unicast packets delivered to a higher-layer protocol
391  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInNUcastPkts, 1);
392 
393  //Number of broadcast packets delivered to a higher-layer protocol
394  IF_MIB_INC_COUNTER32(ifXTable[interface->index].ifInBroadcastPkts, 1);
395  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCInBroadcastPkts, 1);
396  }
397  else if(macIsMulticastAddr(destMacAddr))
398  {
399  //Number of non-unicast packets delivered to a higher-layer protocol
400  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInNUcastPkts, 1);
401 
402  //Number of multicast packets delivered to a higher-layer protocol
403  IF_MIB_INC_COUNTER32(ifXTable[interface->index].ifInMulticastPkts, 1);
404  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCInMulticastPkts, 1);
405  }
406  else
407  {
408  //Number of unicast packets delivered to a higher-layer protocol
409  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInUcastPkts, 1);
410  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInUcastPkts, 1);
411  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCInUcastPkts, 1);
412  }
413 }
414 
415 
416 /**
417  * @brief Update Ethernet output statistics
418  * @param[in] interface Underlying network interface
419  * @param[in] destMacAddr Destination MAC address
420  * @param[in] length Length of the Ethernet frame, in bytes
421  **/
422 
423 void ethUpdateOutStats(NetInterface *interface, const MacAddr *destMacAddr,
424  size_t length)
425 {
426  //Total number of octets transmitted out of the interface
427  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifOutOctets, length);
428  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifOutOctets, length);
429  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCOutOctets, length);
430 
431  //Check whether the destination address is a unicast, broadcast or multicast address
432  if(macCompAddr(destMacAddr, &MAC_BROADCAST_ADDR))
433  {
434  //Number of non-unicast packets that higher-level protocols requested be transmitted
435  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifOutNUcastPkts, 1);
436 
437  //Number of broadcast packets that higher-level protocols requested be transmitted
438  IF_MIB_INC_COUNTER32(ifXTable[interface->index].ifOutBroadcastPkts, 1);
439  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCOutBroadcastPkts, 1);
440  }
441  else if(macIsMulticastAddr(destMacAddr))
442  {
443  //Number of non-unicast packets that higher-level protocols requested be transmitted
444  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifOutNUcastPkts, 1);
445 
446  //Number of multicast packets that higher-level protocols requested be transmitted
447  IF_MIB_INC_COUNTER32(ifXTable[interface->index].ifOutMulticastPkts, 1);
448  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCOutMulticastPkts, 1);
449  }
450  else
451  {
452  //Number of unicast packets that higher-level protocols requested be transmitted
453  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifOutUcastPkts, 1);
454  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifOutUcastPkts, 1);
455  IF_MIB_INC_COUNTER64(ifXTable[interface->index].ifHCOutUcastPkts, 1);
456  }
457 }
458 
459 
460 /**
461  * @brief Update Ethernet error statistics
462  * @param[in] interface Underlying network interface
463  * @param[in] error Status code describing the error
464  **/
465 
466 void ethUpdateErrorStats(NetInterface *interface, error_t error)
467 {
468  //Check error code
469  switch(error)
470  {
473  //Number of inbound packets which were chosen to be discarded even
474  //though no errors had been detected
475  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
476  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInDiscards, 1);
477  break;
480  //Number of inbound packets that contained errors
481  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInErrors, 1);
482  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInErrors, 1);
483  break;
485  //Number of packets received via the interface which were discarded
486  //because of an unknown or unsupported protocol
487  MIB2_IF_INC_COUNTER32(ifTable[interface->index].ifInUnknownProtos, 1);
488  IF_MIB_INC_COUNTER32(ifTable[interface->index].ifInUnknownProtos, 1);
489  break;
490  default:
491  //Just for sanity
492  break;
493  }
494 }
495 
496 
497 /**
498  * @brief Ethernet CRC calculation
499  * @param[in] data Pointer to the data over which to calculate the CRC
500  * @param[in] length Number of bytes to process
501  * @return Resulting CRC value
502  **/
503 
504 uint32_t ethCalcCrc(const void *data, size_t length)
505 {
506 //A lookup table can be used to speed up CRC calculation
507 #if (ETH_FAST_CRC_SUPPORT == ENABLED)
508  uint_t i;
509 
510  //Point to the data over which to calculate the CRC
511  const uint8_t *p = (uint8_t *) data;
512  //CRC preset value
513  uint32_t crc = 0xFFFFFFFF;
514 
515  //Loop through data
516  for(i = 0; i < length; i++)
517  {
518  //The message is processed byte by byte
519  crc = (crc >> 8) ^ crc32Table[(crc & 0xFF) ^ p[i]];
520  }
521 
522  //Return 1's complement value
523  return ~crc;
524 
525 //Bit by bit CRC calculation
526 #else
527  uint_t i;
528  uint_t j;
529 
530  //Point to the data over which to calculate the CRC
531  const uint8_t *p = (uint8_t *) data;
532  //CRC preset value
533  uint32_t crc = 0xFFFFFFFF;
534 
535  //Loop through data
536  for(i = 0; i < length; i++)
537  {
538  //Update CRC value
539  crc ^= p[i];
540 
541  //The message is processed bit by bit
542  for(j = 0; j < 8; j++)
543  {
544  if(crc & 0x00000001)
545  crc = (crc >> 1) ^ 0xEDB88320;
546  else
547  crc = crc >> 1;
548  }
549  }
550 
551  //Return 1's complement value
552  return ~crc;
553 #endif
554 }
555 
556 
557 /**
558  * @brief Calculate CRC over a multi-part buffer
559  * @param[in] buffer Pointer to the multi-part buffer
560  * @param[in] offset Offset from the beginning of the buffer
561  * @param[in] length Number of bytes to process
562  * @return Resulting CRC value
563  **/
564 
565 uint32_t ethCalcCrcEx(const NetBuffer *buffer, size_t offset, size_t length)
566 {
567  uint_t i;
568  uint_t n;
569  uint32_t crc;
570  uint8_t *p;
571 #if (ETH_FAST_CRC_SUPPORT == DISABLED)
572  uint_t k;
573 #endif
574 
575  //CRC preset value
576  crc = 0xFFFFFFFF;
577 
578  //Loop through data chunks
579  for(i = 0; i < buffer->chunkCount && length > 0; i++)
580  {
581  //Is there any data to process in the current chunk?
582  if(offset < buffer->chunk[i].length)
583  {
584  //Point to the first data byte
585  p = (uint8_t *) buffer->chunk[i].address + offset;
586  //Compute the number of bytes to process
587  n = MIN(buffer->chunk[i].length - offset, length);
588  //Adjust byte counter
589  length -= n;
590 
591  //Process current chunk
592  while(n > 0)
593  {
594 #if (ETH_FAST_CRC_SUPPORT == ENABLED)
595  //The message is processed byte by byte
596  crc = (crc >> 8) ^ crc32Table[(crc & 0xFF) ^ *p];
597 #else
598  //Update CRC value
599  crc ^= *p;
600 
601  //The message is processed bit by bit
602  for(k = 0; k < 8; k++)
603  {
604  if(crc & 0x00000001)
605  crc = (crc >> 1) ^ 0xEDB88320;
606  else
607  crc = crc >> 1;
608  }
609 #endif
610  //Next byte
611  p++;
612  n--;
613  }
614 
615  //Process the next block from the start
616  offset = 0;
617  }
618  else
619  {
620  //Skip the current chunk
621  offset -= buffer->chunk[i].length;
622  }
623  }
624 
625  //Return 1's complement value
626  return ~crc;
627 }
628 
629 
630 /**
631  * @brief Ethernet CRC verification
632  * @param[in] interface Underlying network interface
633  * @param[in] frame Pointer to the received Ethernet frame
634  * @param[in] length Length of the frame, in bytes
635  * @return Error code
636  **/
637 
638 error_t ethCheckCrc(NetInterface *interface, const uint8_t *frame,
639  size_t length)
640 {
641  uint32_t crc;
642 
643  //Malformed Ethernet frame?
644  if(length < (sizeof(EthHeader) + ETH_CRC_SIZE))
645  {
646  //Drop the received frame
647  return ERROR_INVALID_LENGTH;
648  }
649 
650  //CRC verification not supported by hardware?
651  if(!interface->nicDriver->autoCrcVerif)
652  {
653  //The value of the residue is 0x2144DF1C when no CRC errors
654  //are detected
655  if(ethCalcCrc(frame, length) != 0x2144DF1C)
656  {
657  //Drop the received frame
658  return ERROR_WRONG_CHECKSUM;
659  }
660  }
661 
662  //Retrieve CRC value
663  crc = LOAD32BE(frame + length - ETH_CRC_SIZE);
664 
665  //Gather entropy
666  netContext.entropy += crc;
667 
668  //Successful CRC verification
669  return NO_ERROR;
670 }
671 
672 #endif
__start_packed struct @4 VlanTag
VLAN tag.
uint8_t length
Definition: coap_common.h:193
#define htons(value)
Definition: cpu_endian.h:413
IPv6 (Internet Protocol Version 6)
#define VLAN_PCP_POS
Definition: ethernet.h:119
MIB-II module.
int bool_t
Definition: compiler_port.h:53
#define Ipv4Header
Definition: ipv4.h:36
__start_packed struct @2 EthHeader
Ethernet frame header.
void ethUpdateInStats(NetInterface *interface, const MacAddr *destMacAddr)
Update Ethernet input statistics.
uint16_t vlanId
uint8_t data[]
Definition: ethernet.h:220
#define LOAD32BE(p)
Definition: cpu_endian.h:210
uint8_t p
Definition: ndp.h:298
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
uint_t chunkCount
Definition: net_mem.h:90
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
uint32_t entropy
Definition: net.h:312
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:260
error_t ethCheckCrc(NetInterface *interface, const uint8_t *frame, size_t length)
Ethernet CRC verification.
#define VLAN_DEI_POS
Definition: ethernet.h:120
#define ETH_MIN_FRAME_SIZE
Definition: ethernet.h:108
NetContext netContext
Definition: net.c:75
@ ETH_TYPE_IPV4
Definition: ethernet.h:164
#define VLAN_VID_MASK
Definition: ethernet.h:124
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define IF_MIB_INC_COUNTER64(name, value)
Definition: if_mib_module.h:48
Ethernet.
uint32_t ethCalcCrcEx(const NetBuffer *buffer, size_t offset, size_t length)
Calculate CRC over a multi-part buffer.
Helper functions for IPv4.
uint16_t length
Definition: net_mem.h:79
#define FALSE
Definition: os_port.h:48
__start_packed struct @0 MacAddr
MAC address.
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
void ethUpdateErrorStats(NetInterface *interface, error_t error)
Update Ethernet error statistics.
char_t type
error_t
Error codes.
Definition: error.h:43
error_t ethDecodeVlanTag(const uint8_t *frame, size_t length, uint16_t *vlanId, uint16_t *type)
VLAN tag decoding.
void * netBufferAt(const NetBuffer *buffer, size_t offset)
Returns a pointer to the data at the specified position.
Definition: net_mem.c:413
void * address
Definition: net_mem.h:78
#define MIB2_IF_INC_COUNTER32(name, value)
Definition: mib2_module.h:156
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:259
@ ERROR_INVALID_LENGTH
Definition: error.h:111
error_t ethPadFrame(NetBuffer *buffer, size_t *length)
Ethernet frame padding.
Interfaces Group MIB module.
@ ERROR_INVALID_PROTOCOL
Definition: error.h:101
#define MIN(a, b)
Definition: os_port.h:65
bool_t ipv4TrapIgmpPacket(Ipv4Header *header)
Trap IGMP packets.
Definition: ipv4_misc.c:790
TCP/IP raw sockets.
#define ntohs(value)
Definition: cpu_endian.h:421
error_t ethCheckDestAddr(NetInterface *interface, const MacAddr *macAddr)
Destination MAC address filtering.
const uint8_t ethPadding[64]
Definition: ethernet_misc.c:56
#define VLAN_DEI_MASK
Definition: ethernet.h:123
ChunkDesc chunk[]
Definition: net_mem.h:92
#define ETH_CRC_SIZE
Definition: ethernet.h:114
uint8_t n
MAC filter table entry.
Definition: ethernet.h:258
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:586
#define IF_MIB_INC_COUNTER32(name, value)
Definition: if_mib_module.h:47
Network interface controller abstraction layer.
#define VLAN_PCP_MASK
Definition: ethernet.h:122
#define macCompAddr(macAddr1, macAddr2)
Definition: ethernet.h:130
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
Socket API.
void ethUpdateOutStats(NetInterface *interface, const MacAddr *destMacAddr, size_t length)
Update Ethernet output statistics.
bool_t ethTrapIgmpPacket(EthHeader *header, uint8_t *data, size_t length)
Trap IGMP packets.
@ ERROR_WRONG_CHECKSUM
Definition: error.h:88
IPv4 (Internet Protocol Version 4)
uint32_t ethCalcCrc(const void *data, size_t length)
Ethernet CRC calculation.
TCP timer management.
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
NetInterface * nicGetLogicalInterface(NetInterface *interface)
Retrieve logical interface.
Definition: nic.c:52
ARP (Address Resolution Protocol)
Helper functions for Ethernet.
error_t ethEncodeVlanTag(NetBuffer *buffer, size_t *offset, uint16_t vlanId, int8_t vlanPcp, int8_t vlanDei, uint16_t type)
VLAN tag encoding.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
const MacAddr MAC_BROADCAST_ADDR
Definition: ethernet.c:57