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