Spanish Italian
17153 Users    

Ethernet 7/7

  Download PDF version of the Article

Checksum
The checksum is a method to control the packet integrity, or rather permits to establish if this contains errors (and so is unusable).
the word checksum doesn't identify a particular algorithm, but that used for IP and others protocols is the complement to 1 of the complements sum to 1 of the words at 16bit of the dates where it is made the calculation;
or rather, they sum all the words at 16bit, summing also the eventual overflow and at last follow the complement at 1.
Fisrt it was illustrated how the checksum, in the sending phase, is calculated and then wrote in the packet; what wasn't still illustrated is the checksum control at the packet arrive. To verify that the packet is integral, must save temporally the packet checksum field and put at zero, then follow the calculation and then confront the result with that one saved; if are the same, the packet is correct.
Actually ,for how is made the algorithm, the verifying in very simple: it's enough to calculate the checksum in the packet without modify it; if the result is zero, so the packet in OK, or else is for reject.

The ENC28J60 integral, in the DMA module, a function quite fast for the checksum calculation, and we'll use it.
Unfortunatelly,
in the chip B5 review, this function gives big problems to the packets reception, so in this case the calculation will follow the software.
First of all, let's see the function prototype DMAChecksum:

u16 DMAChecksum(u16 start, u16 len, BOOL rx)

the first parameter indicates the address from where begin the dates, len the length in byte of these dates, at last rx is useful to indicate
if the address "talks" about the RX or TX .
(The address is an offset relative, compared with the MAC packet dates field beginning )

As I told first, this method has two different implementations for the review B1-B4 e B5, let's see the first one:

u16 DMAChecksum(u16 start, u16 len, BOOL rx){
	// calculates the checksum using the chip function 
	u16 tmp;
	u8 L,H;
	if (rx) {
		tmp = TX_BUF_START + 1 + sizeof(MAC_Header) + start;
	} else {
		tmp = packetStart + 6 + sizeof(MAC_Header) + start;
		if (tmp > RX_BUF_END)
			tmp = tmp - RX_BUF_END + RX_BUF_START - 1;
	}

	setBank(0);
	writeReg(EDMASTL, LOW(tmp));
	writeReg(EDMASTH, HIGH(tmp));
	
	tmp = tmp+len-1; 			// end packet
	if (!rx && tmp > RX_BUF_END)
		tmp = tmp - RX_BUF_END + RX_BUF_START - 1;
	writeReg(EDMANDL, LOW(tmp));
	writeReg(EDMANDH, HIGH(tmp));
	
	BFSReg(ECON1, 0b00110000);      	//start calculation
	while(readETH(ECON1) & 0b00100000);	// wait end calculation
	tmp = (u16)readETH(EDMACSL) << 8;
	tmp = tmp | readETH(EDMACSH);
	return tmp;				// return the checksum calculated
}

Fist of all, are calculated and wrote in the registers the absolute start and end addresses of the dates on we make the operation. Then is passed the calculation and we are waiting for the end.

In the second case, is followed the calculation on the software, which makes the operation very slow:

u16 DMAChecksum(u16 start, u16 len, BOOL rx){
		// calculate the checksum via software
	u16	tmp;
	u16 reg[2];
	u32 sum;
	u16 len2;
	int i;

	if (rx) {
    	tmp = TX_BUF_START + 1 + sizeof(MAC_Header) + start;
	} else {
		tmp = packetStart + 6 + sizeof(MAC_Header) + start;
		if (tmp > RX_BUF_END)
			tmp = tmp - RX_BUF_END + RX_BUF_START - 1;
	}

	// salva ERDPT
	setBank(0);
	reg[0] = readETH(ERDPTL);
	reg[1] = readETH(ERDPTH);

	writeReg(ERDPTL,LOW(tmp));
	writeReg(ERDPTH,HIGH(tmp));

	sum = 0;
	len2 = len & 0xFE;
	CS = 0;
	spiWrite(RBM);
	for (i=0; i<len2; i=i+2){
		tmp = ((u16)spiRead()) << 8 | spiRead();
		sum = sum + (u32) tmp;	
	}
	if (len2!=len) sum += ((u32)spiRead()) << 8; 		// if the packet has odd length
	CS = 1;
	
	while (sum >> 16)
	  sum = (sum & 0xFFFF) + (sum >>  16);

	tmp = ~sum;

	// return ERDPT;
	setBank(0);
	writeReg(ERDPTL,reg[0]);
	writeReg(ERDPTH,reg[1]);

	return htons(tmp);					// return the checksum calculated
}

Before effecting the operation, is saved the ERDPT register (restored at the end ), that's why are read
all the byte necessary to the calculation.

