Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Revision:
128:ae39e6e81531
Parent:
123:dd26752a4538
Child:
131:4758606c9316
--- a/modules/pico_tcp.c	Wed Dec 04 08:39:16 2013 +0000
+++ b/modules/pico_tcp.c	Thu Dec 05 08:31:32 2013 +0000
@@ -150,8 +150,8 @@
 	}
 	else
 	{
-	  struct tcp_input_segment dummy={.seq=long_be(seq)};
-	  // TODO: Check if long_be(seq) is needed
+	  struct tcp_input_segment dummy={.seq=seq};
+
 	  return pico_tree_findKey(&tq->pool,&dummy);
 	}
 
@@ -336,7 +336,7 @@
   return ret;
 }
 
-static int release_all_until(struct pico_tcp_queue *q, uint32_t seq,uint32_t * timestamp)
+static int release_all_until(struct pico_tcp_queue *q, uint32_t seq,pico_time * timestamp)
 {
   void *f = NULL, *tmp __attribute__((unused));
   struct pico_tree_node * idx, * temp;
@@ -440,7 +440,7 @@
 
 static void tcp_add_options(struct pico_socket_tcp *ts, struct pico_frame *f, uint16_t flags, uint16_t optsiz)
 {
-  uint32_t tsval = long_be(pico_tick);
+  uint32_t tsval = long_be((uint32_t)pico_tick);
   uint32_t tsecr = long_be(ts->ts_nxt);
   uint32_t i = 0;
   f->start = f->transport_hdr + PICO_SIZE_TCPHDR;
@@ -460,7 +460,7 @@
   f->start[i++] = PICO_TCPOPTLEN_WS;
   f->start[i++] = (uint8_t)(ts->wnd_scale);
 
-  if (optsiz >= 12) {
+  if ((flags & PICO_TCP_SYN) || ts->ts_ok) {
     f->start[i++] = PICO_TCP_OPTION_TIMESTAMP;
     f->start[i++] = PICO_TCPOPTLEN_TIMESTAMP;
     memcpy(f->start + i, &tsval, 4);
@@ -854,7 +854,7 @@
 }
 
 int pico_tcp_initconn(struct pico_socket *s);
-static void initconn_retry(uint32_t when, void *arg)
+static void initconn_retry(pico_time when, void *arg)
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)arg;
   IGNORE_PARAMETER(when);
@@ -1209,7 +1209,7 @@
       pkt = next_segment(&t->tcpq_in, pkt);
       continue;
     }
-    if(pkt->seq == (right + 1)) {
+    if(pkt->seq == right) {
       right += pkt->payload_len;
       pkt = next_segment(&t->tcpq_in, pkt);
       continue;
@@ -1256,20 +1256,25 @@
         nxt = peek_segment(&t->tcpq_in, t->rcv_nxt);
         while(nxt) {
           tcp_dbg("scrolling rcv_nxt...%08x\n", t->rcv_nxt);
-          t->rcv_nxt += f->payload_len;
+          t->rcv_nxt += nxt->payload_len;
           nxt = peek_segment(&t->tcpq_in, t->rcv_nxt);
         }
         t->sock.ev_pending |= PICO_SOCK_EV_RD;
-        t->rcv_nxt = SEQN(f) + f->payload_len;
       } else {
         tcp_dbg("TCP> lo segment. Uninteresting retransmission. (exp: %x got: %x)\n", t->rcv_nxt, SEQN(f));
       }
     } else {
       tcp_dbg("TCP> hi segment. Possible packet loss. I'll dupack this. (exp: %x got: %x)\n", t->rcv_nxt, SEQN(f));
       if (t->sack_ok) {
-        tcp_sack_prepare(t);
+    	struct tcp_input_segment * input = segment_from_frame(f);
+    	if(input && pico_enqueue_segment(&t->tcpq_in,input) <= 0){
+    		// failed to enqueue, destroy segment
+    		pico_free(input->payload);
+    		pico_free(input);
+    	}
+    	tcp_sack_prepare(t);
       }
-    }
+   }
     /* In either case, ack til recv_nxt. */
     if ( ((t->sock.state & PICO_SOCKET_STATE_TCP) != PICO_SOCKET_STATE_TCP_CLOSE_WAIT) && ((t->sock.state & PICO_SOCKET_STATE_TCP) != PICO_SOCKET_STATE_TCP_SYN_SENT) && ((t->sock.state & PICO_SOCKET_STATE_TCP) != PICO_SOCKET_STATE_TCP_SYN_RECV)) {
       //tcp_dbg("SENDACK CALLED FROM OUTSIDE tcp_synack, state %x\n",t->sock.state);
@@ -1284,7 +1289,7 @@
   }
 }
 
-static int tcp_ack_advance_una(struct pico_socket_tcp *t, struct pico_frame *f, uint32_t * timestamp)
+static int tcp_ack_advance_una(struct pico_socket_tcp *t, struct pico_frame *f, pico_time * timestamp)
 {
   int ret =  release_all_until(&t->tcpq_out, ACKN(f),timestamp);
   if (ret > 0)
@@ -1292,7 +1297,7 @@
   return ret;
 }
 
-static uint16_t time_diff(uint32_t a, uint32_t b)
+static uint16_t time_diff(pico_time a, pico_time b)
 {
   if (a >= b)
     return (uint16_t)(a - b);
@@ -1363,12 +1368,12 @@
   tcp_dbg("TCP_CWND, %lu, %u, %u, %u\n", pico_tick, t->cwnd, t->ssthresh, t->in_flight);
 }
 
-static void add_retransmission_timer(struct pico_socket_tcp *t, uint32_t next_ts);
-static void tcp_retrans_timeout(uint32_t val, void *sock)
+static void add_retransmission_timer(struct pico_socket_tcp *t, pico_time next_ts);
+static void tcp_retrans_timeout(pico_time val, void *sock)
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *) sock;
   struct pico_frame *f = NULL;
-  uint32_t limit = val - t->rto;
+  pico_time limit = val - t->rto;
   if( t->sock.net && ((t->sock.state & 0xFF00) == PICO_SOCKET_STATE_TCP_ESTABLISHED
   		|| (t->sock.state & 0xFF00) == PICO_SOCKET_STATE_TCP_CLOSE_WAIT) && t->backoff < PICO_TCP_MAX_RETRANS)
   {
@@ -1423,7 +1428,7 @@
 	}
 }
 
-static void add_retransmission_timer(struct pico_socket_tcp *t, uint32_t next_ts)
+static void add_retransmission_timer(struct pico_socket_tcp *t, pico_time next_ts)
 {
   struct pico_tree_node * index;
 
@@ -1525,7 +1530,7 @@
   struct pico_tcp_hdr *hdr = (struct pico_tcp_hdr *) f->transport_hdr;
   uint32_t rtt = 0;
   uint16_t acked = 0;
-  uint32_t acked_timestamp = 0;
+  pico_time acked_timestamp = 0;
   uint8_t restart_tmr = 0;
 
   struct pico_frame *una = NULL;
@@ -1695,7 +1700,7 @@
   return 0;
 }
 
-static void tcp_deltcb(uint32_t when, void *arg)
+static void tcp_deltcb(pico_time when, void *arg)
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)arg;
   IGNORE_PARAMETER(when);
@@ -2140,7 +2145,7 @@
   return ret;
 }
 
-static void tcp_send_keepalive(uint32_t when, void *_t)
+static void tcp_send_keepalive(pico_time when, void *_t)
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)_t;
   IGNORE_PARAMETER(when);