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.

Committer:
tass
Date:
Thu Jan 28 15:12:00 2016 +0100
Revision:
155:a70f34550c34
Parent:
154:6c0e92a80c4a
Adding TCP flag for FIN.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
tass 152:a3d286bf94e5 2 PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
TASS Belgium NV 131:4758606c9316 5 .
tass 68:0847e35d08a6 6
TASS Belgium NV 131:4758606c9316 7 Authors: Daniele Lacamera
TASS Belgium NV 131:4758606c9316 8 *********************************************************************/
tass 68:0847e35d08a6 9
tass 68:0847e35d08a6 10
tass 68:0847e35d08a6 11 #include "pico_config.h"
tass 68:0847e35d08a6 12 #include "pico_frame.h"
tass 152:a3d286bf94e5 13 #include "pico_protocol.h"
tass 152:a3d286bf94e5 14 #include "pico_stack.h"
tass 68:0847e35d08a6 15
tass 68:0847e35d08a6 16 #ifdef PICO_SUPPORT_DEBUG_MEMORY
tass 68:0847e35d08a6 17 static int n_frames_allocated;
tass 68:0847e35d08a6 18 #endif
tass 68:0847e35d08a6 19
tass 68:0847e35d08a6 20 /** frame alloc/dealloc/copy **/
tass 68:0847e35d08a6 21 void pico_frame_discard(struct pico_frame *f)
tass 68:0847e35d08a6 22 {
tass picotcp@tass.be 149:5f4cb161cec3 23 if (!f)
tass picotcp@tass.be 149:5f4cb161cec3 24 return;
tass picotcp@tass.be 149:5f4cb161cec3 25
TASS Belgium NV 131:4758606c9316 26 (*f->usage_count)--;
tass 154:6c0e92a80c4a 27 if (*f->usage_count == 0) {
tass 152:a3d286bf94e5 28 if (f->flags & PICO_FRAME_FLAG_EXT_USAGE_COUNTER)
tass 152:a3d286bf94e5 29 PICO_FREE(f->usage_count);
tass 152:a3d286bf94e5 30
tass 68:0847e35d08a6 31 #ifdef PICO_SUPPORT_DEBUG_MEMORY
TASS Belgium NV 131:4758606c9316 32 dbg("Discarded buffer @%p, caller: %p\n", f->buffer, __builtin_return_address(3));
TASS Belgium NV 131:4758606c9316 33 dbg("DEBUG MEMORY: %d frames in use.\n", --n_frames_allocated);
tass 68:0847e35d08a6 34 #endif
tass 152:a3d286bf94e5 35 if (!(f->flags & PICO_FRAME_FLAG_EXT_BUFFER))
tass 152:a3d286bf94e5 36 PICO_FREE(f->buffer);
tass 152:a3d286bf94e5 37 else if (f->notify_free)
tass 152:a3d286bf94e5 38 f->notify_free(f->buffer);
tass 152:a3d286bf94e5 39
TASS Belgium NV 131:4758606c9316 40 if (f->info)
tass picotcp@tass.be 149:5f4cb161cec3 41 PICO_FREE(f->info);
TASS Belgium NV 131:4758606c9316 42 }
TASS Belgium NV 131:4758606c9316 43
tass 68:0847e35d08a6 44 #ifdef PICO_SUPPORT_DEBUG_MEMORY
TASS Belgium NV 131:4758606c9316 45 else {
TASS Belgium NV 131:4758606c9316 46 dbg("Removed frame @%p(copy), usage count now: %d\n", f, *f->usage_count);
TASS Belgium NV 131:4758606c9316 47 }
tass 68:0847e35d08a6 48 #endif
tass picotcp@tass.be 149:5f4cb161cec3 49 PICO_FREE(f);
tass 68:0847e35d08a6 50 }
tass 68:0847e35d08a6 51
tass 68:0847e35d08a6 52 struct pico_frame *pico_frame_copy(struct pico_frame *f)
tass 68:0847e35d08a6 53 {
tass picotcp@tass.be 149:5f4cb161cec3 54 struct pico_frame *new = PICO_ZALLOC(sizeof(struct pico_frame));
TASS Belgium NV 131:4758606c9316 55 if (!new)
TASS Belgium NV 131:4758606c9316 56 return NULL;
TASS Belgium NV 131:4758606c9316 57
TASS Belgium NV 131:4758606c9316 58 memcpy(new, f, sizeof(struct pico_frame));
TASS Belgium NV 131:4758606c9316 59 *(new->usage_count) += 1;
tass 68:0847e35d08a6 60 #ifdef PICO_SUPPORT_DEBUG_MEMORY
TASS Belgium NV 131:4758606c9316 61 dbg("Copied frame @%p, into %p, usage count now: %d\n", f, new, *new->usage_count);
tass 68:0847e35d08a6 62 #endif
TASS Belgium NV 131:4758606c9316 63 new->next = NULL;
TASS Belgium NV 131:4758606c9316 64 return new;
tass 68:0847e35d08a6 65 }
tass 68:0847e35d08a6 66
tass 68:0847e35d08a6 67
tass 152:a3d286bf94e5 68 static struct pico_frame *pico_frame_do_alloc(uint32_t size, int zerocopy, int ext_buffer)
tass 68:0847e35d08a6 69 {
tass picotcp@tass.be 149:5f4cb161cec3 70 struct pico_frame *p = PICO_ZALLOC(sizeof(struct pico_frame));
tass 152:a3d286bf94e5 71 uint32_t frame_buffer_size = size;
TASS Belgium NV 131:4758606c9316 72 if (!p)
TASS Belgium NV 131:4758606c9316 73 return NULL;
TASS Belgium NV 131:4758606c9316 74
tass 152:a3d286bf94e5 75 if (ext_buffer && !zerocopy) {
tass 152:a3d286bf94e5 76 /* external buffer implies zerocopy flag! */
tass 152:a3d286bf94e5 77 PICO_FREE(p);
tass 152:a3d286bf94e5 78 return NULL;
tass 152:a3d286bf94e5 79 }
tass 152:a3d286bf94e5 80
tass picotcp@tass.be 149:5f4cb161cec3 81 if (!zerocopy) {
tass 152:a3d286bf94e5 82 unsigned int align = size % sizeof(uint32_t);
tass 152:a3d286bf94e5 83 /* Ensure that usage_count starts on an aligned address */
tass 152:a3d286bf94e5 84 if (align) {
tass 152:a3d286bf94e5 85 frame_buffer_size += (uint32_t)sizeof(uint32_t) - align;
tass 152:a3d286bf94e5 86 }
tass 152:a3d286bf94e5 87
tass 152:a3d286bf94e5 88 p->buffer = PICO_ZALLOC(frame_buffer_size + sizeof(uint32_t));
tass picotcp@tass.be 149:5f4cb161cec3 89 if (!p->buffer) {
tass picotcp@tass.be 149:5f4cb161cec3 90 PICO_FREE(p);
tass picotcp@tass.be 149:5f4cb161cec3 91 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 92 }
tass 152:a3d286bf94e5 93
tass 152:a3d286bf94e5 94 p->usage_count = (uint32_t *)(((uint8_t*)p->buffer) + frame_buffer_size);
tass picotcp@tass.be 149:5f4cb161cec3 95 } else {
tass picotcp@tass.be 149:5f4cb161cec3 96 p->buffer = NULL;
tass 152:a3d286bf94e5 97 p->flags |= PICO_FRAME_FLAG_EXT_USAGE_COUNTER;
tass 152:a3d286bf94e5 98 p->usage_count = PICO_ZALLOC(sizeof(uint32_t));
tass 152:a3d286bf94e5 99 if (!p->usage_count) {
tass 152:a3d286bf94e5 100 PICO_FREE(p);
tass 152:a3d286bf94e5 101 return NULL;
tass 152:a3d286bf94e5 102 }
TASS Belgium NV 131:4758606c9316 103 }
TASS Belgium NV 131:4758606c9316 104
TASS Belgium NV 131:4758606c9316 105
TASS Belgium NV 131:4758606c9316 106 p->buffer_len = size;
tass 68:0847e35d08a6 107
TASS Belgium NV 131:4758606c9316 108 /* By default, frame content is the full buffer. */
TASS Belgium NV 131:4758606c9316 109 p->start = p->buffer;
TASS Belgium NV 131:4758606c9316 110 p->len = p->buffer_len;
TASS Belgium NV 131:4758606c9316 111 *p->usage_count = 1;
tass 152:a3d286bf94e5 112
tass 152:a3d286bf94e5 113 if (ext_buffer)
tass 152:a3d286bf94e5 114 p->flags |= PICO_FRAME_FLAG_EXT_BUFFER;
tass 152:a3d286bf94e5 115
tass 68:0847e35d08a6 116 #ifdef PICO_SUPPORT_DEBUG_MEMORY
tass 68:0847e35d08a6 117 dbg("Allocated buffer @%p, len= %d caller: %p\n", p->buffer, p->buffer_len, __builtin_return_address(2));
tass 68:0847e35d08a6 118 dbg("DEBUG MEMORY: %d frames in use.\n", ++n_frames_allocated);
tass 68:0847e35d08a6 119 #endif
TASS Belgium NV 131:4758606c9316 120 return p;
tass 68:0847e35d08a6 121 }
tass 68:0847e35d08a6 122
tass picotcp@tass.be 149:5f4cb161cec3 123 struct pico_frame *pico_frame_alloc(uint32_t size)
tass picotcp@tass.be 149:5f4cb161cec3 124 {
tass 152:a3d286bf94e5 125 return pico_frame_do_alloc(size, 0, 0);
tass picotcp@tass.be 149:5f4cb161cec3 126 }
tass picotcp@tass.be 149:5f4cb161cec3 127
tass 152:a3d286bf94e5 128 int pico_frame_grow(struct pico_frame *f, uint32_t size)
tass picotcp@tass.be 149:5f4cb161cec3 129 {
tass 152:a3d286bf94e5 130 uint8_t *oldbuf;
tass 152:a3d286bf94e5 131 uint32_t usage_count, *p_old_usage;
tass 152:a3d286bf94e5 132 uint32_t frame_buffer_size;
tass 152:a3d286bf94e5 133 uint32_t oldsize;
tass 152:a3d286bf94e5 134 unsigned int align;
tass 152:a3d286bf94e5 135 int addr_diff = 0;
tass 152:a3d286bf94e5 136
tass 152:a3d286bf94e5 137 if (!f || (size < f->buffer_len)) {
tass 152:a3d286bf94e5 138 return -1;
tass 152:a3d286bf94e5 139 }
tass 152:a3d286bf94e5 140
tass 152:a3d286bf94e5 141 align = size % sizeof(uint32_t);
tass 152:a3d286bf94e5 142 frame_buffer_size = size;
tass 152:a3d286bf94e5 143 if (align) {
tass 152:a3d286bf94e5 144 frame_buffer_size += (uint32_t)sizeof(uint32_t) - align;
tass 152:a3d286bf94e5 145 }
tass 152:a3d286bf94e5 146
tass 152:a3d286bf94e5 147 oldbuf = f->buffer;
tass 152:a3d286bf94e5 148 oldsize = f->buffer_len;
tass 152:a3d286bf94e5 149 usage_count = *(f->usage_count);
tass 152:a3d286bf94e5 150 p_old_usage = f->usage_count;
tass 152:a3d286bf94e5 151 f->buffer = PICO_ZALLOC(frame_buffer_size + sizeof(uint32_t));
tass 152:a3d286bf94e5 152 if (!f->buffer) {
tass 152:a3d286bf94e5 153 f->buffer = oldbuf;
tass 152:a3d286bf94e5 154 return -1;
tass 152:a3d286bf94e5 155 }
tass 152:a3d286bf94e5 156
tass 152:a3d286bf94e5 157 f->usage_count = (uint32_t *)(((uint8_t*)f->buffer) + frame_buffer_size);
tass 152:a3d286bf94e5 158 *f->usage_count = usage_count;
tass 152:a3d286bf94e5 159 f->buffer_len = size;
tass 152:a3d286bf94e5 160 memcpy(f->buffer, oldbuf, oldsize);
tass 152:a3d286bf94e5 161
tass 152:a3d286bf94e5 162 /* Update hdr fields to new buffer*/
tass 152:a3d286bf94e5 163 addr_diff = (int)(f->buffer - oldbuf);
tass 152:a3d286bf94e5 164 f->net_hdr += addr_diff;
tass 152:a3d286bf94e5 165 f->datalink_hdr += addr_diff;
tass 152:a3d286bf94e5 166 f->transport_hdr += addr_diff;
tass 152:a3d286bf94e5 167 f->app_hdr += addr_diff;
tass 152:a3d286bf94e5 168 f->start += addr_diff;
tass 152:a3d286bf94e5 169 f->payload += addr_diff;
tass 152:a3d286bf94e5 170
tass 152:a3d286bf94e5 171 if (f->flags & PICO_FRAME_FLAG_EXT_USAGE_COUNTER)
tass 152:a3d286bf94e5 172 PICO_FREE(p_old_usage);
tass 152:a3d286bf94e5 173
tass 152:a3d286bf94e5 174 if (!(f->flags & PICO_FRAME_FLAG_EXT_BUFFER))
tass 152:a3d286bf94e5 175 PICO_FREE(oldbuf);
tass 152:a3d286bf94e5 176 else if (f->notify_free)
tass 152:a3d286bf94e5 177 f->notify_free(oldbuf);
tass 152:a3d286bf94e5 178
tass 152:a3d286bf94e5 179 f->flags = 0;
tass 152:a3d286bf94e5 180 /* Now, the frame is not zerocopy anymore, and the usage counter has been moved within it */
tass 152:a3d286bf94e5 181 return 0;
tass 152:a3d286bf94e5 182 }
tass 152:a3d286bf94e5 183
tass 152:a3d286bf94e5 184 struct pico_frame *pico_frame_alloc_skeleton(uint32_t size, int ext_buffer)
tass 152:a3d286bf94e5 185 {
tass 152:a3d286bf94e5 186 return pico_frame_do_alloc(size, 1, ext_buffer);
tass picotcp@tass.be 149:5f4cb161cec3 187 }
tass picotcp@tass.be 149:5f4cb161cec3 188
tass picotcp@tass.be 149:5f4cb161cec3 189 int pico_frame_skeleton_set_buffer(struct pico_frame *f, void *buf)
tass picotcp@tass.be 149:5f4cb161cec3 190 {
tass picotcp@tass.be 149:5f4cb161cec3 191 if (!buf)
tass picotcp@tass.be 149:5f4cb161cec3 192 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 193
tass picotcp@tass.be 149:5f4cb161cec3 194 f->buffer = (uint8_t *) buf;
tass picotcp@tass.be 149:5f4cb161cec3 195 f->start = f->buffer;
tass picotcp@tass.be 149:5f4cb161cec3 196 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 197 }
tass picotcp@tass.be 149:5f4cb161cec3 198
tass 68:0847e35d08a6 199 struct pico_frame *pico_frame_deepcopy(struct pico_frame *f)
tass 68:0847e35d08a6 200 {
TASS Belgium NV 131:4758606c9316 201 struct pico_frame *new = pico_frame_alloc(f->buffer_len);
TASS Belgium NV 131:4758606c9316 202 int addr_diff;
TASS Belgium NV 131:4758606c9316 203 unsigned char *buf;
TASS Belgium NV 131:4758606c9316 204 uint32_t *uc;
TASS Belgium NV 131:4758606c9316 205 if (!new)
TASS Belgium NV 131:4758606c9316 206 return NULL;
tass 68:0847e35d08a6 207
TASS Belgium NV 131:4758606c9316 208 /* Save the two key pointers... */
TASS Belgium NV 131:4758606c9316 209 buf = new->buffer;
TASS Belgium NV 131:4758606c9316 210 uc = new->usage_count;
tass 68:0847e35d08a6 211
TASS Belgium NV 131:4758606c9316 212 /* Overwrite all fields with originals */
TASS Belgium NV 131:4758606c9316 213 memcpy(new, f, sizeof(struct pico_frame));
tass 68:0847e35d08a6 214
TASS Belgium NV 131:4758606c9316 215 /* ...restore the two key pointers */
TASS Belgium NV 131:4758606c9316 216 new->buffer = buf;
TASS Belgium NV 131:4758606c9316 217 new->usage_count = uc;
tass 68:0847e35d08a6 218
TASS Belgium NV 131:4758606c9316 219 /* Update in-buffer pointers with offset */
TASS Belgium NV 131:4758606c9316 220 addr_diff = (int)(new->buffer - f->buffer);
tass 152:a3d286bf94e5 221 new->datalink_hdr += addr_diff;
TASS Belgium NV 131:4758606c9316 222 new->net_hdr += addr_diff;
TASS Belgium NV 131:4758606c9316 223 new->transport_hdr += addr_diff;
TASS Belgium NV 131:4758606c9316 224 new->app_hdr += addr_diff;
TASS Belgium NV 131:4758606c9316 225 new->start += addr_diff;
TASS Belgium NV 131:4758606c9316 226 new->payload += addr_diff;
tass 68:0847e35d08a6 227
tass 68:0847e35d08a6 228 #ifdef PICO_SUPPORT_DEBUG_MEMORY
TASS Belgium NV 131:4758606c9316 229 dbg("Deep-Copied frame @%p, into %p, usage count now: %d\n", f, new, *new->usage_count);
tass 68:0847e35d08a6 230 #endif
TASS Belgium NV 131:4758606c9316 231 new->next = NULL;
TASS Belgium NV 131:4758606c9316 232 return new;
tass 68:0847e35d08a6 233 }
tass 68:0847e35d08a6 234
tass 152:a3d286bf94e5 235
tass 152:a3d286bf94e5 236 static inline uint32_t pico_checksum_adder(uint32_t sum, void *data, uint32_t len)
tass 152:a3d286bf94e5 237 {
tass 152:a3d286bf94e5 238 uint16_t *buf = (uint16_t *)data;
tass 152:a3d286bf94e5 239 uint16_t *stop;
tass 152:a3d286bf94e5 240
tass 152:a3d286bf94e5 241 if (len & 0x01) {
tass 152:a3d286bf94e5 242 --len;
tass 152:a3d286bf94e5 243 #ifdef PICO_BIGENDIAN
tass 152:a3d286bf94e5 244 sum += (((uint8_t *)data)[len]) << 8;
tass 152:a3d286bf94e5 245 #else
tass 152:a3d286bf94e5 246 sum += ((uint8_t *)data)[len];
tass 152:a3d286bf94e5 247 #endif
tass 152:a3d286bf94e5 248 }
tass 152:a3d286bf94e5 249
tass 152:a3d286bf94e5 250 stop = (uint16_t *)(((uint8_t *)data) + len);
tass 152:a3d286bf94e5 251
tass 152:a3d286bf94e5 252 while (buf < stop) {
tass 152:a3d286bf94e5 253 sum += *buf++;
tass 152:a3d286bf94e5 254 }
tass 152:a3d286bf94e5 255 return sum;
tass 152:a3d286bf94e5 256 }
tass 152:a3d286bf94e5 257
tass 152:a3d286bf94e5 258 static inline uint16_t pico_checksum_finalize(uint32_t sum)
tass 152:a3d286bf94e5 259 {
tass 152:a3d286bf94e5 260 while (sum >> 16) { /* a second carry is possible! */
tass 152:a3d286bf94e5 261 sum = (sum & 0x0000FFFF) + (sum >> 16);
tass 152:a3d286bf94e5 262 }
tass 152:a3d286bf94e5 263 return short_be((uint16_t) ~sum);
tass 152:a3d286bf94e5 264 }
tass 152:a3d286bf94e5 265
tass 68:0847e35d08a6 266 /**
tass 68:0847e35d08a6 267 * Calculate checksum of a given string
tass 68:0847e35d08a6 268 */
tass 70:cd218dd180e5 269 uint16_t pico_checksum(void *inbuf, uint32_t len)
tass 68:0847e35d08a6 270 {
tass 152:a3d286bf94e5 271 uint32_t sum;
tass 68:0847e35d08a6 272
tass 152:a3d286bf94e5 273 sum = pico_checksum_adder(0, inbuf, len);
tass 152:a3d286bf94e5 274 return pico_checksum_finalize(sum);
tass 68:0847e35d08a6 275 }
tass 68:0847e35d08a6 276
tass 152:a3d286bf94e5 277 /* WARNING: len1 MUST be an EVEN number */
tass 70:cd218dd180e5 278 uint16_t pico_dualbuffer_checksum(void *inbuf1, uint32_t len1, void *inbuf2, uint32_t len2)
tass 68:0847e35d08a6 279 {
tass 152:a3d286bf94e5 280 uint32_t sum;
TASS Belgium NV 131:4758606c9316 281
tass 152:a3d286bf94e5 282 sum = pico_checksum_adder(0, inbuf1, len1);
tass 152:a3d286bf94e5 283 sum = pico_checksum_adder(sum, inbuf2, len2);
tass 152:a3d286bf94e5 284 return pico_checksum_finalize(sum);
tass 68:0847e35d08a6 285 }
tass 68:0847e35d08a6 286