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:
Fri May 17 12:09:59 2013 +0000
Revision:
1:cfe8984a32b4
Parent:
libraries/picotcp/modules/pico_udp.c@0:d7f2341ab245
Update for smaller SOCKETQ

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 0:d7f2341ab245 1 /*********************************************************************
daniele 0:d7f2341ab245 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 0:d7f2341ab245 3 See LICENSE and COPYING for usage.
daniele 0:d7f2341ab245 4
daniele 0:d7f2341ab245 5 .
daniele 0:d7f2341ab245 6
daniele 0:d7f2341ab245 7 Authors: Daniele Lacamera
daniele 0:d7f2341ab245 8 *********************************************************************/
daniele 0:d7f2341ab245 9
daniele 0:d7f2341ab245 10
daniele 0:d7f2341ab245 11 #include "pico_udp.h"
daniele 0:d7f2341ab245 12 #include "pico_config.h"
daniele 0:d7f2341ab245 13 #include "pico_eth.h"
daniele 0:d7f2341ab245 14 #include "pico_socket.h"
daniele 0:d7f2341ab245 15 #include "pico_stack.h"
daniele 0:d7f2341ab245 16
daniele 0:d7f2341ab245 17
daniele 0:d7f2341ab245 18 /* Queues */
daniele 0:d7f2341ab245 19 static struct pico_queue udp_in = {};
daniele 0:d7f2341ab245 20 static struct pico_queue udp_out = {};
daniele 0:d7f2341ab245 21
daniele 0:d7f2341ab245 22
daniele 0:d7f2341ab245 23 /* Functions */
daniele 0:d7f2341ab245 24
daniele 0:d7f2341ab245 25 uint16_t pico_udp_checksum_ipv4(struct pico_frame *f)
daniele 0:d7f2341ab245 26 {
daniele 0:d7f2341ab245 27 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 0:d7f2341ab245 28 struct pico_udp_hdr *udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
daniele 0:d7f2341ab245 29 struct pico_socket *s = f->sock;
daniele 0:d7f2341ab245 30 struct pico_ipv4_pseudo_hdr pseudo;
daniele 0:d7f2341ab245 31
daniele 0:d7f2341ab245 32 if (s) {
daniele 0:d7f2341ab245 33 /* Case of outgoing frame */
daniele 0:d7f2341ab245 34 //dbg("UDP CRC: on outgoing frame\n");
daniele 0:d7f2341ab245 35 pseudo.src.addr = s->local_addr.ip4.addr;
daniele 0:d7f2341ab245 36 pseudo.dst.addr = s->remote_addr.ip4.addr;
daniele 0:d7f2341ab245 37 } else {
daniele 0:d7f2341ab245 38 /* Case of incomming frame */
daniele 0:d7f2341ab245 39 //dbg("UDP CRC: on incomming frame\n");
daniele 0:d7f2341ab245 40 pseudo.src.addr = hdr->src.addr;
daniele 0:d7f2341ab245 41 pseudo.dst.addr = hdr->dst.addr;
daniele 0:d7f2341ab245 42 }
daniele 0:d7f2341ab245 43 pseudo.zeros = 0;
daniele 0:d7f2341ab245 44 pseudo.proto = PICO_PROTO_UDP;
daniele 0:d7f2341ab245 45 pseudo.len = short_be(f->transport_len);
daniele 0:d7f2341ab245 46
daniele 0:d7f2341ab245 47 return pico_dualbuffer_checksum(&pseudo, sizeof(struct pico_ipv4_pseudo_hdr), udp_hdr, f->transport_len);
daniele 0:d7f2341ab245 48 }
daniele 0:d7f2341ab245 49
daniele 0:d7f2341ab245 50
daniele 0:d7f2341ab245 51 static int pico_udp_process_out(struct pico_protocol *self, struct pico_frame *f)
daniele 0:d7f2341ab245 52 {
daniele 0:d7f2341ab245 53 return pico_network_send(f);
daniele 0:d7f2341ab245 54 }
daniele 0:d7f2341ab245 55
daniele 0:d7f2341ab245 56 static int pico_udp_push(struct pico_protocol *self, struct pico_frame *f)
daniele 0:d7f2341ab245 57 {
daniele 0:d7f2341ab245 58 struct pico_udp_hdr *hdr = (struct pico_udp_hdr *) f->transport_hdr;
daniele 0:d7f2341ab245 59 struct pico_remote_duple *remote_duple = (struct pico_remote_duple *) f->info;
daniele 0:d7f2341ab245 60
daniele 0:d7f2341ab245 61 /* this (fragmented) frame should contain a transport header */
daniele 0:d7f2341ab245 62 if (f->transport_hdr != f->payload) {
daniele 0:d7f2341ab245 63 hdr->trans.sport = f->sock->local_port;
daniele 0:d7f2341ab245 64 if (remote_duple) {
daniele 0:d7f2341ab245 65 hdr->trans.dport = remote_duple->remote_port;
daniele 0:d7f2341ab245 66 } else {
daniele 0:d7f2341ab245 67 hdr->trans.dport = f->sock->remote_port;
daniele 0:d7f2341ab245 68 }
daniele 0:d7f2341ab245 69 hdr->len = short_be(f->transport_len);
daniele 0:d7f2341ab245 70 /* do not perform CRC validation. If you want to, a system needs to be
daniele 0:d7f2341ab245 71 implemented to calculate the CRC over the total payload of a
daniele 0:d7f2341ab245 72 fragmented payload */
daniele 0:d7f2341ab245 73 hdr->crc = 0;
daniele 0:d7f2341ab245 74 }
daniele 0:d7f2341ab245 75
daniele 0:d7f2341ab245 76 if (pico_enqueue(self->q_out, f) > 0) {
daniele 0:d7f2341ab245 77 return f->payload_len;
daniele 0:d7f2341ab245 78 } else {
daniele 0:d7f2341ab245 79 return 0;
daniele 0:d7f2341ab245 80 }
daniele 0:d7f2341ab245 81 }
daniele 0:d7f2341ab245 82
daniele 0:d7f2341ab245 83 /* Interface: protocol definition */
daniele 0:d7f2341ab245 84 struct pico_protocol pico_proto_udp = {
daniele 0:d7f2341ab245 85 .name = "udp",
daniele 0:d7f2341ab245 86 .proto_number = PICO_PROTO_UDP,
daniele 0:d7f2341ab245 87 .layer = PICO_LAYER_TRANSPORT,
daniele 0:d7f2341ab245 88 .process_in = pico_transport_process_in,
daniele 0:d7f2341ab245 89 .process_out = pico_udp_process_out,
daniele 0:d7f2341ab245 90 .push = pico_udp_push,
daniele 0:d7f2341ab245 91 .q_in = &udp_in,
daniele 0:d7f2341ab245 92 .q_out = &udp_out,
daniele 0:d7f2341ab245 93 };
daniele 0:d7f2341ab245 94
daniele 0:d7f2341ab245 95
daniele 0:d7f2341ab245 96 #define PICO_UDP_MODE_UNICAST 0x01
daniele 0:d7f2341ab245 97 #define PICO_UDP_MODE_MULTICAST 0x02
daniele 0:d7f2341ab245 98 #define PICO_UDP_MODE_BROADCAST 0xFF
daniele 0:d7f2341ab245 99
daniele 0:d7f2341ab245 100 struct pico_socket_udp
daniele 0:d7f2341ab245 101 {
daniele 0:d7f2341ab245 102 struct pico_socket sock;
daniele 0:d7f2341ab245 103 int mode;
daniele 0:d7f2341ab245 104 #ifdef PICO_SUPPORT_MCAST
daniele 0:d7f2341ab245 105 uint8_t mc_ttl; /* Multicasting TTL */
daniele 0:d7f2341ab245 106 #endif
daniele 0:d7f2341ab245 107 };
daniele 0:d7f2341ab245 108
daniele 0:d7f2341ab245 109 #ifdef PICO_SUPPORT_MCAST
daniele 0:d7f2341ab245 110 int pico_udp_set_mc_ttl(struct pico_socket *s, uint8_t ttl)
daniele 0:d7f2341ab245 111 {
daniele 0:d7f2341ab245 112 struct pico_socket_udp *u;
daniele 0:d7f2341ab245 113 if(!s) {
daniele 0:d7f2341ab245 114 pico_err = PICO_ERR_EINVAL;
daniele 0:d7f2341ab245 115 return -1;
daniele 0:d7f2341ab245 116 }
daniele 0:d7f2341ab245 117 u = (struct pico_socket_udp *) s;
daniele 0:d7f2341ab245 118 u->mc_ttl = ttl;
daniele 0:d7f2341ab245 119 return 0;
daniele 0:d7f2341ab245 120 }
daniele 0:d7f2341ab245 121
daniele 0:d7f2341ab245 122 int pico_udp_get_mc_ttl(struct pico_socket *s, uint8_t *ttl)
daniele 0:d7f2341ab245 123 {
daniele 0:d7f2341ab245 124 struct pico_socket_udp *u;
daniele 0:d7f2341ab245 125 if(!s)
daniele 0:d7f2341ab245 126 return -1;
daniele 0:d7f2341ab245 127 u = (struct pico_socket_udp *) s;
daniele 0:d7f2341ab245 128 *ttl = u->mc_ttl;
daniele 0:d7f2341ab245 129 return 0;
daniele 0:d7f2341ab245 130 }
daniele 0:d7f2341ab245 131 #endif /* PICO_SUPPORT_MCAST */
daniele 0:d7f2341ab245 132
daniele 0:d7f2341ab245 133 struct pico_socket *pico_udp_open(void)
daniele 0:d7f2341ab245 134 {
daniele 0:d7f2341ab245 135 struct pico_socket_udp *u = pico_zalloc(sizeof(struct pico_socket_udp));
daniele 0:d7f2341ab245 136 if (!u)
daniele 0:d7f2341ab245 137 return NULL;
daniele 0:d7f2341ab245 138 u->mode = PICO_UDP_MODE_UNICAST;
daniele 0:d7f2341ab245 139
daniele 0:d7f2341ab245 140 #ifdef PICO_SUPPORT_MCAST
daniele 0:d7f2341ab245 141 u->mc_ttl = PICO_IP_DEFAULT_MULTICAST_TTL;
daniele 0:d7f2341ab245 142 /* enable multicast loopback by default */
daniele 0:d7f2341ab245 143 u->sock.opt_flags |= (1 << PICO_SOCKET_OPT_MULTICAST_LOOP);
daniele 0:d7f2341ab245 144 #endif
daniele 0:d7f2341ab245 145
daniele 0:d7f2341ab245 146 return &u->sock;
daniele 0:d7f2341ab245 147 }
daniele 0:d7f2341ab245 148
daniele 0:d7f2341ab245 149 int pico_udp_recv(struct pico_socket *s, void *buf, int len, void *src, uint16_t *port)
daniele 0:d7f2341ab245 150 {
daniele 0:d7f2341ab245 151 struct pico_frame *f = pico_queue_peek(&s->q_in);
daniele 0:d7f2341ab245 152 if (f) {
daniele 0:d7f2341ab245 153 f->payload = f->transport_hdr + sizeof(struct pico_udp_hdr);
daniele 0:d7f2341ab245 154 f->payload_len = f->transport_len - sizeof(struct pico_udp_hdr);
daniele 0:d7f2341ab245 155 // dbg("expected: %d, got: %d\n", len, f->payload_len);
daniele 0:d7f2341ab245 156 if (src)
daniele 0:d7f2341ab245 157 pico_store_network_origin(src, f);
daniele 0:d7f2341ab245 158 if (port) {
daniele 0:d7f2341ab245 159 struct pico_trans *hdr = (struct pico_trans *)f->transport_hdr;
daniele 0:d7f2341ab245 160 *port = hdr->sport;
daniele 0:d7f2341ab245 161 }
daniele 0:d7f2341ab245 162 if (f->payload_len > len) {
daniele 0:d7f2341ab245 163 memcpy(buf, f->payload, len);
daniele 0:d7f2341ab245 164 f->payload += len;
daniele 0:d7f2341ab245 165 f->payload_len -= len;
daniele 0:d7f2341ab245 166 return len;
daniele 0:d7f2341ab245 167 } else {
daniele 0:d7f2341ab245 168 int ret = f->payload_len;
daniele 0:d7f2341ab245 169 memcpy(buf, f->payload, f->payload_len);
daniele 0:d7f2341ab245 170 f = pico_dequeue(&s->q_in);
daniele 0:d7f2341ab245 171 pico_frame_discard(f);
daniele 0:d7f2341ab245 172 return ret;
daniele 0:d7f2341ab245 173 }
daniele 0:d7f2341ab245 174 } else return 0;
daniele 0:d7f2341ab245 175 }
daniele 0:d7f2341ab245 176