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:
Mon Sep 28 13:16:18 2015 +0200
Revision:
152:a3d286bf94e5
Parent:
149:5f4cb161cec3
Mercurial: latest development version of PicoTCP

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_udp.h"
tass 68:0847e35d08a6 12 #include "pico_config.h"
tass 68:0847e35d08a6 13 #include "pico_eth.h"
tass 68:0847e35d08a6 14 #include "pico_socket.h"
tass 68:0847e35d08a6 15 #include "pico_stack.h"
tass 68:0847e35d08a6 16
tass picotcp@tass.be 149:5f4cb161cec3 17 #define UDP_FRAME_OVERHEAD (sizeof(struct pico_frame))
tass 152:a3d286bf94e5 18 #define udp_dbg(...) do {} while(0)
tass 68:0847e35d08a6 19
tass 68:0847e35d08a6 20 /* Queues */
TASS Belgium NV 131:4758606c9316 21 static struct pico_queue udp_in = {
TASS Belgium NV 131:4758606c9316 22 0
TASS Belgium NV 131:4758606c9316 23 };
TASS Belgium NV 131:4758606c9316 24 static struct pico_queue udp_out = {
TASS Belgium NV 131:4758606c9316 25 0
TASS Belgium NV 131:4758606c9316 26 };
tass 68:0847e35d08a6 27
tass 68:0847e35d08a6 28
tass 68:0847e35d08a6 29 /* Functions */
tass 68:0847e35d08a6 30
tass 68:0847e35d08a6 31 uint16_t pico_udp_checksum_ipv4(struct pico_frame *f)
tass 68:0847e35d08a6 32 {
TASS Belgium NV 131:4758606c9316 33 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 34 struct pico_udp_hdr *udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 35 struct pico_socket *s = f->sock;
TASS Belgium NV 131:4758606c9316 36 struct pico_ipv4_pseudo_hdr pseudo;
tass 68:0847e35d08a6 37
TASS Belgium NV 131:4758606c9316 38 if (s) {
TASS Belgium NV 131:4758606c9316 39 /* Case of outgoing frame */
tass 152:a3d286bf94e5 40 udp_dbg("UDP CRC: on outgoing frame\n");
TASS Belgium NV 131:4758606c9316 41 pseudo.src.addr = s->local_addr.ip4.addr;
TASS Belgium NV 131:4758606c9316 42 pseudo.dst.addr = s->remote_addr.ip4.addr;
TASS Belgium NV 131:4758606c9316 43 } else {
TASS Belgium NV 131:4758606c9316 44 /* Case of incomming frame */
tass 152:a3d286bf94e5 45 udp_dbg("UDP CRC: on incomming frame\n");
TASS Belgium NV 131:4758606c9316 46 pseudo.src.addr = hdr->src.addr;
TASS Belgium NV 131:4758606c9316 47 pseudo.dst.addr = hdr->dst.addr;
TASS Belgium NV 131:4758606c9316 48 }
tass 68:0847e35d08a6 49
TASS Belgium NV 131:4758606c9316 50 pseudo.zeros = 0;
TASS Belgium NV 131:4758606c9316 51 pseudo.proto = PICO_PROTO_UDP;
TASS Belgium NV 131:4758606c9316 52 pseudo.len = short_be(f->transport_len);
TASS Belgium NV 131:4758606c9316 53
TASS Belgium NV 131:4758606c9316 54 return pico_dualbuffer_checksum(&pseudo, sizeof(struct pico_ipv4_pseudo_hdr), udp_hdr, f->transport_len);
tass 68:0847e35d08a6 55 }
tass 68:0847e35d08a6 56
tass picotcp@tass.be 149:5f4cb161cec3 57 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 58 uint16_t pico_udp_checksum_ipv6(struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 59 {
tass picotcp@tass.be 149:5f4cb161cec3 60 struct pico_ipv6_hdr *ipv6_hdr = (struct pico_ipv6_hdr *)f->net_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 61 struct pico_udp_hdr *udp_hdr = (struct pico_udp_hdr *)f->transport_hdr;
tass 152:a3d286bf94e5 62 struct pico_ipv6_pseudo_hdr pseudo = {
tass 152:a3d286bf94e5 63 .src = {{0}}, .dst = {{0}}, .len = 0, .zero = {0}, .nxthdr = 0
tass 152:a3d286bf94e5 64 };
tass picotcp@tass.be 149:5f4cb161cec3 65 struct pico_socket *s = f->sock;
tass picotcp@tass.be 149:5f4cb161cec3 66 struct pico_remote_endpoint *remote_endpoint = (struct pico_remote_endpoint *)f->info;
tass picotcp@tass.be 149:5f4cb161cec3 67
tass picotcp@tass.be 149:5f4cb161cec3 68 /* XXX If the IPv6 packet contains a Routing header, the Destination
tass picotcp@tass.be 149:5f4cb161cec3 69 * Address used in the pseudo-header is that of the final destination */
tass picotcp@tass.be 149:5f4cb161cec3 70 if (s) {
tass picotcp@tass.be 149:5f4cb161cec3 71 /* Case of outgoing frame */
tass picotcp@tass.be 149:5f4cb161cec3 72 pseudo.src = s->local_addr.ip6;
tass picotcp@tass.be 149:5f4cb161cec3 73 if (remote_endpoint)
tass picotcp@tass.be 149:5f4cb161cec3 74 pseudo.dst = remote_endpoint->remote_addr.ip6;
tass picotcp@tass.be 149:5f4cb161cec3 75 else
tass picotcp@tass.be 149:5f4cb161cec3 76 pseudo.dst = s->remote_addr.ip6;
tass picotcp@tass.be 149:5f4cb161cec3 77 } else {
tass picotcp@tass.be 149:5f4cb161cec3 78 /* Case of incomming frame */
tass picotcp@tass.be 149:5f4cb161cec3 79 pseudo.src = ipv6_hdr->src;
tass picotcp@tass.be 149:5f4cb161cec3 80 pseudo.dst = ipv6_hdr->dst;
tass picotcp@tass.be 149:5f4cb161cec3 81 }
tass picotcp@tass.be 149:5f4cb161cec3 82
tass picotcp@tass.be 149:5f4cb161cec3 83 pseudo.len = long_be(f->transport_len);
tass picotcp@tass.be 149:5f4cb161cec3 84 pseudo.nxthdr = PICO_PROTO_UDP;
tass picotcp@tass.be 149:5f4cb161cec3 85
tass picotcp@tass.be 149:5f4cb161cec3 86 return pico_dualbuffer_checksum(&pseudo, sizeof(struct pico_ipv6_pseudo_hdr), udp_hdr, f->transport_len);
tass picotcp@tass.be 149:5f4cb161cec3 87 }
tass picotcp@tass.be 149:5f4cb161cec3 88 #endif
tass picotcp@tass.be 149:5f4cb161cec3 89
tass picotcp@tass.be 149:5f4cb161cec3 90
tass 68:0847e35d08a6 91
tass 68:0847e35d08a6 92 static int pico_udp_process_out(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 93 {
TASS Belgium NV 131:4758606c9316 94 IGNORE_PARAMETER(self);
tass picotcp@tass.be 149:5f4cb161cec3 95 return (int)pico_network_send(f);
tass 68:0847e35d08a6 96 }
tass 68:0847e35d08a6 97
tass 68:0847e35d08a6 98 static int pico_udp_push(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 99 {
TASS Belgium NV 131:4758606c9316 100 struct pico_udp_hdr *hdr = (struct pico_udp_hdr *) f->transport_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 101 struct pico_remote_endpoint *remote_endpoint = (struct pico_remote_endpoint *) f->info;
tass 68:0847e35d08a6 102
TASS Belgium NV 131:4758606c9316 103 /* this (fragmented) frame should contain a transport header */
TASS Belgium NV 131:4758606c9316 104 if (f->transport_hdr != f->payload) {
TASS Belgium NV 131:4758606c9316 105 hdr->trans.sport = f->sock->local_port;
tass picotcp@tass.be 149:5f4cb161cec3 106 if (remote_endpoint) {
tass picotcp@tass.be 149:5f4cb161cec3 107 hdr->trans.dport = remote_endpoint->remote_port;
TASS Belgium NV 131:4758606c9316 108 } else {
TASS Belgium NV 131:4758606c9316 109 hdr->trans.dport = f->sock->remote_port;
TASS Belgium NV 131:4758606c9316 110 }
TASS Belgium NV 131:4758606c9316 111
TASS Belgium NV 131:4758606c9316 112 hdr->len = short_be(f->transport_len);
tass picotcp@tass.be 149:5f4cb161cec3 113
TASS Belgium NV 131:4758606c9316 114 /* do not perform CRC validation. If you want to, a system needs to be
TASS Belgium NV 131:4758606c9316 115 implemented to calculate the CRC over the total payload of a
tass picotcp@tass.be 149:5f4cb161cec3 116 fragmented payload
tass picotcp@tass.be 149:5f4cb161cec3 117 */
TASS Belgium NV 131:4758606c9316 118 hdr->crc = 0;
tass 68:0847e35d08a6 119 }
tass 68:0847e35d08a6 120
TASS Belgium NV 131:4758606c9316 121 if (pico_enqueue(self->q_out, f) > 0) {
TASS Belgium NV 131:4758606c9316 122 return f->payload_len;
TASS Belgium NV 131:4758606c9316 123 } else {
TASS Belgium NV 131:4758606c9316 124 return 0;
TASS Belgium NV 131:4758606c9316 125 }
tass 68:0847e35d08a6 126 }
tass 68:0847e35d08a6 127
tass 68:0847e35d08a6 128 /* Interface: protocol definition */
tass 68:0847e35d08a6 129 struct pico_protocol pico_proto_udp = {
TASS Belgium NV 131:4758606c9316 130 .name = "udp",
TASS Belgium NV 131:4758606c9316 131 .proto_number = PICO_PROTO_UDP,
TASS Belgium NV 131:4758606c9316 132 .layer = PICO_LAYER_TRANSPORT,
TASS Belgium NV 131:4758606c9316 133 .process_in = pico_transport_process_in,
TASS Belgium NV 131:4758606c9316 134 .process_out = pico_udp_process_out,
TASS Belgium NV 131:4758606c9316 135 .push = pico_udp_push,
TASS Belgium NV 131:4758606c9316 136 .q_in = &udp_in,
TASS Belgium NV 131:4758606c9316 137 .q_out = &udp_out,
tass 68:0847e35d08a6 138 };
tass 68:0847e35d08a6 139
tass 68:0847e35d08a6 140
tass 68:0847e35d08a6 141
tass 68:0847e35d08a6 142 struct pico_socket *pico_udp_open(void)
tass 68:0847e35d08a6 143 {
tass picotcp@tass.be 149:5f4cb161cec3 144 struct pico_socket_udp *u = PICO_ZALLOC(sizeof(struct pico_socket_udp));
TASS Belgium NV 131:4758606c9316 145 if (!u)
TASS Belgium NV 131:4758606c9316 146 return NULL;
TASS Belgium NV 131:4758606c9316 147
TASS Belgium NV 131:4758606c9316 148 u->mode = PICO_UDP_MODE_UNICAST;
tass 68:0847e35d08a6 149
tass 68:0847e35d08a6 150 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 151 u->mc_ttl = PICO_IP_DEFAULT_MULTICAST_TTL;
TASS Belgium NV 131:4758606c9316 152 /* enable multicast loopback by default */
TASS Belgium NV 131:4758606c9316 153 u->sock.opt_flags |= (1 << PICO_SOCKET_OPT_MULTICAST_LOOP);
tass 68:0847e35d08a6 154 #endif
tass 68:0847e35d08a6 155
TASS Belgium NV 131:4758606c9316 156 return &u->sock;
tass 68:0847e35d08a6 157 }
tass 68:0847e35d08a6 158
tass 152:a3d286bf94e5 159 static void pico_udp_get_msginfo(struct pico_frame *f, struct pico_msginfo *msginfo)
tass 152:a3d286bf94e5 160 {
tass 152:a3d286bf94e5 161 msginfo->dev = f->dev;
tass 152:a3d286bf94e5 162 if (!msginfo || !f->net_hdr)
tass 152:a3d286bf94e5 163 return;
tass 152:a3d286bf94e5 164
tass 152:a3d286bf94e5 165 if (IS_IPV4(f)) { /* IPV4 */
tass 152:a3d286bf94e5 166 #ifdef PICO_SUPPORT_IPV4
tass 152:a3d286bf94e5 167 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)(f->net_hdr);
tass 152:a3d286bf94e5 168 msginfo->ttl = hdr->ttl;
tass 152:a3d286bf94e5 169 msginfo->tos = hdr->tos;
tass 152:a3d286bf94e5 170 #endif
tass 152:a3d286bf94e5 171 } else {
tass 152:a3d286bf94e5 172 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 173 struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)(f->net_hdr);
tass 152:a3d286bf94e5 174 msginfo->ttl = hdr->hop;
tass 152:a3d286bf94e5 175 msginfo->tos = (hdr->vtf >> 20) & 0xFF; /* IPv6 traffic class */
tass 152:a3d286bf94e5 176 #endif
tass 152:a3d286bf94e5 177 }
tass 152:a3d286bf94e5 178 }
tass 152:a3d286bf94e5 179
tass 152:a3d286bf94e5 180 uint16_t pico_udp_recv(struct pico_socket *s, void *buf, uint16_t len, void *src, uint16_t *port, struct pico_msginfo *msginfo)
tass 68:0847e35d08a6 181 {
TASS Belgium NV 131:4758606c9316 182 struct pico_frame *f = pico_queue_peek(&s->q_in);
TASS Belgium NV 131:4758606c9316 183 if (f) {
TASS Belgium NV 131:4758606c9316 184 if(!f->payload_len) {
TASS Belgium NV 131:4758606c9316 185 f->payload = f->transport_hdr + sizeof(struct pico_udp_hdr);
TASS Belgium NV 131:4758606c9316 186 f->payload_len = (uint16_t)(f->transport_len - sizeof(struct pico_udp_hdr));
TASS Belgium NV 131:4758606c9316 187 }
TASS Belgium NV 131:4758606c9316 188
tass 152:a3d286bf94e5 189 udp_dbg("expected: %d, got: %d\n", len, f->payload_len);
TASS Belgium NV 131:4758606c9316 190 if (src)
TASS Belgium NV 131:4758606c9316 191 pico_store_network_origin(src, f);
TASS Belgium NV 131:4758606c9316 192
TASS Belgium NV 131:4758606c9316 193 if (port) {
TASS Belgium NV 131:4758606c9316 194 struct pico_trans *hdr = (struct pico_trans *)f->transport_hdr;
TASS Belgium NV 131:4758606c9316 195 *port = hdr->sport;
TASS Belgium NV 131:4758606c9316 196 }
TASS Belgium NV 131:4758606c9316 197
tass 152:a3d286bf94e5 198 if (msginfo) {
tass 152:a3d286bf94e5 199 pico_udp_get_msginfo(f, msginfo);
tass 152:a3d286bf94e5 200 }
tass 152:a3d286bf94e5 201
TASS Belgium NV 131:4758606c9316 202 if (f->payload_len > len) {
TASS Belgium NV 131:4758606c9316 203 memcpy(buf, f->payload, len);
TASS Belgium NV 131:4758606c9316 204 f->payload += len;
TASS Belgium NV 131:4758606c9316 205 f->payload_len = (uint16_t)(f->payload_len - len);
TASS Belgium NV 131:4758606c9316 206 return len;
TASS Belgium NV 131:4758606c9316 207 } else {
TASS Belgium NV 131:4758606c9316 208 uint16_t ret = f->payload_len;
TASS Belgium NV 131:4758606c9316 209 memcpy(buf, f->payload, f->payload_len);
TASS Belgium NV 131:4758606c9316 210 f = pico_dequeue(&s->q_in);
TASS Belgium NV 131:4758606c9316 211 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 212 return ret;
TASS Belgium NV 131:4758606c9316 213 }
TASS Belgium NV 131:4758606c9316 214 } else return 0;
tass 68:0847e35d08a6 215 }
tass 68:0847e35d08a6 216