Altera_Forum
Honored Contributor
11 years agoUDP packets via TSE
Hi, I am working on a project that requires me to send data packets from DE2-115 to a PC. since I need a transfer rate in access of 500 Mbps, i decided to do it using Ethernet using Triple Speed Ethernet IP from altera. But I am facing some problem with the packet fabrication.
what i didThe hardware side of it is very similar to the "using triple-speed ethernet on de2-115 boards" (ftp://ftp.altera.com/up/pub/altera_material/12.0/tutorials/de2-115/using_triple_speed_ethernet.pdf) tutorial. I used TSE and DMA to send data from ethernet. it works fine. I think... On the software side, I used the tse_tutorial.v provided with the tutorial but changed it arround to make the following changes: Firstly, I made the following struct to help make ethernet, ip and udp headers
struct etheader {
unsigned char preamble;
unsigned char MACdestination;
unsigned char MACsource;
unsigned char proto;
};
struct ipheader {
unsigned char iph_type;
unsigned char iph_dscp;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flag;
unsigned char iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned char iph_sourceip;
unsigned char iph_destip;
};
// UDP header's structure
struct udpheader {
unsigned short int port;
unsigned short int udph_len;
unsigned short int udph_chksum;
};
struct crc32body {
unsigned int crc_chksum;
unsigned char end;
};
Then I made the following function to compute the ipchecksum and crc32:
unsigned int crc32c(unsigned char *message, unsigned int last) {
int i, j;
unsigned int byte, crc, mask;
static unsigned int table;
/* Set up the table, if necessary. */
if (table == 0) {
for (byte = 0; byte <= 255; byte++) {
crc = byte;
for (j = 7; j >= 0; j--) { // Do eight times.
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
table = crc;
}
}
/* Through with table setup, now calculate the CRC. */
i = 0;
crc = 0xFFFFFFFF;
while ((byte = message) != 0) {
crc = (crc >> 8) ^ table;
i = i + 1;
}
return ~crc;
}
unsigned short csum(unsigned short *buf, int nwords, int mwords)
{ //
unsigned short *sht_buf = (buf + mwords );
unsigned long sum;
for(sum=0; nwords>0; nwords--)
sum += *sht_buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
unsigned short int htons(unsigned short int x)
{# if BYTE_ORDER == LITTLE_ENDIAN
u_char *s = (u_char *) &x;
return (unsigned short int)(s << 8 | s);# else
return x;# endif
}
the codes are correct to my understanding. after initializing the TSE core, I started with the making to the transmission frame:
// frame buffer
unsigned char rx_frame
// size of frame
unsigned frame Tx_UDPpayloadlength = 180
unsigned int total_size = sizeof(struct etheader)+Tx_UDPpayloadlength+
sizeof(struct ipheader)+sizeof(struct udpheader) + 0x0004;
// structure the frame
unsigned char MAC_des = {0x78,0x84,0x3c,0xcf,0xf4,0x25};// laptop
unsigned char MAC_src = {0x01,0x60,0x6E,0x11,0x02,0x0F};
unsigned char IP_des = {192,168,0,2};
unsigned char IP_src = {192,168,0,44};
struct etheader *eth = (struct etheader * ) tx_frame;
struct ipheader *ip = (struct ipheader *) (tx_frame + sizeof(struct etheader) );
struct udpheader *udp = (struct udpheader *) (tx_frame + sizeof(struct etheader)+ sizeof(struct ipheader));
struct crc32body *crc_32b = (struct crc32body *) (tx_frame + sizeof(struct etheader)+
sizeof(struct ipheader)+sizeof(struct udpheader) + Tx_UDPpayloadlength);
// Fabricate the ethernet header or we can use the
int lp=0;
for (lp=0; lp < 2; lp++) // Ethernet preamble
eth->preamble = 0x00;
for (lp=0; lp < 6; lp++) // Ethernet preamble
{
eth->MACsource = MAC_src;
eth->MACdestination = MAC_des;
if (lp < 4)
{
ip->iph_sourceip = IP_src;
ip->iph_destip = IP_des;
}
}
eth->proto=0x08;
eth->proto=0x00;
// Fabricate the IP and UDP header
ip->iph_type = 0x45;
ip->iph_dscp = 0x00;
ip->iph_len = Tx_UDPpayloadlength + sizeof(struct ipheader) + sizeof(struct udpheader);
ip->iph_ident = 0x0000;
ip->iph_offset = 0x00;
ip->iph_flag = 0x00;
ip->iph_ttl = 0x80; // time to live
ip->iph_protocol = 0x11; // UDP = 17
udp->port=htons(1024);//0x04; udp->port=0x00;
udp->port=htons(1024);//=0x04; udp->port=0x00;
//udp->port=htons(1024);
udp->udph_len=htons(sizeof(struct udpheader)+Tx_UDPpayloadlength);
udp->udph_chksum=0x0000;
ip->iph_chksum=csum((unsigned short *)tx_frame, sizeof(struct ipheader) + sizeof(struct udpheader), sizeof(struct etheader) );
crc_32b->crc_chksum =crc32c(tx_frame, total_size-0x0005);
crc_32b->end = '\0';
this in should make a frame that send date from 192.168.0.44:1024 to 129.168.0.2:1024. I used tcpdump to validate my packets. This is what I get: <time> IP truncated-ip - 53035 bytes missing! 192.168.0.44.1024 > 192.168.0.2.1024: UDP, length 180 commands for sending packet: alt_avalon_sgdma_construct_mem_to_stream_desc( &tx_descriptor, &tx_descriptor_end, tx_frame, total_size, 0, 1, 1, 0 );
// Set up non-blocking transfer of sgdma transmit descriptor
alt_avalon_sgdma_do_async_transfer( sgdma_tx_dev, &tx_descriptor );
TSE settings: --- Quote Start --- Select the following options: Enable MAC 10/100 half duplex support, Include statistics counters,Align packet headers to 32-bit boundary, and Include MDIO module (MDC/MDIO), --- Quote End --- Maybe someone has experience with this to know where I am going wrong!