From 3ea00af9aa1be0ba11ab52f7978b9388c9919583 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 30 Sep 2013 14:37:04 -0600 Subject: [PATCH] net/net_sendfile: High performance sendfile is now functional. From Max Holtzberg --- ChangeLog | 3 ++ include/nuttx/net/uip/uip-tcp.h | 1 + net/net_sendfile.c | 55 +++++++++++++++++++++------------ net/uip/uip_tcpinput.c | 4 +++ 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9b92745764..5f94183bdd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5684,3 +5684,6 @@ * configs/freedom-kl25z/minnsh: A new configuration that is an experiement to see how small we can get the NuttX footprint. From Carvalho de Assis. (2013-9-30). + * net/net_sendfile: The high performance sendfile logic is + now functional. From Max Holtzberg (2013-9-30). + diff --git a/include/nuttx/net/uip/uip-tcp.h b/include/nuttx/net/uip/uip-tcp.h index c3c800d7bd..80ab0229c1 100644 --- a/include/nuttx/net/uip/uip-tcp.h +++ b/include/nuttx/net/uip/uip-tcp.h @@ -133,6 +133,7 @@ struct uip_conn uint16_t unacked; /* Number bytes sent but not yet ACKed */ uint16_t mss; /* Current maximum segment size for the * connection */ + uint16_t winsize; /* Current window size of the connection */ uint16_t initialmss; /* Initial maximum segment size for the * connection */ uint8_t crefs; /* Reference counts on this instance */ diff --git a/net/net_sendfile.c b/net/net_sendfile.c index a5b2fcddfa..266bb5e08d 100644 --- a/net/net_sendfile.c +++ b/net/net_sendfile.c @@ -148,6 +148,8 @@ static uint16_t ack_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn, { FAR struct sendfile_s *pstate = (FAR struct sendfile_s *)pvpriv; + nllvdbg("flags: %04x\n", flags); + if ((flags & UIP_ACKDATA) != 0) { /* The current acknowledgement number number is the (relative) offset @@ -161,9 +163,29 @@ static uint16_t ack_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn, pstate->snd_acked, pstate->snd_sent, pstate->snd_flen); dev->d_sndlen = 0; + + /* Wake up the waiting thread */ + + sem_post(&pstate->snd_sem); + + flags &= ~UIP_ACKDATA; } - return OK; + /* Check for a loss of connection */ + + else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0) + { + /* Report not connected */ + + nlldbg("Lost connection\n"); + + net_lostconnection(pstate->snd_sock, flags); + pstate->snd_sent = -ENOTCONN; + + sem_post(&pstate->snd_sem); + } + + return flags; } /**************************************************************************** @@ -240,10 +262,8 @@ static uint16_t sendfile_interrupt(FAR struct uip_driver_s *dev, FAR void *pvcon } /* Check if we have "space" in the window */ -#warning REVISIT -#if 0 /* Where is wndsize defined? */ - if ((pstate->snd_sent - pstate->snd_acked + sndlen) < conn->wndsize) -#endif + + if ((pstate->snd_sent - pstate->snd_acked + sndlen) < conn->winsize) { uint32_t seqno; @@ -314,14 +334,11 @@ static uint16_t sendfile_interrupt(FAR struct uip_driver_s *dev, FAR void *pvcon #endif } } -#warning REVISIT -#if 0 /* Where is wndsize defined? */ else { - nlldbg("window full, wait for ack\n"); + nlldbg("Window full, wait for ack\n"); goto wait; } -#endif } /* All data has been send and we are just waiting for ACK or re-transmit @@ -432,8 +449,6 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset, uip_lock_t save; int err; - nlldbg("pid: %d\n", getpid()); - /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) @@ -490,33 +505,33 @@ ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset, /* Get the initial sequence number that will be used */ - state.snd_isn = uip_tcpgetsequence(conn->sndseq); + state.snd_isn = uip_tcpgetsequence(conn->sndseq); /* There is no outstanding, unacknowledged data after this * initial sequence number. */ - conn->unacked = 0; + conn->unacked = 0; /* Set the initial time for calculating timeouts */ #if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK) - state.snd_time = clock_systimer(); + state.snd_time = clock_systimer(); #endif /* Set up the ACK callback in the connection */ - state.snd_ackcb->flags = UIP_ACKDATA; - state.snd_ackcb->priv = (void*)&state; - state.snd_ackcb->event = ack_interrupt; + state.snd_ackcb->flags = UIP_ACKDATA|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; + state.snd_ackcb->priv = (void*)&state; + state.snd_ackcb->event = ack_interrupt; /* Perform the TCP send operation */ do { - state.snd_datacb->flags = UIP_REXMIT|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT; - state.snd_datacb->priv = (void*)&state; - state.snd_datacb->event = sendfile_interrupt; + state.snd_datacb->flags = UIP_REXMIT|UIP_POLL; + state.snd_datacb->priv = (void*)&state; + state.snd_datacb->event = sendfile_interrupt; /* Notify the device driver of the availaibilty of TX data */ diff --git a/net/uip/uip_tcpinput.c b/net/uip/uip_tcpinput.c index 5b40963b6b..e0f3a78194 100644 --- a/net/uip/uip_tcpinput.c +++ b/net/uip/uip_tcpinput.c @@ -298,6 +298,10 @@ reset: found: + /* Update the connection's window size */ + + conn->winsize = BUF->wnd[0] << 8 | BUF->wnd[1]; + flags = 0; /* We do a very naive form of TCP reset processing; we just accept