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 152:a3d286bf94e5 1 #include "pico_config.h"
tass picotcp@tass.be 149:5f4cb161cec3 2 #include "pico_socket.h"
tass picotcp@tass.be 149:5f4cb161cec3 3 #include "pico_udp.h"
tass picotcp@tass.be 149:5f4cb161cec3 4 #include "pico_socket_multicast.h"
tass picotcp@tass.be 149:5f4cb161cec3 5 #include "pico_ipv4.h"
tass picotcp@tass.be 149:5f4cb161cec3 6 #include "pico_ipv6.h"
tass 152:a3d286bf94e5 7 #include "pico_socket_udp.h"
tass picotcp@tass.be 149:5f4cb161cec3 8
tass picotcp@tass.be 149:5f4cb161cec3 9 #define UDP_FRAME_OVERHEAD (sizeof(struct pico_frame))
tass picotcp@tass.be 149:5f4cb161cec3 10
tass picotcp@tass.be 149:5f4cb161cec3 11
tass picotcp@tass.be 149:5f4cb161cec3 12 struct pico_socket *pico_socket_udp_open(void)
tass picotcp@tass.be 149:5f4cb161cec3 13 {
tass picotcp@tass.be 149:5f4cb161cec3 14 struct pico_socket *s = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 15 #ifdef PICO_SUPPORT_UDP
tass picotcp@tass.be 149:5f4cb161cec3 16 s = pico_udp_open();
tass picotcp@tass.be 149:5f4cb161cec3 17 if (!s) {
tass picotcp@tass.be 149:5f4cb161cec3 18 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 19 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 20 }
tass picotcp@tass.be 149:5f4cb161cec3 21
tass picotcp@tass.be 149:5f4cb161cec3 22 s->proto = &pico_proto_udp;
tass 152:a3d286bf94e5 23 s->q_in.overhead = UDP_FRAME_OVERHEAD;
tass 152:a3d286bf94e5 24 s->q_out.overhead = UDP_FRAME_OVERHEAD;
tass picotcp@tass.be 149:5f4cb161cec3 25 #endif
tass picotcp@tass.be 149:5f4cb161cec3 26 return s;
tass picotcp@tass.be 149:5f4cb161cec3 27 }
tass picotcp@tass.be 149:5f4cb161cec3 28
tass picotcp@tass.be 149:5f4cb161cec3 29
tass picotcp@tass.be 149:5f4cb161cec3 30 #ifdef PICO_SUPPORT_IPV4
tass 152:a3d286bf94e5 31 static inline int pico_socket_udp_deliver_ipv4_mcast_initial_checks(struct pico_socket *s, struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 32 {
tass 152:a3d286bf94e5 33 struct pico_ip4 p_dst;
tass picotcp@tass.be 149:5f4cb161cec3 34 struct pico_ipv4_hdr *ip4hdr;
tass picotcp@tass.be 149:5f4cb161cec3 35
tass 152:a3d286bf94e5 36 ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr);
tass 152:a3d286bf94e5 37 p_dst.addr = ip4hdr->dst.addr;
tass 152:a3d286bf94e5 38 if (pico_ipv4_is_multicast(p_dst.addr) && (pico_socket_mcast_filter(s, (union pico_address *)&ip4hdr->dst, (union pico_address *)&ip4hdr->src) < 0))
tass 152:a3d286bf94e5 39 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 40
tass picotcp@tass.be 149:5f4cb161cec3 41
tass 152:a3d286bf94e5 42 if ((pico_ipv4_link_get(&ip4hdr->src)) && (PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_MULTICAST_LOOP) == 0u)) {
tass 152:a3d286bf94e5 43 /* Datagram from ourselves, Loop disabled, discarding. */
tass 152:a3d286bf94e5 44 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 45 }
tass picotcp@tass.be 149:5f4cb161cec3 46
tass picotcp@tass.be 149:5f4cb161cec3 47 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 48 }
tass 152:a3d286bf94e5 49
tass picotcp@tass.be 149:5f4cb161cec3 50
tass 152:a3d286bf94e5 51 static int pico_socket_udp_deliver_ipv4_mcast(struct pico_socket *s, struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 52 {
tass 152:a3d286bf94e5 53 struct pico_ip4 s_local;
tass picotcp@tass.be 149:5f4cb161cec3 54 struct pico_frame *cpy;
tass 152:a3d286bf94e5 55 struct pico_device *dev = pico_ipv4_link_find(&s->local_addr.ip4);
tass 152:a3d286bf94e5 56
tass 152:a3d286bf94e5 57 s_local.addr = s->local_addr.ip4.addr;
tass 152:a3d286bf94e5 58
tass 152:a3d286bf94e5 59 if (pico_socket_udp_deliver_ipv4_mcast_initial_checks(s, f) < 0)
tass 152:a3d286bf94e5 60 return 0;
tass 152:a3d286bf94e5 61
tass 152:a3d286bf94e5 62 if ((s_local.addr == PICO_IPV4_INADDR_ANY) || /* If our local ip is ANY, or.. */
tass 152:a3d286bf94e5 63 (dev == f->dev)) { /* the source of the bcast packet is a neighbor... */
tass picotcp@tass.be 149:5f4cb161cec3 64 cpy = pico_frame_copy(f);
tass picotcp@tass.be 149:5f4cb161cec3 65 if (!cpy)
tass picotcp@tass.be 149:5f4cb161cec3 66 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 67
tass picotcp@tass.be 149:5f4cb161cec3 68 if (pico_enqueue(&s->q_in, cpy) > 0) {
tass picotcp@tass.be 149:5f4cb161cec3 69 if (s->wakeup)
tass picotcp@tass.be 149:5f4cb161cec3 70 s->wakeup(PICO_SOCK_EV_RD, s);
tass picotcp@tass.be 149:5f4cb161cec3 71 }
tass picotcp@tass.be 149:5f4cb161cec3 72 else
tass picotcp@tass.be 149:5f4cb161cec3 73 pico_frame_discard(cpy);
tass 152:a3d286bf94e5 74 }
tass 152:a3d286bf94e5 75
tass 152:a3d286bf94e5 76 return 0;
tass 152:a3d286bf94e5 77 }
tass 152:a3d286bf94e5 78
tass 152:a3d286bf94e5 79 static int pico_socket_udp_deliver_ipv4_unicast(struct pico_socket *s, struct pico_frame *f)
tass 152:a3d286bf94e5 80 {
tass 152:a3d286bf94e5 81 struct pico_frame *cpy;
tass 152:a3d286bf94e5 82 /* Either local socket is ANY, or matches dst */
tass 152:a3d286bf94e5 83 cpy = pico_frame_copy(f);
tass 152:a3d286bf94e5 84 if (!cpy)
tass 152:a3d286bf94e5 85 return -1;
tass 152:a3d286bf94e5 86
tass 152:a3d286bf94e5 87 if (pico_enqueue(&s->q_in, cpy) > 0) {
tass 152:a3d286bf94e5 88 if (s->wakeup)
tass 152:a3d286bf94e5 89 s->wakeup(PICO_SOCK_EV_RD, s);
tass 152:a3d286bf94e5 90 } else {
tass 152:a3d286bf94e5 91 pico_frame_discard(cpy);
tass 152:a3d286bf94e5 92 }
tass 152:a3d286bf94e5 93
tass 152:a3d286bf94e5 94 return 0;
tass 152:a3d286bf94e5 95 }
tass 152:a3d286bf94e5 96
tass 152:a3d286bf94e5 97
tass 152:a3d286bf94e5 98 static int pico_socket_udp_deliver_ipv4(struct pico_socket *s, struct pico_frame *f)
tass 152:a3d286bf94e5 99 {
tass 152:a3d286bf94e5 100 int ret = 0;
tass 152:a3d286bf94e5 101 struct pico_ip4 s_local, p_dst;
tass 152:a3d286bf94e5 102 struct pico_ipv4_hdr *ip4hdr;
tass 152:a3d286bf94e5 103 ip4hdr = (struct pico_ipv4_hdr*)(f->net_hdr);
tass 152:a3d286bf94e5 104 s_local.addr = s->local_addr.ip4.addr;
tass 152:a3d286bf94e5 105 p_dst.addr = ip4hdr->dst.addr;
tass 152:a3d286bf94e5 106 if ((pico_ipv4_is_broadcast(p_dst.addr)) || pico_ipv4_is_multicast(p_dst.addr)) {
tass 152:a3d286bf94e5 107 ret = pico_socket_udp_deliver_ipv4_mcast(s, f);
tass 152:a3d286bf94e5 108 } else if ((s_local.addr == PICO_IPV4_INADDR_ANY) || (s_local.addr == p_dst.addr)) {
tass 152:a3d286bf94e5 109 ret = pico_socket_udp_deliver_ipv4_unicast(s, f);
tass 152:a3d286bf94e5 110 }
tass 152:a3d286bf94e5 111
tass 152:a3d286bf94e5 112 pico_frame_discard(f);
tass 152:a3d286bf94e5 113 return ret;
tass 152:a3d286bf94e5 114 }
tass 152:a3d286bf94e5 115 #endif
tass 152:a3d286bf94e5 116
tass 152:a3d286bf94e5 117 #ifdef PICO_SUPPORT_IPV6
tass 152:a3d286bf94e5 118 static inline int pico_socket_udp_deliver_ipv6_mcast(struct pico_socket *s, struct pico_frame *f)
tass 152:a3d286bf94e5 119 {
tass 152:a3d286bf94e5 120 struct pico_ipv6_hdr *ip6hdr;
tass 152:a3d286bf94e5 121 struct pico_frame *cpy;
tass 152:a3d286bf94e5 122 struct pico_device *dev = pico_ipv6_link_find(&s->local_addr.ip6);
tass 152:a3d286bf94e5 123
tass 152:a3d286bf94e5 124 ip6hdr = (struct pico_ipv6_hdr*)(f->net_hdr);
tass 152:a3d286bf94e5 125
tass 152:a3d286bf94e5 126 if ((pico_ipv6_link_get(&ip6hdr->src)) && (PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_MULTICAST_LOOP) == 0u)) {
tass 152:a3d286bf94e5 127 /* Datagram from ourselves, Loop disabled, discarding. */
tass 152:a3d286bf94e5 128 return 0;
tass 152:a3d286bf94e5 129 }
tass 152:a3d286bf94e5 130
tass 152:a3d286bf94e5 131
tass 152:a3d286bf94e5 132 if (pico_ipv6_is_unspecified(s->local_addr.ip6.addr) || /* If our local ip is ANY, or.. */
tass 152:a3d286bf94e5 133 (dev == f->dev)) { /* the source of the bcast packet is a neighbor... */
tass 152:a3d286bf94e5 134 cpy = pico_frame_copy(f);
tass 152:a3d286bf94e5 135 if (!cpy)
tass 152:a3d286bf94e5 136 {
tass 152:a3d286bf94e5 137 return -1;
tass 152:a3d286bf94e5 138 }
tass 152:a3d286bf94e5 139
tass 152:a3d286bf94e5 140 if (pico_enqueue(&s->q_in, cpy) > 0) {
tass 152:a3d286bf94e5 141 if (s->wakeup)
tass 152:a3d286bf94e5 142 s->wakeup(PICO_SOCK_EV_RD, s);
tass 152:a3d286bf94e5 143 }
tass 152:a3d286bf94e5 144 else
tass 152:a3d286bf94e5 145 pico_frame_discard(cpy);
tass 152:a3d286bf94e5 146 }
tass 152:a3d286bf94e5 147
tass 152:a3d286bf94e5 148 return 0;
tass 152:a3d286bf94e5 149 }
tass 152:a3d286bf94e5 150
tass 152:a3d286bf94e5 151 static int pico_socket_udp_deliver_ipv6(struct pico_socket *s, struct pico_frame *f)
tass 152:a3d286bf94e5 152 {
tass 152:a3d286bf94e5 153 struct pico_ip6 s_local, p_dst;
tass 152:a3d286bf94e5 154 struct pico_ipv6_hdr *ip6hdr;
tass 152:a3d286bf94e5 155 struct pico_frame *cpy;
tass 152:a3d286bf94e5 156 ip6hdr = (struct pico_ipv6_hdr*)(f->net_hdr);
tass 152:a3d286bf94e5 157 s_local = s->local_addr.ip6;
tass 152:a3d286bf94e5 158 p_dst = ip6hdr->dst;
tass 152:a3d286bf94e5 159 if ((pico_ipv6_is_multicast(p_dst.addr))) {
tass 152:a3d286bf94e5 160 int retval = pico_socket_udp_deliver_ipv6_mcast(s, f);
tass 152:a3d286bf94e5 161 pico_frame_discard(f);
tass 152:a3d286bf94e5 162 return retval;
tass 152:a3d286bf94e5 163 }
tass 152:a3d286bf94e5 164 else if (pico_ipv6_is_unspecified(s->local_addr.ip6.addr) || (pico_ipv6_compare(&s_local, &p_dst) == 0))
tass picotcp@tass.be 149:5f4cb161cec3 165 { /* Either local socket is ANY, or matches dst */
tass picotcp@tass.be 149:5f4cb161cec3 166 cpy = pico_frame_copy(f);
tass picotcp@tass.be 149:5f4cb161cec3 167 if (!cpy)
tass 152:a3d286bf94e5 168 {
tass 152:a3d286bf94e5 169 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 170 return -1;
tass 152:a3d286bf94e5 171 }
tass picotcp@tass.be 149:5f4cb161cec3 172
tass picotcp@tass.be 149:5f4cb161cec3 173 if (pico_enqueue(&s->q_in, cpy) > 0) {
tass picotcp@tass.be 149:5f4cb161cec3 174 if (s->wakeup)
tass picotcp@tass.be 149:5f4cb161cec3 175 s->wakeup(PICO_SOCK_EV_RD, s);
tass picotcp@tass.be 149:5f4cb161cec3 176 }
tass picotcp@tass.be 149:5f4cb161cec3 177 }
tass picotcp@tass.be 149:5f4cb161cec3 178
tass picotcp@tass.be 149:5f4cb161cec3 179 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 180 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 181 }
tass picotcp@tass.be 149:5f4cb161cec3 182 #endif
tass picotcp@tass.be 149:5f4cb161cec3 183
tass picotcp@tass.be 149:5f4cb161cec3 184
tass picotcp@tass.be 149:5f4cb161cec3 185 int pico_socket_udp_deliver(struct pico_sockport *sp, struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 186 {
tass picotcp@tass.be 149:5f4cb161cec3 187 struct pico_tree_node *index = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 188 struct pico_tree_node *_tmp;
tass picotcp@tass.be 149:5f4cb161cec3 189 struct pico_socket *s = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 190 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass picotcp@tass.be 149:5f4cb161cec3 191 #ifdef PICO_SUPPORT_UDP
tass picotcp@tass.be 149:5f4cb161cec3 192 pico_err = PICO_ERR_NOERR;
tass picotcp@tass.be 149:5f4cb161cec3 193 pico_tree_foreach_safe(index, &sp->socks, _tmp){
tass picotcp@tass.be 149:5f4cb161cec3 194 s = index->keyValue;
tass picotcp@tass.be 149:5f4cb161cec3 195 if (IS_IPV4(f)) { /* IPV4 */
tass picotcp@tass.be 149:5f4cb161cec3 196 #ifdef PICO_SUPPORT_IPV4
tass picotcp@tass.be 149:5f4cb161cec3 197 return pico_socket_udp_deliver_ipv4(s, f);
tass picotcp@tass.be 149:5f4cb161cec3 198 #endif
tass 152:a3d286bf94e5 199 } else if (IS_IPV6(f)) {
tass picotcp@tass.be 149:5f4cb161cec3 200 #ifdef PICO_SUPPORT_IPV6
tass picotcp@tass.be 149:5f4cb161cec3 201 return pico_socket_udp_deliver_ipv6(s, f);
tass picotcp@tass.be 149:5f4cb161cec3 202 #endif
tass 152:a3d286bf94e5 203 } else {
tass 152:a3d286bf94e5 204 /* something wrong in the packet header*/
tass picotcp@tass.be 149:5f4cb161cec3 205 }
tass picotcp@tass.be 149:5f4cb161cec3 206 } /* FOREACH */
tass picotcp@tass.be 149:5f4cb161cec3 207 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 208 if (s)
tass picotcp@tass.be 149:5f4cb161cec3 209 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 210
tass picotcp@tass.be 149:5f4cb161cec3 211 pico_err = PICO_ERR_ENXIO;
tass picotcp@tass.be 149:5f4cb161cec3 212 #endif
tass picotcp@tass.be 149:5f4cb161cec3 213 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 214 }
tass picotcp@tass.be 149:5f4cb161cec3 215
tass picotcp@tass.be 149:5f4cb161cec3 216 int pico_setsockopt_udp(struct pico_socket *s, int option, void *value)
tass picotcp@tass.be 149:5f4cb161cec3 217 {
tass picotcp@tass.be 149:5f4cb161cec3 218 switch(option) {
tass picotcp@tass.be 149:5f4cb161cec3 219 case PICO_SOCKET_OPT_RCVBUF:
tass picotcp@tass.be 149:5f4cb161cec3 220 s->q_in.max_size = (*(uint32_t*)value);
tass picotcp@tass.be 149:5f4cb161cec3 221 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 222 case PICO_SOCKET_OPT_SNDBUF:
tass picotcp@tass.be 149:5f4cb161cec3 223 s->q_out.max_size = (*(uint32_t*)value);
tass picotcp@tass.be 149:5f4cb161cec3 224 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 225 }
tass picotcp@tass.be 149:5f4cb161cec3 226
tass picotcp@tass.be 149:5f4cb161cec3 227 /* switch's default */
tass picotcp@tass.be 149:5f4cb161cec3 228 #ifdef PICO_SUPPORT_MCAST
tass picotcp@tass.be 149:5f4cb161cec3 229 return pico_setsockopt_mcast(s, option, value);
tass picotcp@tass.be 149:5f4cb161cec3 230 #else
tass picotcp@tass.be 149:5f4cb161cec3 231 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 232 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 233 #endif
tass picotcp@tass.be 149:5f4cb161cec3 234 }
tass picotcp@tass.be 149:5f4cb161cec3 235
tass picotcp@tass.be 149:5f4cb161cec3 236 int pico_getsockopt_udp(struct pico_socket *s, int option, void *value)
tass picotcp@tass.be 149:5f4cb161cec3 237 {
tass picotcp@tass.be 149:5f4cb161cec3 238 uint32_t *val = (uint32_t *)value;
tass picotcp@tass.be 149:5f4cb161cec3 239 switch(option) {
tass picotcp@tass.be 149:5f4cb161cec3 240 case PICO_SOCKET_OPT_RCVBUF:
tass picotcp@tass.be 149:5f4cb161cec3 241 *val = s->q_in.max_size;
tass picotcp@tass.be 149:5f4cb161cec3 242 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 243 case PICO_SOCKET_OPT_SNDBUF:
tass picotcp@tass.be 149:5f4cb161cec3 244 *val = s->q_out.max_size;
tass picotcp@tass.be 149:5f4cb161cec3 245 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 246 }
tass picotcp@tass.be 149:5f4cb161cec3 247
tass picotcp@tass.be 149:5f4cb161cec3 248 /* switch's default */
tass picotcp@tass.be 149:5f4cb161cec3 249 #ifdef PICO_SUPPORT_MCAST
tass picotcp@tass.be 149:5f4cb161cec3 250 return pico_getsockopt_mcast(s, option, value);
tass picotcp@tass.be 149:5f4cb161cec3 251 #else
tass picotcp@tass.be 149:5f4cb161cec3 252 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 253 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 254 #endif
tass picotcp@tass.be 149:5f4cb161cec3 255 }
tass picotcp@tass.be 149:5f4cb161cec3 256