Let's see also the method putChecksum used in precedence:

void putChecksum(u16 offset, u16 sum){
	// write the checksum "sum" to the address "offset" to the  writing buffer internal
	u16 tmp;
	u16 addr[2];
	setBank(0);		
	addr[0] = readETH(EWRPTL);			// save temporally the punter
	addr[1] = readETH(EWRPTH);			// of the writing
	tmp = 1+sizeof(MAC_Header)+offset;		// new address
	writeReg(EWRPTL,LOW(TX_BUF_START+tmp));
	writeReg(EWRPTH,HIGH(TX_BUF_START+tmp));	// charge the punter
	encPut(LOW(sum));
	encPut(HIGH(sum));      			// write the checksum
	writeReg(EWRPTL,addr[0]);
	writeReg(EWRPTH,addr[1]);			// restore the old pinter}

ICMP
The ICMP is a service protocol (descried from the RFC 792), used to effectuate the controls and the signals inside a network. An ICMP packet can transport different messages types, but that most known and the unique treat in here, is the Echo request, known also like Ping.
In the ISO/OSI model this protocol is usually insert to the third level, doesn't being properly a transport protocol, but it is found above the IP protocol inside of this one is encapsulated.

The packet structure
The ICMP packet structure varies upon the transported message, with the exception of the heading, common to all the types.
Let's see the particular case of an eco request:

ICMP

- Type: takes the value 8 for the request, while in the answer packet is 0.
- Code: unused.
- Checksum: By now known the control field. The algorithm used is the same with the IP protocol..
- Identifier e Sequence Number: are generated by the applicant to recognize the answer. Are left unchanged from who respond.
- Data: contains the dates variable number that are turned in in the answer.

The code
First of all let's see the content of icmp.h file that contains some define, but especially the ICMP packet definition.

#define ICMP_ECHO		8
#define ICMP_ECHO_REPLY		0
#define MAX_ICMP_DATA 		32  	// the maximum length of the dates field

typedef struct {
	u8	type;
	u8	code;
	u16	checksum;
	u16	id;
	u16	sn;
	u8	data[MAX_ICMP_DATA];
} ICMPPacket;

void processICMP(IP_Header ipHeader);

Like you can see are presented the different fields described in the previous paragraph.

The icmp.c file contains the code that permits to answer to a ping.

#include "stack.h"

#define ICMP_Offset	sizeof(IP_Header)

void processICMP(IP_Header ipHeader){
	ICMPPacket	packet;
	u8 size;

	size = ipHeader.totalLength - (ipHeader.verlen & 0x0F)*4;
	if (size > sizeof(packet)) size = sizeof(packet);
	encGetArray((u8*)&packet, size);
	
	if (packet.type == ICMP_ECHO){
		packet.type = ICMP_ECHO_REPLY;
		packet.checksum = 0;
		IPPutHeader(ipHeader.sourceIP, IPPROTO_ICMP, (u8*)&packet, size, size);
		putChecksum(ICMP_Offset+2,DMAChecksum(ICMP_Offset,size,TRUE));
		MACSend();
	}	
}

Through the encGetArray method the packet is read and saved in the variable packet . Then, once examined the type field, if this results to be an eco request, is built the answer packet:
the type field is set to 0 (Echo Reply),the checksum is reseted to zero and recalculated once that the packet is wrote in the buffer; at last is sent everything withMACSend.

ProcessPacket
To functioning everything, must implement a method that examines the packets in arrived and send them to the relatives administrator. (IP and ARP for the third level).
This method is processPacketans is recalled inside a infinite loop in the method main:

void main() {
	encInit();
	
	while (1)
		processPacket();	
}

Let's see the stack.c file

#include "stack.h"

MACAddr	remoteAddr;

void processPacket(){
	MAC_Header header;
	setBank(1);
	while (readETH(EPKTCNT)) { // if there is almost a packet

		MACGetHeader(&header);
		if (header.type == TYPE_IP){
			remoteAddr = header.sourceMAC;
			processIP();
		} else
		if (header.type == TYPE_ARP)
			processARP();

		freeRxSpace();  // free the space in the RX buffer 
	}
}

Reading the EPKCNT register we verify that there is almost a packet waiting to be read, then with the MACGetHeader is read the MAC heading and through the type field is selected if call processIP or proccessARP (or none of these).
These methods were treat in the previous pages.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
4 + 6 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.

Who's new

  • bilalbinrais
  • laulau
  • RiyasAhammed
  • ah2003
  • ronne
  • stomodot
  • mbowien
  • rsilva
  • daveh1955
  • pankspec

Who's online

There are currently 0 users and 61 guests online.