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:
51:ab4529a384a6
Parent:
49:4b404dd2c97a
Child:
57:5d5b84784344
--- a/modules/pico_tcp.c	Tue Aug 06 08:04:03 2013 +0000
+++ b/modules/pico_tcp.c	Mon Sep 02 08:02:21 2013 +0000
@@ -23,8 +23,8 @@
 
 #define PICO_TCP_RTO_MIN 10
 #define PICO_TCP_RTO_MAX 120000
-#define PICO_TCP_IW          2
-#define PICO_TCP_SYN_TO  1000
+#define PICO_TCP_IW 		 2
+#define PICO_TCP_SYN_TO	 1000
 #define PICO_TCP_ZOMBIE_TO 30000
 
 #define PICO_TCP_MAX_CONNECT_RETRIES 7
@@ -54,8 +54,8 @@
 
 struct tcp_port_pair
 {
-    uint16_t local;
-    uint16_t remote;
+	uint16_t local;
+	uint16_t remote;
 };
 
 #ifdef PICO_SUPPORT_MUTEX
@@ -107,7 +107,7 @@
 static struct pico_frame *peek_segment(struct pico_tcp_queue *tq, uint32_t seq)
 {
   struct pico_tcp_hdr H;
-  struct pico_frame f = {};
+  struct pico_frame f = {0};
   f.transport_hdr = (uint8_t *) (&H);
   H.seq = long_be(seq);
 
@@ -128,13 +128,13 @@
 
 static int pico_enqueue_segment(struct pico_tcp_queue *tq, struct pico_frame *f)
 {
-    int ret = -1;
+	int ret = -1;
   if (f->payload_len <= 0) {
     tcp_dbg("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TRIED TO ENQUEUE INVALID SEGMENT!\n");
     //abort();
     return -1;
   }
-    LOCK(Mutex);
+	LOCK(Mutex);
   if ((tq->size + f->payload_len) > tq->max_size)
   {
     ret = 0;
@@ -229,8 +229,8 @@
 };
 
 /* Queues */
-static struct pico_queue tcp_in = {};
-static struct pico_queue tcp_out = {};
+static struct pico_queue tcp_in = {0};
+static struct pico_queue tcp_out = {0};
 
 /* If Nagle enabled, this function can make 1 new segment from smaller segments in hold queue */
 static struct pico_frame * pico_hold_segment_make(struct pico_socket_tcp *t);
@@ -311,6 +311,7 @@
 {
   struct pico_tcp_hdr *hdr;
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)f->sock;
+  IGNORE_PARAMETER(self);
   hdr = (struct pico_tcp_hdr *)f->transport_hdr;
 
   if (f->payload_len > 0) {
@@ -476,7 +477,7 @@
   struct pico_frame *f;
   struct pico_tree_node * index, * temp;
   int cmp;
-  int count = 0;
+  uint16_t count = 0;
 
   pico_tree_foreach_safe(index,&t->tcpq_out.pool,temp){
     f = index->keyValue;
@@ -531,7 +532,7 @@
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)f->sock;
   uint8_t *opt = f->transport_hdr + PICO_SIZE_TCPHDR;
-  int i = 0;
+  uint32_t i = 0;
   f->timestamp = 0;
   while (i < (f->transport_len - PICO_SIZE_TCPHDR)) {
     uint8_t type =  opt[i++];
@@ -720,7 +721,7 @@
       in_frame_off = 0;
       in_frame_len = f->payload_len;
     }
-    if ((in_frame_len + tot_rd_len) > len) {
+    if ((in_frame_len + tot_rd_len) > (uint32_t)len) {
       in_frame_len = len - tot_rd_len;
     }
 
@@ -731,7 +732,7 @@
     tot_rd_len += in_frame_len;
     t->rcv_processed += in_frame_len;
 
-    if ((in_frame_len == 0) || (in_frame_len == f->payload_len)) {
+    if ((in_frame_len == 0u) || (in_frame_len == (uint32_t)f->payload_len)) {
       pico_discard_segment(&t->tcpq_in, f);
     }
   }
@@ -748,6 +749,7 @@
 static void initconn_retry(unsigned long when, void *arg)
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)arg;
+  IGNORE_PARAMETER(when);
   if (TCPSTATE(&t->sock) == PICO_SOCKET_STATE_TCP_SYN_SENT) {
     if (t->backoff > PICO_TCP_MAX_CONNECT_RETRIES) {
       tcp_dbg("TCP> Connection timeout. \n");
@@ -1255,56 +1257,56 @@
   unsigned long limit = val - t->rto;
   struct pico_tcp_hdr *hdr;
   if( t->sock.net && ((t->sock.state & 0xFF00) == PICO_SOCKET_STATE_TCP_ESTABLISHED
-        || (t->sock.state & 0xFF00) == PICO_SOCKET_STATE_TCP_CLOSE_WAIT) )
+  		|| (t->sock.state & 0xFF00) == PICO_SOCKET_STATE_TCP_CLOSE_WAIT) )
   {
-        tcp_dbg("\n\nTIMEOUT! backoff = %d\n", t->backoff);
-        /* was timer cancelled? */
-        if (t->timer_running == 0) {
-            add_retransmission_timer(t, 0);
-            return;
-        }
-        t->timer_running--;
+		tcp_dbg("TIMEOUT! backoff = %d\n", t->backoff);
+		/* was timer cancelled? */
+		if (t->timer_running == 0) {
+			add_retransmission_timer(t, 0);
+			return;
+		}
+		t->timer_running--;
 
-        f = first_segment(&t->tcpq_out);
-        while (f) {
-            if ((t->x_mode == PICO_TCP_WINDOW_FULL) ||
-                    ((f->timestamp != 0) && (f->timestamp <= limit))) {
-                struct pico_frame *cpy;
-                hdr = (struct pico_tcp_hdr *)f->transport_hdr;
-                tcp_dbg("TCP BLACKOUT> TIMED OUT (output) frame %08x, len= %d rto=%d Win full: %d frame flags: %04x\n", SEQN(f), f->payload_len, t->rto, t->x_mode == PICO_TCP_WINDOW_FULL, f->flags);
-                if ((t->x_mode != PICO_TCP_WINDOW_FULL) ) {
-                    t->x_mode = PICO_TCP_BLACKOUT;
-                    tcp_dbg("Mode: Blackout.\n");
-                    t->cwnd = PICO_TCP_IW;
-                    t->in_flight = 0;
-                }
-                f->timestamp = pico_tick;
-                tcp_add_options(t, f, 0, f->transport_len - f->payload_len - PICO_SIZE_TCPHDR);
-                hdr->rwnd = short_be(t->wnd);
-                hdr->flags |= PICO_TCP_PSH;
-                hdr->ack = long_be(t->rcv_nxt);
-                hdr->crc = 0;
-                hdr->crc = short_be(pico_tcp_checksum_ipv4(f));
-                /* TCP: ENQUEUE to PROTO ( retransmit )*/
-                cpy = pico_frame_copy(f);
-                if (pico_enqueue(&tcp_out, cpy) > 0) {
-                    t->backoff++;
-                    add_retransmission_timer(t, (t->rto << t->backoff) + pico_tick);
-                    tcp_dbg("TCP_CWND, %lu, %u, %u, %u\n", pico_tick, t->cwnd, t->ssthresh, t->in_flight);
-                    return;
-                } else {
-                    add_retransmission_timer(t, (t->rto << t->backoff) + pico_tick);
-                    pico_frame_discard(cpy);
-                }
-            }
-            f = next_segment(&t->tcpq_out, f);
-        }
-        t->backoff = 0;
-        add_retransmission_timer(t, 0);
-        if (t->tcpq_out.size < t->tcpq_out.max_size)
-             t->sock.ev_pending |= PICO_SOCK_EV_WR;
-        return;
-    }
+		f = first_segment(&t->tcpq_out);
+		while (f) {
+			if ((t->x_mode == PICO_TCP_WINDOW_FULL) ||
+					((f->timestamp != 0) && (f->timestamp <= limit))) {
+				struct pico_frame *cpy;
+				hdr = (struct pico_tcp_hdr *)f->transport_hdr;
+				tcp_dbg("TCP BLACKOUT> TIMED OUT (output) frame %08x, len= %d rto=%d Win full: %d frame flags: %04x\n", SEQN(f), f->payload_len, t->rto, t->x_mode == PICO_TCP_WINDOW_FULL, f->flags);
+				if ((t->x_mode != PICO_TCP_WINDOW_FULL) ) {
+					t->x_mode = PICO_TCP_BLACKOUT;
+					tcp_dbg("Mode: Blackout.\n");
+					t->cwnd = PICO_TCP_IW;
+					t->in_flight = 0;
+				}
+				f->timestamp = pico_tick;
+				tcp_add_options(t, f, 0, f->transport_len - f->payload_len - PICO_SIZE_TCPHDR);
+				hdr->rwnd = short_be(t->wnd);
+				hdr->flags |= PICO_TCP_PSH;
+				hdr->ack = long_be(t->rcv_nxt);
+				hdr->crc = 0;
+				hdr->crc = short_be(pico_tcp_checksum_ipv4(f));
+				/* TCP: ENQUEUE to PROTO ( retransmit )*/
+				cpy = pico_frame_copy(f);
+				if (pico_enqueue(&tcp_out, cpy) > 0) {
+					t->backoff++;
+					add_retransmission_timer(t, (t->rto << t->backoff) + pico_tick);
+					tcp_dbg("TCP_CWND, %lu, %u, %u, %u\n", pico_tick, t->cwnd, t->ssthresh, t->in_flight);
+					return;
+				} else {
+					add_retransmission_timer(t, (t->rto << t->backoff) + pico_tick);
+					pico_frame_discard(cpy);
+				}
+			}
+			f = next_segment(&t->tcpq_out, f);
+		}
+		t->backoff = 0;
+		add_retransmission_timer(t, 0);
+		if (t->tcpq_out.size < t->tcpq_out.max_size)
+			 t->sock.ev_pending |= PICO_SOCK_EV_WR;
+		return;
+	}
 }
 
 static void add_retransmission_timer(struct pico_socket_tcp *t, unsigned long next_ts)
@@ -1404,7 +1406,7 @@
     tcp_dbg("%08x %d%s\n", cur, cur_f->payload_len, info);
 
   }
