FCS collision in (Ethernet) frames
What will happen is that the frame will be considered valid by the data link layer and its payload will be passed to the upper layers. The upper layers might have their own error detection mechanisms (e.g. TCP/IP checksum) so the might detect the error themselves and throw out the frame, but then again, they might not. If they don't, then the application will actually receive faulty data.
The chances of that happening are rather low, but I'm sure happens due to the sheer number of packets sent across networks.
C - CRC32 checksum does not match Wireshark on Ethernet Frame Check Sequence
Your implementation is definitively correct (for NUL terminated C strings). It's a maybe a wrong configuration of the network interface. In default mode Wireshark doesn't get a FCS from the network driver. If you use Linux and the driver supports this, then you must enable this with ethtool to get the FCS.
Unfortunately, on my system this only works for receiving frames:
$ ethtool -K eth0 rx-fcs on
See this for details.
I use a slightly different algorithm in my embedded (for AVR microcontrollers) projects and it works perfectly for me:
#define CRC_POLY 0xEDB88320
uint32_t crc32_calc(uint8_t *data, int len)
{
int i, j;
uint32_t crc;
if (!data)
return 0;
if (len < 1)
return 0;
crc = 0xFFFFFFFF;
for (j = 0; j < len; j++) {
crc ^= data[j];
for (i = 0; i < 8; i++) {
crc = (crc & 1) ? ((crc >> 1) ^ CRC_POLY) : (crc >> 1);
}
}
return (crc ^ 0xFFFFFFFF);
}
A real world example:
The Ethernet frame in Wireshark (with ethtool rx-fcs on):
The test with my used implementation:
uint8_t frame[] = { 0x20, 0xcf, 0x30, 0x1a, 0xce, 0xa1, 0x62, 0x38,
0xe0, 0xc2, 0xbd, 0x30, 0x08, 0x06, 0x00, 0x01,
0x08, 0x00 ,0x06 ,0x04 ,0x00 ,0x01 ,0x62 ,0x38,
0xe0 ,0xc2 ,0xbd ,0x30 ,0x0a, 0x2a, 0x2a, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x2a,
0x2a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
printf("0x%x\n", crc32_calc(frame, sizeof(frame)));
The output:
$ ./fcs-test
0x6026b722
$
You can see, Wireshark reports 0x22bf2660 as correct FCS. Here is only a different output because of the byte-order. But the CRC calculation algorithm is correct.
EDIT:
I have modified your code:
uint32_t crc32b(uint8_t *message, int len) {
int i, j;
uint32_t crc, mask;
uint8_t byte;
crc = 0xFFFFFFFF;
for (j = 0; j < len; j++) {
byte = message[j];
crc = crc ^ byte;
for (i = 7; i >= 0; i--) {
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
}
return ~crc;
}
I added a length argument, because your implementation only works correct when message is a NUL terminated C string. If your input is a byte array, then you get a incorrect CRC value.
See the differences (Array and C string):
uint8_t msg_arr[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x5c, 0xb9, 0x01, 0x7c, 0x5a, 0x53, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
char *msg_str = "aabbccddeeff5cb9017c5a53080000000000000000000000000000";
printf("0x%x\n", crc32b(msg_arr, sizeof(msg_arr)));
printf("0x%x\n", crc32b(msg_str, strlen(msg_str)));
Output:
$
0x3422dd71
0xd81e4af3
$
CRC checking on switch
Here's a description of a store-and-forward switch that checks FCS before sending it on. FCS could only be done for store-and-forward, it seems, since you have to have the whole packet to calculate the FCS. But that doesn't mean all switches do this on store-and-forward.
Edit:
Also found that a switch in cut-through mode will forward a packet with an incorrect FCS left intact.
What if CRC bits have error in Ethernet Frame?
No matter crc itself is good or bad, as long as it doesn't match/verify payload (even the payload is still good), this ethernet frame is considered as having a crc error and should be dropped at layer2.
From what I know, in general we don't do any error "correction" with ethernet. Besides, crc is for error detection, not correction.
However, mainly upper layer protocol (say TCP) is responsible for reliable delivery and does what it should do to retransmit.
calculate (and validate) ethernet FCS (crc32) in vhdl
I started working on an ethernet MAC a while back, and although I never got round to finishing it I do have a working CRC generator that you can use here:
CRC.vhd
Its based on a Xilinx App note on the IEEE 802.3 CRC, which you can find here.
The CRC is instantiated in the ethernet receieve component, if you look at the ETH_RECEIVE_SM process you can see how the FCS is loaded into the checker.
Hopefully you can spot your mistake by comparing with my code.
Edit:
I took the sample ethernet frame from fpga4fun and passed it through the CRC checker, see the simulation screenshot below (right click, copy URL and view in a new browser tab for full resolution):
You can see the residual C704DD7B at the end there, try doing the same with your own CRC checker and see what you get.
Related Topics
How to Check If Ssh-Agent Is Already Running in Bash
Get Link Speed Programmatically
Could Not Load Shared Library Symbols for Linux-Vdso.So.1. While Debugging
How to Download the Torvalds Linux Kernel Master, (Re)Compile It, and Boot It with Qemu
How to Program for Linux's New 'Fanotify' File System Monitoring Feature
How to Mmap the Stack for the Clone() System Call on Linux
Gdb Does Not Hit Any Breakpoints When I Run It from Inside Docker Container
Implementing Poll in a Linux Kernel Module
Multiple Option Arguments Using Getopts (Bash)
Sort by Third Column Leaving First and Second Column Intact in Linux
Git Pull Permission Denied Linux
Use Sed with Ignore Case While Adding Text Before Some Pattern
How to Add a Footer to the Bottom of Each Page of a Postscript or PDF File in Linux