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