-  tcp_dbg("SND_NXT is %08x, snd_LAST is %08x", nxt, t->snd_last);
+  tcp_dbg("SND_NXT is %08x, snd_LAST is %08x\n", nxt, t->snd_last);
   tcp_dbg("===================================\n");
   tcp_dbg("\n\n");
 }
@@ -1416,7 +1418,7 @@
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)s;
   struct pico_tcp_hdr *hdr = (struct pico_tcp_hdr *) f->transport_hdr;
   uint32_t rtt = 0;
-  int acked = 0;
+  uint16_t acked = 0;
   struct pico_frame *una = NULL;
   if ((hdr->flags & PICO_TCP_ACK) == 0)
     return -1;
@@ -1558,7 +1560,8 @@
 
 static int tcp_finwaitack(struct pico_socket *s, struct pico_frame *f)
 {
-  tcp_dbg("RECEIVED ACK IN FIN_WAIT1\nTCP> IN STATE FIN_WAIT2\n");
+  tcp_dbg("RECEIVED ACK IN FIN_WAIT1\n");
+  tcp_dbg("TCP> IN STATE FIN_WAIT2\n");
 
   /* acking part */
   tcp_ack(s,f);
@@ -1572,6 +1575,8 @@
 static void tcp_deltcb(unsigned long when, void *arg)
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)arg;
+  IGNORE_PARAMETER(when);
+
   if (TCPSTATE(&t->sock) == PICO_SOCKET_STATE_TCP_TIME_WAIT) {
     tcp_dbg("TCP> state: time_wait, final timer expired, going to closed state\n");
     /* update state */
@@ -1628,6 +1633,7 @@
 
 static int tcp_lastackwait(struct pico_socket *s, struct pico_frame *f)
 {
+	IGNORE_PARAMETER(f);
   tcp_dbg("TCP> state: last_ack, received ack, to closed\n");
   s->state &= 0x00FFU;
   s->state |= PICO_SOCKET_STATE_TCP_CLOSED;
@@ -1770,17 +1776,17 @@
     tcp_ack(s,f);
   if (seq_compare(SEQN(f), t->rcv_nxt) == 0) {
     /* received FIN, increase ACK nr */
-    t->rcv_nxt = long_be(hdr->seq) + 1;
-        s->state &= 0x00FFU;
-        s->state |= PICO_SOCKET_STATE_TCP_CLOSE_WAIT;
-        /* set SHUT_REMOTE */
+  	t->rcv_nxt = long_be(hdr->seq) + 1;
+		s->state &= 0x00FFU;
+		s->state |= PICO_SOCKET_STATE_TCP_CLOSE_WAIT;
+		/* set SHUT_REMOTE */
     s->state |= PICO_SOCKET_STATE_SHUT_REMOTE;
       tcp_dbg("TCP> Close-wait\n");
 
     if (s->wakeup){
       if(f->payload_len>0){
-        struct pico_socket_tcp *t = (struct pico_socket_tcp *)s;
-        t->sock.ev_pending |=PICO_SOCK_EV_CLOSE;
+        struct pico_socket_tcp *_t = (struct pico_socket_tcp *)s;
+        _t->sock.ev_pending |=PICO_SOCK_EV_CLOSE;
       }else
         s->wakeup(PICO_SOCK_EV_CLOSE, s);
     }
@@ -1798,6 +1804,7 @@
 static int tcp_rcvfin(struct pico_socket *s, struct pico_frame *f)
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)s;
+  IGNORE_PARAMETER(f);
   tcp_dbg("TCP> Received FIN in FIN_WAIT1\n");
   s->state &= 0x00FFU;
   s->state |= PICO_SOCKET_STATE_TCP_CLOSING;
@@ -1811,6 +1818,8 @@
 static int tcp_finack(struct pico_socket *s, struct pico_frame *f)
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)s;
+  IGNORE_PARAMETER(f);
+
   tcp_dbg("TCP> ENTERED finack\n");
   t->rcv_nxt++;
   /* send ACK */
@@ -1989,40 +1998,42 @@
 static void tcp_send_keepalive(unsigned long when, void *_t)
 {
   struct pico_socket_tcp *t = (struct pico_socket_tcp *)_t;
-  tcp_dbg("\n\nSending keepalive (%d), [State = %d]...\n", t->backoff,t->sock.state );
+  IGNORE_PARAMETER(when);
+  tcp_dbg("Sending keepalive (%d), [State = %d]...\n", t->backoff,t->sock.state );
   if( t->sock.net && ((t->sock.state & 0xFF00) == PICO_SOCKET_STATE_TCP_ESTABLISHED) )
   {
-        tcp_send_ack(t);
+		tcp_send_ack(t);
 
-        if (t->keepalive_timer_running > 0) {
-            t->keepalive_timer_running--;
-        }
+		if (t->keepalive_timer_running > 0) {
+			t->keepalive_timer_running--;
+		}
 
-        if (t->keepalive_timer_running == 0) {
-            t->keepalive_timer_running++;
-            tcp_dbg("[Self] Adding timer(retransmit keepalive)\n");
-            pico_timer_add(t->rto << (++t->backoff), tcp_send_keepalive, t);
-        }
+		if (t->keepalive_timer_running == 0) {
+			t->keepalive_timer_running++;
+			tcp_dbg("[Self] Adding timer(retransmit keepalive)\n");
+			pico_timer_add(t->rto << (++t->backoff), tcp_send_keepalive, t);
+		}
   }
 }
 
 void zombie_timer(unsigned long time, void *param)
 {
-    struct tcp_port_pair * ports = (struct tcp_port_pair *)param;
-    if(ports)
-    {
-        struct pico_socket_tcp * t = (struct pico_socket_tcp *)pico_sockets_find(ports->local,ports->remote);
-        if(t)
-        {
-            (t->sock).state &= 0x00FFU;
-            (t->sock).state |= PICO_SOCKET_STATE_TCP_CLOSED;
-            (t->sock).state &= 0xFF00U;
-            (t->sock).state |= PICO_SOCKET_STATE_CLOSED;
-            tcp_dbg("Deleting zombie socket %p\n",param);
-            pico_socket_del(&t->sock);
-        }
-        pico_free(ports);
-    }
+	struct tcp_port_pair * ports = (struct tcp_port_pair *)param;
+	IGNORE_PARAMETER(time);
+	if(ports)
+	{
+		struct pico_socket_tcp * t = (struct pico_socket_tcp *)pico_sockets_find(ports->local,ports->remote);
+		if(t)
+		{
+			(t->sock).state &= 0x00FFU;
+			(t->sock).state |= PICO_SOCKET_STATE_TCP_CLOSED;
+			(t->sock).state &= 0xFF00U;
+			(t->sock).state |= PICO_SOCKET_STATE_CLOSED;
+			tcp_dbg("Deleting zombie socket %p\n",param);
+			pico_socket_del(&t->sock);
+		}
+		pico_free(ports);
+	}
 }
 
 int pico_tcp_output(struct pico_socket *s, int loop_score)
@@ -2094,9 +2105,9 @@
       s->state &= 0x00FFU;
       s->state |= PICO_SOCKET_STATE_TCP_FIN_WAIT1;
     } else if ((s->state & PICO_SOCKET_STATE_TCP) == PICO_SOCKET_STATE_TCP_CLOSE_WAIT) {
-        struct tcp_port_pair *pair = (struct tcp_port_pair *)pico_zalloc(sizeof(struct tcp_port_pair));
-        pair->local = s->local_port;
-        pair->remote = s->remote_port;
+    	struct tcp_port_pair *pair = (struct tcp_port_pair *)pico_zalloc(sizeof(struct tcp_port_pair));
+    	pair->local = s->local_port;
+    	pair->remote = s->remote_port;
       /* send fin if queue empty and in state shut local (write) */
       tcp_send_fin(t);
       /* change tcp state to LAST_ACK */
@@ -2176,13 +2187,14 @@
   struct pico_socket_tcp *t = (struct pico_socket_tcp *) f->sock;
   struct pico_frame *f_new;
   int total_len = 0;
+  IGNORE_PARAMETER(self);
 
   hdr->trans.sport = t->sock.local_port;
   hdr->trans.dport = t->sock.remote_port;
   hdr->seq = long_be(t->snd_last + 1);
   hdr->len = (f->payload - f->transport_hdr) << 2 | t->jumbo;
 
-  if (f->payload_len > (t->tcpq_out.max_size - t->tcpq_out.size))
+  if ((uint32_t)f->payload_len > (uint32_t)(t->tcpq_out.max_size - t->tcpq_out.size))
     t->sock.ev_pending &= (~PICO_SOCK_EV_WR);
 
   /***************************************************************************/