Take #2. Wrote up negotiation of segsize, passes first smoketest.
Anyone interesting helping to test/comment on the patch?

Tested w/this server: http://tftpd32.jounin.net

-- 
Øyvind Harboe
http://www.zylin.com - eCos ARM & FPGA  developer kit
### Eclipse Workspace Patch 1.0
#P ecos
Index: net/common/current/cdl/net.cdl
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/cdl/net.cdl,v
retrieving revision 1.17
diff -u -r1.17 net.cdl
--- net/common/current/cdl/net.cdl      7 Jan 2007 14:46:55 -0000       1.17
+++ net/common/current/cdl/net.cdl      19 Dec 2007 10:36:38 -0000
@@ -167,6 +167,16 @@
             threads can have precedence over TFTP server processing."
         }
 
+        cdl_option CYGPKG_NET_TFTPD_CLIENT_GET_PACKETSIZE {
+            display "TFTP protocol allows negotiation of bigger packets."
+            flavor  data
+            default_value 512
+            legal_values 512 to 65464
+            description   "
+             tftp blksize egotiation support. >512 byte block sizes improves 
+             tftp GET performance"
+        }
+
         cdl_option CYGPKG_NET_TFTPD_THREAD_STACK_SIZE {
             display "Stack size for TFTP threads."
             flavor  data
Index: net/common/current/include/arpa/tftp.h
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/include/arpa/tftp.h,v
retrieving revision 1.2
diff -u -r1.2 tftp.h
--- net/common/current/include/arpa/tftp.h      7 Aug 2002 14:42:35 -0000       
1.2
+++ net/common/current/include/arpa/tftp.h      19 Dec 2007 10:36:38 -0000
@@ -70,6 +70,7 @@
 #define        DATA    03                      /* data packet */
 #define        ACK     04                      /* acknowledgement */
 #define        ERROR   05                      /* error code */
+#define        OACK    06                      /* option acknowledge */
 
 struct tftphdr {
        short   th_opcode;              /* packet type */
Index: net/common/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/ChangeLog,v
retrieving revision 1.81
diff -u -r1.81 ChangeLog
--- net/common/current/ChangeLog        15 Jan 2007 18:37:52 -0000      1.81
+++ net/common/current/ChangeLog        19 Dec 2007 10:36:38 -0000
@@ -1,3 +1,8 @@
+2007-12-19  Oyvind Harboe <[EMAIL PROTECTED]>
+
+       * src/tftp_client.c, include/arpa/tftp.h, cdl/net.cdl: tftp blksize 
+       negotiation support. >512 byte block sizes improves tftp GET performance
+        
 2007-01-15  Gary Thomas  <[EMAIL PROTECTED]>
 
        * src/dhcp_support.c (dhcp_mgt_entry): Better handling when restarting
Index: net/common/current/src/tftp_client.c
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/common/current/src/tftp_client.c,v
retrieving revision 1.10
diff -u -r1.10 tftp_client.c
--- net/common/current/src/tftp_client.c        16 Sep 2005 14:56:26 -0000      
1.10
+++ net/common/current/src/tftp_client.c        19 Dec 2007 10:36:38 -0000
@@ -57,6 +57,8 @@
 #include <network.h>
 #include <arpa/tftp.h>
 #include <tftp_support.h>
+#include <stdlib.h>
+#include <stdio.h>
 
 #define min(x,y) (x<y ? x : y)
 
@@ -66,14 +68,16 @@
 // On error, *err will hold the reason.
 // This version uses the server name. This can be a name for DNS lookup
 // or a dotty or colony number format for IPv4 or IPv6.
-int tftp_client_get(const char * const filename,
+static int tftp_client_get_inner(char *data,
+                   const char * const filename,
                    const char * const server,
                    const int port,
                    char *buf,
                    int len,
                    const int mode,
                    int * const err) {
-                   
+       
+       int blksize=512;
     int result = 0;
     int s=-1;
     int actual_len, data_len;
@@ -85,7 +89,6 @@
     int error;
 
     struct sockaddr local_addr, from_addr;
-    char data[SEGSIZE+sizeof(struct tftphdr)];
     struct tftphdr *hdr = (struct tftphdr *)data;
     const char *fp;
     char *cp, *bp;
@@ -112,6 +115,13 @@
     }
     while (*fp) *cp++ = *fp++;
     *cp++ = '\0';
+#if CYGPKG_NET_TFTPD_CLIENT_GET_PACKETSIZE>512
+    fp="blksize";
+    while (*fp) *cp++ = *fp++;
+    *cp++ = '\0';
+    cp+=sprintf(cp, "%d", CYGPKG_NET_TFTPD_CLIENT_GET_PACKETSIZE);
+    *cp++ = '\0';
+#endif
 
     memset(&hints,0,sizeof(hints));
     hints.ai_family = PF_UNSPEC;
@@ -214,15 +224,34 @@
               }
             }
          } else {
-           recv_len = sizeof(data);
+           recv_len = blksize;
            from_len = sizeof(from_addr);
-           if ((data_len = recvfrom(s, &data, recv_len, 0, 
+           if ((data_len = recvfrom(s, data, recv_len, 0, 
                                     &from_addr, &from_len)) < 0) {
              // What happened?
              *err = TFTP_NETERR;
              goto out;
            }
-           if (ntohs(hdr->th_opcode) == DATA) {
+           if (ntohs(hdr->th_opcode) == OACK) {
+               // We can have only *one* option, the one we sent..
+               if (strncmp(data+2, "blksize", from_len)==0)
+               {
+                       blksize=atol(data+2+strlen("blksize")+1);
+               } else
+               {
+                       // option ignored, use default.
+               }
+                     // Send out the ACK
+                     hdr->th_opcode = htons(ACK);
+                     hdr->th_block = htons(last_good_block);
+                     if (sendto(s, data, 4 /* FIXME */, 0, 
+                                &from_addr, from_len) < 0) {
+                       // Problem sending request
+                       *err = TFTP_NETERR;
+                       goto out;
+                     }
+                     
+           } else if (ntohs(hdr->th_opcode) == DATA) {
              actual_len = 0;
              if (ntohs(hdr->th_block) == (last_good_block+1)) {
                // Consume this data
@@ -244,7 +273,7 @@
                 // To prevent an out-of-sequence packet from
                 // terminating transmission prematurely, set
                 // actual_len to a full size packet.
-               actual_len = SEGSIZE;
+               actual_len = blksize;
              }
              // Send out the ACK
              hdr->th_opcode = htons(ACK);
@@ -256,7 +285,8 @@
                goto out;
              }
               // A short packet marks the end of the file.
-             if ((actual_len >= 0) && (actual_len < SEGSIZE)) {
+                 /* 4 = Sizeof TFTP header */
+             if ((actual_len >= 0) && (actual_len < (blksize-4))) {
                // End of data
                close(s);
                freeaddrinfo(res);
@@ -290,6 +320,35 @@
     freeaddrinfo(res);
     return -1;
 }
+
+
+int tftp_client_get(const char * const filename,
+                   const char * const server,
+                   const int port,
+                   char *buf,
+                   int len,
+                   const int mode,
+                   int * const err) {
+       int result;
+#if CYGPKG_NET_TFTPD_CLIENT_GET_PACKETSIZE>512
+    char *data = malloc(CYGPKG_NET_TFTPD_CLIENT_GET_PACKETSIZE+sizeof(struct 
tftphdr));
+    if (data==NULL)
+    {
+       *err=TFTP_ENOSPACE;
+       return -1;
+    }
+#else
+    char data[SEGSIZE+sizeof(struct tftphdr)];
+#endif
+    result=tftp_client_get_inner(data, filename, server, port, buf, len, mode, 
err);
+    
+#if CYGPKG_NET_TFTPD_CLIENT_GET_PACKETSIZE>512
+    free(data);
+#endif
+    
+    return result;
+}
+
 //
 // Read a file from a host into a local buffer.  Returns the
 // number of bytes actually read, or (-1) if an error occurs.
-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

Reply via email to