How to Receive the Wrong Ethernet Frames and Disable the Crc/Fcs Calcul

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):

wireshark frame

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):

Sample Image

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



Leave a reply



Submit