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 picotcp@tass.be
Date:
Wed Apr 09 14:31:41 2014 +0200
Revision:
149:5f4cb161cec3
Parent:
131:4758606c9316
Child:
152:a3d286bf94e5
Update from git masterbranch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
TASS Belgium NV 131:4758606c9316 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. 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 Authors: Andrei Carp
TASS Belgium NV 131:4758606c9316 6 Simon Maes
TASS Belgium NV 131:4758606c9316 7 *********************************************************************/
tass 68:0847e35d08a6 8
tass 68:0847e35d08a6 9 #include "pico_ipv4.h"
tass 68:0847e35d08a6 10 #include "pico_config.h"
tass 68:0847e35d08a6 11 #include "pico_icmp4.h"
tass 68:0847e35d08a6 12 #include "pico_stack.h"
tass 68:0847e35d08a6 13 #include "pico_eth.h"
tass 68:0847e35d08a6 14 #include "pico_socket.h"
tass 68:0847e35d08a6 15 #include "pico_device.h"
tass 68:0847e35d08a6 16 #include "pico_ipfilter.h"
tass 68:0847e35d08a6 17 #include "pico_tcp.h"
tass 68:0847e35d08a6 18 #include "pico_udp.h"
tass 125:96003ae6f1d8 19 #include "pico_tree.h"
tass 68:0847e35d08a6 20
tass 125:96003ae6f1d8 21 /**************** LOCAL MACROS ****************/
TASS Belgium NV 131:4758606c9316 22 #define MAX_PRIORITY (10)
TASS Belgium NV 131:4758606c9316 23 #define MIN_PRIORITY (-10)
tass 125:96003ae6f1d8 24
TASS Belgium NV 131:4758606c9316 25 #define ipf_dbg(...) do {} while(0)
tass 68:0847e35d08a6 26
tass 125:96003ae6f1d8 27 /**************** LOCAL DECLARATIONS ****************/
tass 68:0847e35d08a6 28 struct filter_node;
tass 125:96003ae6f1d8 29 static int filter_compare(void *filterA, void *filterB);
tass 125:96003ae6f1d8 30
tass 125:96003ae6f1d8 31 /**************** FILTER TREE ****************/
tass 68:0847e35d08a6 32
tass 68:0847e35d08a6 33 struct filter_node {
TASS Belgium NV 131:4758606c9316 34 struct pico_device *fdev;
TASS Belgium NV 131:4758606c9316 35 /* output address */
TASS Belgium NV 131:4758606c9316 36 uint32_t out_addr;
TASS Belgium NV 131:4758606c9316 37 uint32_t out_addr_netmask;
TASS Belgium NV 131:4758606c9316 38 /* input address */
TASS Belgium NV 131:4758606c9316 39 uint32_t in_addr;
TASS Belgium NV 131:4758606c9316 40 uint32_t in_addr_netmask;
TASS Belgium NV 131:4758606c9316 41 /* transport */
TASS Belgium NV 131:4758606c9316 42 uint16_t out_port;
TASS Belgium NV 131:4758606c9316 43 uint16_t in_port;
TASS Belgium NV 131:4758606c9316 44 /* filter details */
TASS Belgium NV 131:4758606c9316 45 uint8_t proto;
TASS Belgium NV 131:4758606c9316 46 int8_t priority;
TASS Belgium NV 131:4758606c9316 47 uint8_t tos;
TASS Belgium NV 131:4758606c9316 48 uint8_t filter_id;
TASS Belgium NV 131:4758606c9316 49 int (*function_ptr)(struct filter_node *filter, struct pico_frame *f);
tass 68:0847e35d08a6 50 };
tass 68:0847e35d08a6 51
TASS Belgium NV 131:4758606c9316 52 PICO_TREE_DECLARE(filter_tree, &filter_compare);
tass 125:96003ae6f1d8 53
TASS Belgium NV 131:4758606c9316 54 #define CHECK_AND_RETURN(a, b) do { \
TASS Belgium NV 131:4758606c9316 55 if((a) && ((a) != (b))) \
TASS Belgium NV 131:4758606c9316 56 { \
TASS Belgium NV 131:4758606c9316 57 if((a) > (b)) return 1; \
TASS Belgium NV 131:4758606c9316 58 else return -1; \
TASS Belgium NV 131:4758606c9316 59 } \
TASS Belgium NV 131:4758606c9316 60 } while(0) \
tass 125:96003ae6f1d8 61
tass 68:0847e35d08a6 62
tass 125:96003ae6f1d8 63 int filter_compare(void *filterA, void *filterB)
tass 125:96003ae6f1d8 64 {
TASS Belgium NV 131:4758606c9316 65 struct filter_node *filter = (struct filter_node *)filterA,
TASS Belgium NV 131:4758606c9316 66 *temp = (struct filter_node *)filterB;
tass 125:96003ae6f1d8 67
TASS Belgium NV 131:4758606c9316 68 /* improve the search */
TASS Belgium NV 131:4758606c9316 69 if(temp->filter_id && filter->filter_id == temp->filter_id)
TASS Belgium NV 131:4758606c9316 70 return 0;
tass 68:0847e35d08a6 71
TASS Belgium NV 131:4758606c9316 72 ipf_dbg("\nfilter ->> %x %x %x %x %d %d %d\n", filter->in_addr, filter->in_addr_netmask, filter->out_addr, filter->out_addr_netmask, filter->in_port, filter->out_port, filter->proto);
TASS Belgium NV 131:4758606c9316 73 ipf_dbg("\ntemp ->> %x %x %x %x %d %d %d\n", temp->in_addr, temp->in_addr_netmask, temp->out_addr, temp->out_addr_netmask, temp->in_port, temp->out_port, filter->proto);
TASS Belgium NV 131:4758606c9316 74 CHECK_AND_RETURN(filter->fdev, temp->fdev);
TASS Belgium NV 131:4758606c9316 75 CHECK_AND_RETURN((filter->in_addr & filter->in_addr_netmask), (temp->in_addr & filter->in_addr_netmask));
TASS Belgium NV 131:4758606c9316 76 CHECK_AND_RETURN((filter->out_addr & filter->out_addr_netmask), (temp->out_addr & filter->out_addr_netmask));
TASS Belgium NV 131:4758606c9316 77 CHECK_AND_RETURN(filter->in_port, temp->in_port);
TASS Belgium NV 131:4758606c9316 78 CHECK_AND_RETURN(filter->out_port, temp->out_port);
TASS Belgium NV 131:4758606c9316 79 CHECK_AND_RETURN(filter->priority, temp->priority);
TASS Belgium NV 131:4758606c9316 80 CHECK_AND_RETURN(filter->proto, temp->proto);
tass 125:96003ae6f1d8 81
TASS Belgium NV 131:4758606c9316 82 return 0;
tass 68:0847e35d08a6 83 }
tass 68:0847e35d08a6 84
tass 125:96003ae6f1d8 85 /**************** FILTER CALLBACKS ****************/
tass 125:96003ae6f1d8 86
TASS Belgium NV 131:4758606c9316 87 static int fp_priority(struct filter_node *filter, struct pico_frame *f)
TASS Belgium NV 131:4758606c9316 88 {
TASS Belgium NV 131:4758606c9316 89 /* TODO do priority-stuff */
TASS Belgium NV 131:4758606c9316 90 IGNORE_PARAMETER(filter);
TASS Belgium NV 131:4758606c9316 91 IGNORE_PARAMETER(f);
TASS Belgium NV 131:4758606c9316 92 return 0;
tass 68:0847e35d08a6 93 }
tass 68:0847e35d08a6 94
TASS Belgium NV 131:4758606c9316 95 static int fp_reject(struct filter_node *filter, struct pico_frame *f)
TASS Belgium NV 131:4758606c9316 96 {
TASS Belgium NV 131:4758606c9316 97 /* TODO check first if sender is pico itself or not */
TASS Belgium NV 131:4758606c9316 98 IGNORE_PARAMETER(filter);
TASS Belgium NV 131:4758606c9316 99 ipf_dbg("ipfilter> reject\n");
TASS Belgium NV 131:4758606c9316 100 pico_icmp4_packet_filtered(f);
TASS Belgium NV 131:4758606c9316 101 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 102 return 1;
tass 68:0847e35d08a6 103 }
tass 68:0847e35d08a6 104
TASS Belgium NV 131:4758606c9316 105 static int fp_drop(struct filter_node *filter, struct pico_frame *f)
TASS Belgium NV 131:4758606c9316 106 {
TASS Belgium NV 131:4758606c9316 107 IGNORE_PARAMETER(filter);
TASS Belgium NV 131:4758606c9316 108 ipf_dbg("ipfilter> drop\n");
TASS Belgium NV 131:4758606c9316 109 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 110 return 1;
tass 68:0847e35d08a6 111 }
tass 68:0847e35d08a6 112
tass 125:96003ae6f1d8 113 /**************** FILTER API's ****************/
tass 68:0847e35d08a6 114 int pico_ipv4_filter_add(struct pico_device *dev, uint8_t proto, struct pico_ip4 *out_addr, struct pico_ip4 *out_addr_netmask, struct pico_ip4 *in_addr, struct pico_ip4 *in_addr_netmask, uint16_t out_port, uint16_t in_port, int8_t priority, uint8_t tos, enum filter_action action)
tass 68:0847e35d08a6 115 {
TASS Belgium NV 131:4758606c9316 116 static uint8_t filter_id = 0;
TASS Belgium NV 131:4758606c9316 117 struct filter_node *new_filter;
tass 68:0847e35d08a6 118
TASS Belgium NV 131:4758606c9316 119 if (proto != PICO_PROTO_IPV4 || tos != 0 )
TASS Belgium NV 131:4758606c9316 120 {
TASS Belgium NV 131:4758606c9316 121 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 122 return -1;
TASS Belgium NV 131:4758606c9316 123 }
TASS Belgium NV 131:4758606c9316 124
TASS Belgium NV 131:4758606c9316 125 if ( priority > MAX_PRIORITY || priority < MIN_PRIORITY) {
TASS Belgium NV 131:4758606c9316 126 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 127 return -1;
TASS Belgium NV 131:4758606c9316 128 }
tass 125:96003ae6f1d8 129
TASS Belgium NV 131:4758606c9316 130 if (action > FILTER_COUNT) {
TASS Belgium NV 131:4758606c9316 131 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 132 return -1;
TASS Belgium NV 131:4758606c9316 133 }
TASS Belgium NV 131:4758606c9316 134
TASS Belgium NV 131:4758606c9316 135 ipf_dbg("ipfilter> adding filter\n");
tass 68:0847e35d08a6 136
tass picotcp@tass.be 149:5f4cb161cec3 137 new_filter = PICO_ZALLOC(sizeof(struct filter_node));
tass picotcp@tass.be 149:5f4cb161cec3 138
tass picotcp@tass.be 149:5f4cb161cec3 139 if (!new_filter) {
tass picotcp@tass.be 149:5f4cb161cec3 140 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 141 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 142 }
tass 68:0847e35d08a6 143
TASS Belgium NV 131:4758606c9316 144 new_filter->fdev = dev;
TASS Belgium NV 131:4758606c9316 145 new_filter->proto = proto;
tass 68:0847e35d08a6 146
tass picotcp@tass.be 149:5f4cb161cec3 147 new_filter->out_addr = (!out_addr) ? (0U) : (out_addr->addr);
tass picotcp@tass.be 149:5f4cb161cec3 148 new_filter->out_addr_netmask = (!out_addr_netmask) ? (0U) : (out_addr_netmask->addr);
tass picotcp@tass.be 149:5f4cb161cec3 149 new_filter->in_addr = (!in_addr) ? (0U) : (in_addr->addr);
tass picotcp@tass.be 149:5f4cb161cec3 150 new_filter->in_addr_netmask = (!in_addr_netmask) ? (0U) : (in_addr_netmask->addr);
tass 68:0847e35d08a6 151
TASS Belgium NV 131:4758606c9316 152 new_filter->out_port = out_port;
TASS Belgium NV 131:4758606c9316 153 new_filter->in_port = in_port;
TASS Belgium NV 131:4758606c9316 154 new_filter->priority = priority;
TASS Belgium NV 131:4758606c9316 155 new_filter->tos = tos;
tass 125:96003ae6f1d8 156
TASS Belgium NV 131:4758606c9316 157 if(filter_id == 0)
TASS Belgium NV 131:4758606c9316 158 filter_id = 1;
tass 125:96003ae6f1d8 159
TASS Belgium NV 131:4758606c9316 160 new_filter->filter_id = filter_id++;
tass 68:0847e35d08a6 161
TASS Belgium NV 131:4758606c9316 162 /*Define filterType_functionPointer here instead of in ipfilter-function, to prevent running multiple times through switch*/
TASS Belgium NV 131:4758606c9316 163 switch (action) {
tass 68:0847e35d08a6 164 case FILTER_PRIORITY:
TASS Belgium NV 131:4758606c9316 165 new_filter->function_ptr = fp_priority;
TASS Belgium NV 131:4758606c9316 166 break;
tass 68:0847e35d08a6 167 case FILTER_REJECT:
TASS Belgium NV 131:4758606c9316 168 new_filter->function_ptr = fp_reject;
TASS Belgium NV 131:4758606c9316 169 break;
tass 68:0847e35d08a6 170 case FILTER_DROP:
TASS Belgium NV 131:4758606c9316 171 new_filter->function_ptr = fp_drop;
TASS Belgium NV 131:4758606c9316 172 break;
tass 68:0847e35d08a6 173 default:
TASS Belgium NV 131:4758606c9316 174 ipf_dbg("ipfilter> unknown filter action\n");
TASS Belgium NV 131:4758606c9316 175 break;
TASS Belgium NV 131:4758606c9316 176 }
TASS Belgium NV 131:4758606c9316 177 if(pico_tree_insert(&filter_tree, new_filter))
TASS Belgium NV 131:4758606c9316 178 {
tass picotcp@tass.be 149:5f4cb161cec3 179 PICO_FREE(new_filter);
TASS Belgium NV 131:4758606c9316 180 ipf_dbg("ipfilter> failed adding filter to tree.\n");
TASS Belgium NV 131:4758606c9316 181 return -1;
TASS Belgium NV 131:4758606c9316 182 }
tass 125:96003ae6f1d8 183
TASS Belgium NV 131:4758606c9316 184 return new_filter->filter_id;
tass 68:0847e35d08a6 185 }
tass 68:0847e35d08a6 186
tass 68:0847e35d08a6 187 int pico_ipv4_filter_del(uint8_t filter_id)
tass 68:0847e35d08a6 188 {
TASS Belgium NV 131:4758606c9316 189 struct filter_node *node = NULL;
TASS Belgium NV 131:4758606c9316 190 struct filter_node dummy = {
TASS Belgium NV 131:4758606c9316 191 .filter_id = filter_id
TASS Belgium NV 131:4758606c9316 192 };
TASS Belgium NV 131:4758606c9316 193 if((node = pico_tree_delete(&filter_tree, &dummy)) == NULL)
TASS Belgium NV 131:4758606c9316 194 {
TASS Belgium NV 131:4758606c9316 195 ipf_dbg("ipfilter> failed to delete filter :%d\n", filter_id);
TASS Belgium NV 131:4758606c9316 196 return -1;
TASS Belgium NV 131:4758606c9316 197 }
tass 68:0847e35d08a6 198
tass picotcp@tass.be 149:5f4cb161cec3 199 PICO_FREE(node);
TASS Belgium NV 131:4758606c9316 200 return 0;
tass 68:0847e35d08a6 201 }
tass 68:0847e35d08a6 202
tass 125:96003ae6f1d8 203 int ipfilter(struct pico_frame *f)
tass 68:0847e35d08a6 204 {
TASS Belgium NV 131:4758606c9316 205 struct filter_node temp;
TASS Belgium NV 131:4758606c9316 206 struct filter_node *filter_frame = NULL;
TASS Belgium NV 131:4758606c9316 207 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 208 struct pico_tcp_hdr *tcp_hdr;
TASS Belgium NV 131:4758606c9316 209 struct pico_udp_hdr *udp_hdr;
TASS Belgium NV 131:4758606c9316 210 struct pico_icmp4_hdr *icmp_hdr;
tass 68:0847e35d08a6 211
TASS Belgium NV 131:4758606c9316 212 memset(&temp, 0u, sizeof(struct filter_node));
tass 68:0847e35d08a6 213
TASS Belgium NV 131:4758606c9316 214 temp.fdev = f->dev;
TASS Belgium NV 131:4758606c9316 215 temp.out_addr = ipv4_hdr->dst.addr;
TASS Belgium NV 131:4758606c9316 216 temp.in_addr = ipv4_hdr->src.addr;
tass 128:ae39e6e81531 217
TASS Belgium NV 131:4758606c9316 218 if (ipv4_hdr->proto == PICO_PROTO_TCP ) {
TASS Belgium NV 131:4758606c9316 219 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 220 temp.out_port = short_be(tcp_hdr->trans.dport);
TASS Belgium NV 131:4758606c9316 221 temp.in_port = short_be(tcp_hdr->trans.sport);
TASS Belgium NV 131:4758606c9316 222 }else if (ipv4_hdr->proto == PICO_PROTO_UDP ) {
TASS Belgium NV 131:4758606c9316 223 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 224 temp.out_port = short_be(udp_hdr->trans.dport);
TASS Belgium NV 131:4758606c9316 225 temp.in_port = short_be(udp_hdr->trans.sport);
TASS Belgium NV 131:4758606c9316 226 }
TASS Belgium NV 131:4758606c9316 227 else
TASS Belgium NV 131:4758606c9316 228 {
TASS Belgium NV 131:4758606c9316 229 if(ipv4_hdr->proto == PICO_PROTO_ICMP4)
TASS Belgium NV 131:4758606c9316 230 {
TASS Belgium NV 131:4758606c9316 231 icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 232 if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->type == PICO_ICMP_UNREACH_FILTER_PROHIB)
TASS Belgium NV 131:4758606c9316 233 return 0;
TASS Belgium NV 131:4758606c9316 234 }
tass 125:96003ae6f1d8 235
TASS Belgium NV 131:4758606c9316 236 temp.out_port = temp.in_port = 0;
TASS Belgium NV 131:4758606c9316 237 }
TASS Belgium NV 131:4758606c9316 238
TASS Belgium NV 131:4758606c9316 239 temp.proto = ipv4_hdr->proto;
TASS Belgium NV 131:4758606c9316 240 temp.priority = f->priority;
TASS Belgium NV 131:4758606c9316 241 temp.tos = ipv4_hdr->tos;
tass 68:0847e35d08a6 242
TASS Belgium NV 131:4758606c9316 243 filter_frame = pico_tree_findKey(&filter_tree, &temp);
TASS Belgium NV 131:4758606c9316 244 if(filter_frame)
TASS Belgium NV 131:4758606c9316 245 {
TASS Belgium NV 131:4758606c9316 246 ipf_dbg("Filtering frame %p with filter %p\n", f, filter_frame);
TASS Belgium NV 131:4758606c9316 247 filter_frame->function_ptr(filter_frame, f);
TASS Belgium NV 131:4758606c9316 248 return 1;
TASS Belgium NV 131:4758606c9316 249 }
tass 68:0847e35d08a6 250
TASS Belgium NV 131:4758606c9316 251 return 0;
tass 68:0847e35d08a6 252 }
tass 68:0847e35d08a6 253