[ECOS] Ethernet stack sends empty fragment

Timo Gerber timo.gerber@x2e.de
Mon Mar 1 13:22:00 GMT 2010


Am 01.03.2010 13:50, schrieb Gary Thomas:
> Please keep your replies on the mailing list so that all benefit.
>
> On 03/01/2010 05:31 AM, Timo Gerber wrote:
>> Am 01.03.2010 13:19, schrieb Gary Thomas:
>>> On 03/01/2010 03:27 AM, Timo Gerber wrote:
>>>> Hi guys,
>>>> I'm working on an ethernet driver with scather gather support and I am
>>>> wondering:
>>>> When sending UDP packets from the application with a higher
>>>> payload-size (e.g. 2500Bytesand more), the ethernet stack calls my
>>>> DRV_eth_send() function with a weird sg_list.
>>>> For instance, some packets are fragmented like this:
>>>> sg_list[1].len => 42
>>>> sg_list[1].buf => points to the hdr.
>>>>
>>>> sg_list[2].len => 1472
>>>> sg_list[2].buf => points to the payload.
>>>>
>>>> sg_list[3].len => 0
>>>> sg_list[3].buf => points to an empty buffer.
>>>>
>>>> As you can see the last sg fragment is kinda weird, but this scheme
>>>> appears all the time, not only now an then.
>>>
>>> What's the MTU on that interface?
>>>
>> Its a standard ethernet interface with an MTU of 1514
>
> Which matches the request (42+1472==1514). The upper layer
> which creates the SG list must be messing up when this happens.
>
> Which stack (BSD, LWIP) are you using? I don't see how this
> is possible with the BSD layer as it only counts segments which
> have a non-zero length.

This is exactly I am wondering about. I'm using the FreeBSD stack, TCP 
runs just fine. But when the application tries to send an UDP packet 
larger it looses a fragment. At the moment my driver discards the whole 
ethernet-frame when it discovers a sg_list.len with size 0.

I just found out the the limit is 2048 Bytes. That means, udp packest 
with size <= 2048 are fine.

This is my small application code to test the udp interface:

static int udptest(void)
{
#define DEST_IP "192.168.222.100"
#define PORT 5555
#define NPACK 4
#define BUFLEN (2049)
	const int nBytes = BUFLEN * NPACK;
	struct sockaddr_in dest_host;
	int s, i;
	int slen = sizeof(dest_host);
	char buf[BUFLEN];

	cyg_tick_count_t tv1, tv2;

	if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1){
		TST_PRINTF("socket error\n");
	}

	memset(buf, 0, BUFLEN);

	memset((char *) &dest_host, 0, sizeof(dest_host));
	dest_host.sin_len = sizeof(struct sockaddr_in);
	dest_host.sin_family = AF_INET;
	dest_host.sin_port = htons(PORT);
	if (inet_aton(DEST_IP, &dest_host.sin_addr) == 0) {
		TST_PRINTF("inet_aton() failed\n");
		return -1;
	}
	TST_PRINTF("Sending %d packets (%d kBytes)\n", NPACK, nBytes/1000);
	tv1 = cyg_current_time();
	for (i = 0; i < NPACK; i++)
	{
		//TST_PRINTF("Sending packet %d\n", i);
	    snprintf(buf, BUFLEN, "This is packet %d\n", i);
	    int ret = sendto(s, buf, BUFLEN, 0, (struct sockaddr *) &dest_host, 
slen );
	    if( ret == -1)
	    {
	  	  TST_PRINTF("sendto() error(%d)", errno);
	  	  TST_PRINTF("%s)", strerror(errno));
	    }
	 }
     tv2 = cyg_current_time();
     TST_PRINTF("Dauer: %llu ms\n", (tv2-tv1)*1000UL/TICKS_PER_SECOND);
     TST_PRINTF("Durchsatz: %llu kByte/s\n", (((nBytes)) / 
((tv2-tv1)*1000UL/TICKS_PER_SECOND)));
	close(s);

	return 0;
}



-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss



More information about the Ecos-discuss mailing list