From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27981 invoked by alias); 19 Oct 2005 19:11:27 -0000 Mailing-List: contact ecos-discuss-help@ecos.sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: ecos-discuss-owner@ecos.sourceware.org Received: (qmail 27936 invoked by uid 22791); 19 Oct 2005 19:11:19 -0000 Received: from mailgw2a.lmco.com (HELO mailgw2a.lmco.com) (192.91.147.7) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Wed, 19 Oct 2005 19:11:19 +0000 Received: from emss01g01.ems.lmco.com (relay1.ems.lmco.com [129.197.181.54]) by mailgw2a.lmco.com (8.12.10/8.12.10) with ESMTP id j9JJ9IZo004373; Wed, 19 Oct 2005 15:11:17 -0400 (EDT) Received: from CONVERSION-DAEMON.lmco.com by lmco.com (PMDF V6.1-1X6 #30875) id <0IOM00M01FPKHC@lmco.com>; Wed, 19 Oct 2005 12:05:44 -0700 (PDT) Received: from cui1.lmms.lmco.com ([129.197.1.64]) by lmco.com (PMDF V6.1-1X6 #30875) with ESMTP id <0IOM00K92FPJU8@lmco.com>; Wed, 19 Oct 2005 12:05:43 -0700 (PDT) Received: from lmco.com (obligato.lmms.lmco.com [129.197.113.45]) by cui1.lmms.lmco.com (8.11.7p1+Sun/8.9.2) with ESMTP id j9JJ5gt09812; Wed, 19 Oct 2005 12:05:42 -0700 (PDT) Date: Wed, 19 Oct 2005 19:11:00 -0000 From: Barry Wealand In-reply-to: <1129744855.9769.7.camel@hermes> To: Gary Thomas Cc: eCos Discussion , "Mills, Ted" , "Reagan, John T" Message-id: <4356365E.8060108@lmco.com> MIME-version: 1.0 Content-type: multipart/mixed; boundary="Boundary_(ID_JJN714Y33kdoPPHtuKDuQg)" User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 References: <43561EFF.8030200@lmco.com> <1129744855.9769.7.camel@hermes> Subject: Re: [ECOS] [Fwd: FreeBSD network stack question] X-SW-Source: 2005-10/txt/msg00143.txt.bz2 --Boundary_(ID_JJN714Y33kdoPPHtuKDuQg) Content-type: text/plain; format=flowed; charset=ISO-8859-1 Content-transfer-encoding: 7BIT Content-length: 2280 Here are the target and host applications, with makefiles for each. For the target, edit target.mk and modify ECOS_LIB appropriately. Also edit tool names, if appropriate. The host is a (trivial) server, the target is the client. Let me know if I can provide further information. Barry Wealand barry.wealand@lmco.com Gary Thomas wrote: >On Wed, 2005-10-19 at 10:25 +0000, Barry Wealand wrote: > > >>Hello - >> >>We're working with a MIPS-like target, eCos 2.0, and the FreeBSD network >>stack. I have a simple application that sends UDP messages to a host >>server process, which sends back a short acknowledgement for each. >>Message size can be varied - for the present problem, we're using a size >>of 2K bytes. Of course, such messages must be fragmented before being >>transmitted over an ethernet link. >> >>If we collect a packet trace with tcpdump, we see an ARP request and ARP >>reply, then we see the 2nd segment of the first message - the first >>segment of the first message is never transmitted. A little tracing >>with GDB has shown that: >> >>1. udp_output calls ip_output >>2. ip_output calls ether_output >>3. ether_output calls arpresolve >>4. arpresolve calls arprequest >>5. arprequest sends the ARP request message (recurses into >>ether_output), then returns to arpresolve. >>6. arpresolve apparently operates asynchronously, and returns 0, >>indicating that address resolution is not yet complete. (Meanwhile, in >>due time, an ARP reply is received, providing the needed remote host's >>ethernet address.) >>7. ether_output returns 0 to ip_output, indicating no errors. In >>effect, the first segment has been dropped. >>8. ip_output believes that all is well with the first segment and >>proceeds to send the second. By now, the ARP resolution process has >>completed, and the second segment is transmitted normally. >> >>Is this normal? If not, do you have any idea what we might we be doing >>wrong that could lead to this behavior? >> >> > >I don't think this is normal, but UDP is by design not guaranteed >reliable. > >Would it be possible to post your program(s) so they could be >tested on other systems? > >n.b. eCos 2.0 is now more than 3 years old - quite a lot has happened >in the meantime :-) > > > --Boundary_(ID_JJN714Y33kdoPPHtuKDuQg) Content-type: text/plain; name=udp_server.c Content-transfer-encoding: 7BIT Content-disposition: inline; filename=udp_server.c Content-length: 2490 /* ** udp_server.c ** ** Based on network_interface.c from the netvision program. ** ** Initiated: 9/6/05 */ #include #include #include #include #include #include #include #define MAX_PACKET_SIZE 80000 #define SOCK_PORT 5691 typedef struct { unsigned short sequence; unsigned short flags; unsigned long params; } MessageHeaderType; static int sock_fd, sock_port; static unsigned char buffer[MAX_PACKET_SIZE]; int get_packet(void *packet, int length) /* ** Receive a packet on the datagram socket, and place the packet in . */ { int n, cli_len; int echo_len = sizeof(MessageHeaderType); struct sockaddr_in cli_addr; cli_len = sizeof(cli_addr); n = recvfrom( sock_fd, (char *) packet, length, 0, (struct sockaddr *)&cli_addr, &cli_len ); if(n < 0) { perror("recvfrom"); return -1; } if(sendto( sock_fd, (char *) packet, echo_len, 0, (struct sockaddr *)&cli_addr, cli_len ) != echo_len) { perror("sendto"); return -1; } return n; } int socket_init(void) /* */ { struct sockaddr_in serv_addr; int one = 1; int i; /* ** Fill in some fields - */ sock_port = SOCK_PORT; sock_fd = -1; /* ** Open the UDP socket - */ sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if(sock_fd < 0) { perror("socket"); return -1; } if(setsockopt( sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one) ) < 0) { perror("setsockopt"); return -1; } /* ** Bind our local address so that the client can send to us - */ memset((char *) &serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(sock_port); if(bind( sock_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr) ) < 0) { perror("bind"); return -1; } return 0; } int main() { int i, n, total_bytes = 0; time_t start, run; double elapsed; if(socket_init() < 0) { printf("Error initializing UDP socket\n"); return 1; } printf("Elapsed Time\tTotal Bytes\tThroughput\n"); start = time(NULL); for(i = 1; ; i++) { n = get_packet(buffer, sizeof(buffer)); if(n < 0) { printf("get_packet returned error code %d\n", n); } else { total_bytes += n; } if((i % 1000) == 0) { run = time(NULL); elapsed = difftime(run, start); printf( "%g\t%d\t%g\n", elapsed, total_bytes, (double) total_bytes / elapsed ); } } return 0; } --Boundary_(ID_JJN714Y33kdoPPHtuKDuQg) Content-type: text/plain; name=host.mk Content-transfer-encoding: 7BIT Content-disposition: inline; filename=host.mk Content-length: 121 CC = gcc CCFLAGS = -O2 all : udp_server clean : rm udp_server udp_server : udp_server.c $(CC) $(CCFLAGS) -o $@ $< --Boundary_(ID_JJN714Y33kdoPPHtuKDuQg) Content-type: text/plain; name=udp_client.c Content-transfer-encoding: 7BIT Content-disposition: inline; filename=udp_client.c Content-length: 5614 /* ** File: udp_client.c ** */ #include #include #include #include #include #include #include #include #define SERVER_IP_ADDRESS "10.10.1.10" #define ServerUDPport 5691 #define MAX_MESSAGE_SIZE 80000 static double AckTimeout = 10.0; /* ** Define some local state to be associated with the UDP socket upon ** which all data transfers will take place. */ static int local_sock_fd; static struct sockaddr_in local_sockaddr; static struct sockaddr_in remote_sockaddr; typedef struct { unsigned short sequence; unsigned short flags; unsigned long params; } MessageHeaderType; static char buffer[MAX_MESSAGE_SIZE]; /* ** Function: sendMessage ** ** Purpose: This function sends a message over the ** network to the host and receives the corresponding ** acknowledgement. If the acknowledgement is not ** received within an acceptable time limit, the ** message is retransmitted. This is repeated until ** the acknowledgement is received. ** ** Parameters: ** Name Purpose ** ---- ------- ** message A pointer to the message to be transferred. ** ** length Size of the message. ** ** Returns: Nothing. */ void sendMessage(void *message, int length) { MessageHeaderType ackMsg, *msg = message; static unsigned short sequence = 0; int n; bool xmitRequired = true; msg->sequence = ++sequence; for( ; ; ) { if(xmitRequired) { /* ** Send the message and check for errors - */ n = length; if(sendto( local_sock_fd, message, n, 0, (struct sockaddr *) &remote_sockaddr, sizeof(remote_sockaddr) ) != n) { perror("image_transfer_8bpp::sendMessage: sendto"); _exit(errno); } } /* ** Receive the acknowledgement with an awareness that the operation ** may time out. */ n = recvfrom( local_sock_fd, &ackMsg, sizeof(ackMsg), 0, (struct sockaddr *) 0, (socklen_t *) 0 ); if(n < 0) { if(errno == ETIMEDOUT) { /* ** The recvfrom system call timed out. Begin the process ** again starting with retransmission. */ xmitRequired = true; continue; } else { /* ** The recvfrom system call failed - */ perror("image_transfer_8bpp::sendMessage: recvfrom"); _exit(errno); } } else { if(ackMsg.sequence == sequence) { /* ** We received the correct acknowledgement for the message ** sent. Exit the loop. */ break; } else { /* ** We received a message, but the sequence field does not ** match that of the message we sent. This could be a ** duplicate acknowledgement from an earlier transmission. ** swallow this acknowledgement and attempt to receive ** another, but don't retransmit. */ xmitRequired = false; continue; } } } // end for( ; ; ) } /* ** Function: initialize ** ** Purpose: Perform all initialization required to start up the network ** transfer service for 8-bit-per-pixel image data. This ** includes opening the transfer socket, creating the ** synchronization objects, and creating and starting up the ** server thread. ** ** Parameters: None. ** ** Returns: Nothing. */ void initialize(void) { struct timeval ackTimeout; /* ** Bring up the TCP/IP stack - */ init_all_network_interfaces(); /* ** Open our UDP socket and establish the receive timeout value. */ local_sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if(local_sock_fd < 0) { perror("image_transfer_8bpp::initialize: socket"); _exit(errno); } ackTimeout.tv_sec = (long) AckTimeout; ackTimeout.tv_usec = (long) (1000000.0 * (AckTimeout - (double) ackTimeout.tv_sec)); if(setsockopt( local_sock_fd, SOL_SOCKET, SO_RCVTIMEO, &ackTimeout, sizeof(ackTimeout) ) < 0) { perror("image_transfer_8bpp::initialize: setsockopt"); _exit(errno); } /* ** Now bind the local socket to the correct address and port. */ memset(&local_sockaddr, 0, sizeof(local_sockaddr)); local_sockaddr.sin_family = AF_INET; local_sockaddr.sin_len = sizeof(local_sockaddr); local_sockaddr.sin_port = htons(ServerUDPport); local_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind( local_sock_fd, (struct sockaddr *) &local_sockaddr, sizeof(local_sockaddr) ) < 0) { perror("image_transfer_8bpp::initialize: bind"); _exit(errno); } /* ** Initialize the sockaddr for the remote (server) machine. */ memset(&remote_sockaddr, 0, sizeof(remote_sockaddr)); remote_sockaddr.sin_family = AF_INET; remote_sockaddr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDRESS); remote_sockaddr.sin_port = htons(ServerUDPport); } #define UDP_MAIN_THREAD_PRIORITY 16 static char udp_main_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x10000]; static cyg_thread udp_main_object; static cyg_handle_t udp_main_handle; void udp_main(cyg_addrword_t param) { char userInput[128]; int i, msg_length = 2048; printf("net-speed: A simple net performance test\n\n"); for(i = 0; i < sizeof(buffer); i++) { buffer[i] = (char) i; } initialize(); while(true) { sendMessage(buffer, msg_length); } } void cyg_user_start(void) { cyg_thread_create( UDP_MAIN_THREAD_PRIORITY, udp_main, 0, "UDP main thread", &udp_main_stack[0], sizeof(udp_main_stack), &udp_main_handle, &udp_main_object ); cyg_thread_resume(udp_main_handle); cyg_scheduler_start(); } --Boundary_(ID_JJN714Y33kdoPPHtuKDuQg) Content-type: text/plain; name=target.mk Content-transfer-encoding: 7BIT Content-disposition: inline; filename=target.mk Content-length: 855 TESTS = udp_client ECOS_LIB = /space/ecos-2.0/latest/nga/full/no-assert INCLUDE = . SOURCE = . vpath %.h $(INCLUDE) vpath %.c $(SOURCE) CC = mips-elf-gcc LD = mips-elf-gcc DIS = mips-elf-objdump -d -S $@ > $@.dis SGEN = mips-elf-objcopy -O srec $@ $@.srec CCFLAGS = -g -D__ECOS -I$(ECOS_LIB)/include -I$(INCLUDE) \ -ffunction-sections -fdata-sections -freg-struct-return LDFLAGS = -g -nostartfiles -L$(ECOS_LIB)/lib -Wl,--gc-sections -Wl,--Map -Wl,$@.map LIBS = -Ttarget.ld -nostdlib .C.o : $(CPP) $(CCFLAGS) -c $< .c.o : $(CC) $(CCFLAGS) -c $< .S.o : $(AS) $(ASFLAGS) -c $< %.po : %.o $(PRELINK) -o $@ $< all : $(TESTS) clean : rm -f $(TESTS) *.o *.dis *.map *.srec relink : rm -f $(TESTS) udp_client : udp_client.o $(LD) -o $@ udp_client.o $(LDFLAGS) $(LIBS) $(SGEN) $(DIS) udp_client.o : udp_client.c --Boundary_(ID_JJN714Y33kdoPPHtuKDuQg) Content-Type: text/plain; charset=us-ascii Content-length: 148 -- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss --Boundary_(ID_JJN714Y33kdoPPHtuKDuQg)--