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 02 08:02:21 2013 +0000
Revision:
51:ab4529a384a6
Parent:
3:b4047e8a0123
Child:
63:97f481e33cb2
Updated from masterbranch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 3:b4047e8a0123 1 /*********************************************************************
daniele 3:b4047e8a0123 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 3:b4047e8a0123 3 See LICENSE and COPYING for usage.
daniele 3:b4047e8a0123 4
daniele 3:b4047e8a0123 5 Authors: Simon Maes
daniele 3:b4047e8a0123 6 *********************************************************************/
daniele 3:b4047e8a0123 7
daniele 3:b4047e8a0123 8 #include "pico_ipv4.h"
daniele 3:b4047e8a0123 9 #include "pico_config.h"
daniele 3:b4047e8a0123 10 #include "pico_icmp4.h"
daniele 3:b4047e8a0123 11 #include "pico_stack.h"
daniele 3:b4047e8a0123 12 #include "pico_eth.h"
daniele 3:b4047e8a0123 13 #include "pico_socket.h"
daniele 3:b4047e8a0123 14 #include "pico_device.h"
daniele 3:b4047e8a0123 15 #include "pico_ipfilter.h"
daniele 3:b4047e8a0123 16 #include "pico_tcp.h"
daniele 3:b4047e8a0123 17 #include "pico_udp.h"
daniele 3:b4047e8a0123 18
daniele 3:b4047e8a0123 19
daniele 3:b4047e8a0123 20 //#define ipf_dbg dbg
daniele 3:b4047e8a0123 21 #define ipf_dbg(...) do{}while(0)
daniele 3:b4047e8a0123 22
daniele 3:b4047e8a0123 23 struct filter_node;
daniele 3:b4047e8a0123 24 typedef int (*func_pntr)(struct filter_node *filter, struct pico_frame *f);
daniele 3:b4047e8a0123 25
daniele 3:b4047e8a0123 26 struct filter_node {
daniele 3:b4047e8a0123 27 struct pico_device *fdev;
daniele 3:b4047e8a0123 28 struct filter_node *next_filter;
daniele 3:b4047e8a0123 29 uint32_t out_addr;
daniele 3:b4047e8a0123 30 uint32_t out_addr_netmask;
daniele 3:b4047e8a0123 31 uint32_t in_addr;
daniele 3:b4047e8a0123 32 uint32_t in_addr_netmask;
daniele 3:b4047e8a0123 33 uint16_t out_port;
daniele 3:b4047e8a0123 34 uint16_t in_port;
daniele 3:b4047e8a0123 35 uint8_t proto;
daniele 3:b4047e8a0123 36 int8_t priority;
daniele 3:b4047e8a0123 37 uint8_t tos;
daniele 3:b4047e8a0123 38 uint8_t filter_id;
daniele 3:b4047e8a0123 39 func_pntr function_ptr;
daniele 3:b4047e8a0123 40 };
daniele 3:b4047e8a0123 41
daniele 3:b4047e8a0123 42 static struct filter_node *head = NULL;
daniele 3:b4047e8a0123 43 static struct filter_node *tail = NULL;
daniele 3:b4047e8a0123 44
daniele 3:b4047e8a0123 45 /*======================== FUNCTION PNTRS ==========================*/
daniele 3:b4047e8a0123 46
tass 51:ab4529a384a6 47 static int fp_accept(struct filter_node *filter, struct pico_frame *f) {
tass 51:ab4529a384a6 48 IGNORE_PARAMETER(filter);
tass 51:ab4529a384a6 49 IGNORE_PARAMETER(f);
tass 51:ab4529a384a6 50 return 0;
tass 51:ab4529a384a6 51 }
daniele 3:b4047e8a0123 52
daniele 3:b4047e8a0123 53 static int fp_priority(struct filter_node *filter, struct pico_frame *f) {
daniele 3:b4047e8a0123 54
daniele 3:b4047e8a0123 55 //TODO do priority-stuff
tass 51:ab4529a384a6 56 IGNORE_PARAMETER(filter);
tass 51:ab4529a384a6 57 IGNORE_PARAMETER(f);
daniele 3:b4047e8a0123 58 return 0;
daniele 3:b4047e8a0123 59 }
daniele 3:b4047e8a0123 60
daniele 3:b4047e8a0123 61 static int fp_reject(struct filter_node *filter, struct pico_frame *f) {
daniele 3:b4047e8a0123 62 // TODO check first if sender is pico itself or not
tass 51:ab4529a384a6 63 IGNORE_PARAMETER(filter);
daniele 3:b4047e8a0123 64 ipf_dbg("ipfilter> #reject\n");
daniele 3:b4047e8a0123 65 pico_icmp4_packet_filtered(f);
daniele 3:b4047e8a0123 66 pico_frame_discard(f);
daniele 3:b4047e8a0123 67 return 1;
daniele 3:b4047e8a0123 68 }
daniele 3:b4047e8a0123 69
daniele 3:b4047e8a0123 70 static int fp_drop(struct filter_node *filter, struct pico_frame *f) {
tass 51:ab4529a384a6 71 IGNORE_PARAMETER(filter);
daniele 3:b4047e8a0123 72 ipf_dbg("ipfilter> # drop\n");
daniele 3:b4047e8a0123 73 pico_frame_discard(f);
daniele 3:b4047e8a0123 74 return 1;
daniele 3:b4047e8a0123 75 }
daniele 3:b4047e8a0123 76
daniele 3:b4047e8a0123 77 /*============================ API CALLS ============================*/
daniele 3:b4047e8a0123 78 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)
daniele 3:b4047e8a0123 79 {
daniele 3:b4047e8a0123 80 static uint8_t filter_id = 0;
daniele 3:b4047e8a0123 81 struct filter_node *new_filter;
daniele 3:b4047e8a0123 82
daniele 3:b4047e8a0123 83 if ( !(dev != NULL || proto != 0 || (out_addr != NULL && out_addr->addr != 0U) || (out_addr_netmask != NULL && out_addr_netmask->addr != 0U)|| (in_addr != NULL && in_addr->addr != 0U) || (in_addr_netmask != NULL && in_addr_netmask->addr != 0U)|| out_port != 0 || in_port !=0 || tos != 0 )) {
daniele 3:b4047e8a0123 84 pico_err = PICO_ERR_EINVAL;
daniele 3:b4047e8a0123 85 return -1;
daniele 3:b4047e8a0123 86 }
daniele 3:b4047e8a0123 87 if ( priority > 10 || priority < -10) {
daniele 3:b4047e8a0123 88 pico_err = PICO_ERR_EINVAL;
daniele 3:b4047e8a0123 89 return -1;
daniele 3:b4047e8a0123 90 }
tass 51:ab4529a384a6 91 if (action > 3) {
daniele 3:b4047e8a0123 92 pico_err = PICO_ERR_EINVAL;
daniele 3:b4047e8a0123 93 return -1;
daniele 3:b4047e8a0123 94 }
daniele 3:b4047e8a0123 95 ipf_dbg("ipfilter> # adding filter\n");
daniele 3:b4047e8a0123 96
daniele 3:b4047e8a0123 97 new_filter = pico_zalloc(sizeof(struct filter_node));
daniele 3:b4047e8a0123 98 if (!head) {
daniele 3:b4047e8a0123 99 head = tail = new_filter;
daniele 3:b4047e8a0123 100 } else {
daniele 3:b4047e8a0123 101 tail->next_filter = new_filter;
daniele 3:b4047e8a0123 102 tail = new_filter;
daniele 3:b4047e8a0123 103 }
daniele 3:b4047e8a0123 104
daniele 3:b4047e8a0123 105 new_filter->fdev = dev;
daniele 3:b4047e8a0123 106 new_filter->proto = proto;
daniele 3:b4047e8a0123 107 if (out_addr != NULL)
daniele 3:b4047e8a0123 108 new_filter->out_addr = out_addr->addr;
daniele 3:b4047e8a0123 109 else
daniele 3:b4047e8a0123 110 new_filter->out_addr = 0U;
daniele 3:b4047e8a0123 111
daniele 3:b4047e8a0123 112 if (out_addr_netmask != NULL)
daniele 3:b4047e8a0123 113 new_filter->out_addr_netmask = out_addr_netmask->addr;
daniele 3:b4047e8a0123 114 else
daniele 3:b4047e8a0123 115 new_filter->out_addr_netmask = 0U;
daniele 3:b4047e8a0123 116
daniele 3:b4047e8a0123 117 if (in_addr != NULL)
daniele 3:b4047e8a0123 118 new_filter->in_addr = in_addr->addr;
daniele 3:b4047e8a0123 119 else
daniele 3:b4047e8a0123 120 new_filter->in_addr = 0U;
daniele 3:b4047e8a0123 121
daniele 3:b4047e8a0123 122 if (in_addr_netmask != NULL)
daniele 3:b4047e8a0123 123 new_filter->in_addr_netmask = in_addr_netmask->addr;
daniele 3:b4047e8a0123 124 else
daniele 3:b4047e8a0123 125 new_filter->in_addr_netmask = 0U;
daniele 3:b4047e8a0123 126
daniele 3:b4047e8a0123 127 new_filter->out_port = out_port;
daniele 3:b4047e8a0123 128 new_filter->in_port = in_port;
daniele 3:b4047e8a0123 129 new_filter->priority = priority;
daniele 3:b4047e8a0123 130 new_filter->tos = tos;
daniele 3:b4047e8a0123 131 new_filter->filter_id = filter_id++;
daniele 3:b4047e8a0123 132
daniele 3:b4047e8a0123 133 /*Define filterType_functionPointer here instead of in ipfilter-function, to prevent running multiple times through switch*/
daniele 3:b4047e8a0123 134 switch (action) {
daniele 3:b4047e8a0123 135 case FILTER_ACCEPT:
daniele 3:b4047e8a0123 136 new_filter->function_ptr = fp_accept;
daniele 3:b4047e8a0123 137 break;
daniele 3:b4047e8a0123 138 case FILTER_PRIORITY:
daniele 3:b4047e8a0123 139 new_filter->function_ptr = fp_priority;
daniele 3:b4047e8a0123 140 break;
daniele 3:b4047e8a0123 141 case FILTER_REJECT:
daniele 3:b4047e8a0123 142 new_filter->function_ptr = fp_reject;
daniele 3:b4047e8a0123 143 break;
daniele 3:b4047e8a0123 144 case FILTER_DROP:
daniele 3:b4047e8a0123 145 new_filter->function_ptr = fp_drop;
daniele 3:b4047e8a0123 146 break;
daniele 3:b4047e8a0123 147 default:
daniele 3:b4047e8a0123 148 ipf_dbg("ipfilter> #unknown filter action\n");
daniele 3:b4047e8a0123 149 break;
daniele 3:b4047e8a0123 150 }
daniele 3:b4047e8a0123 151 return new_filter->filter_id;
daniele 3:b4047e8a0123 152 }
daniele 3:b4047e8a0123 153
daniele 3:b4047e8a0123 154 int pico_ipv4_filter_del(uint8_t filter_id)
daniele 3:b4047e8a0123 155 {
daniele 3:b4047e8a0123 156 struct filter_node *work;
daniele 3:b4047e8a0123 157 struct filter_node *prev;
daniele 3:b4047e8a0123 158
daniele 3:b4047e8a0123 159 if (!tail || !head) {
daniele 3:b4047e8a0123 160 pico_err = PICO_ERR_EPERM;
daniele 3:b4047e8a0123 161 return -1;
daniele 3:b4047e8a0123 162 }
daniele 3:b4047e8a0123 163
daniele 3:b4047e8a0123 164 work = head;
daniele 3:b4047e8a0123 165 if (work->filter_id == filter_id) {
daniele 3:b4047e8a0123 166 /*delete filter_node from linked list*/
daniele 3:b4047e8a0123 167 head = work->next_filter;
daniele 3:b4047e8a0123 168 pico_free(work);
daniele 3:b4047e8a0123 169 return 0;
daniele 3:b4047e8a0123 170 }
daniele 3:b4047e8a0123 171 prev = work;
daniele 3:b4047e8a0123 172 work = work->next_filter;
daniele 3:b4047e8a0123 173
daniele 3:b4047e8a0123 174 while (1) {
daniele 3:b4047e8a0123 175 if (work->filter_id == filter_id) {
daniele 3:b4047e8a0123 176 if (work != tail) {
daniele 3:b4047e8a0123 177 /*delete filter_node from linked list*/
daniele 3:b4047e8a0123 178 prev->next_filter = work->next_filter;
daniele 3:b4047e8a0123 179 pico_free(work);
daniele 3:b4047e8a0123 180 return 0;
daniele 3:b4047e8a0123 181 } else {
daniele 3:b4047e8a0123 182 prev->next_filter = NULL;
daniele 3:b4047e8a0123 183 pico_free(work);
daniele 3:b4047e8a0123 184 return 0;
daniele 3:b4047e8a0123 185 }
daniele 3:b4047e8a0123 186 } else {
daniele 3:b4047e8a0123 187 /*check next filter_node*/
daniele 3:b4047e8a0123 188 prev = work;
daniele 3:b4047e8a0123 189 work = work->next_filter;
daniele 3:b4047e8a0123 190 if (work == tail) {
daniele 3:b4047e8a0123 191 pico_err = PICO_ERR_EINVAL;
daniele 3:b4047e8a0123 192 return -1;
daniele 3:b4047e8a0123 193 }
daniele 3:b4047e8a0123 194 }
daniele 3:b4047e8a0123 195 }
daniele 3:b4047e8a0123 196 }
daniele 3:b4047e8a0123 197
daniele 3:b4047e8a0123 198 /*================================== CORE FILTER FUNCTIONS ==================================*/
daniele 3:b4047e8a0123 199 int match_filter(struct filter_node *filter, struct pico_frame *f)
daniele 3:b4047e8a0123 200 {
daniele 3:b4047e8a0123 201 struct filter_node temp;
daniele 3:b4047e8a0123 202 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 3:b4047e8a0123 203 struct pico_tcp_hdr *tcp_hdr;
daniele 3:b4047e8a0123 204 struct pico_udp_hdr *udp_hdr;
daniele 3:b4047e8a0123 205
daniele 3:b4047e8a0123 206 if (!filter|| !f) {
daniele 3:b4047e8a0123 207 ipf_dbg("ipfilter> ## nullpointer in match filter \n");
daniele 3:b4047e8a0123 208 return -1;
daniele 3:b4047e8a0123 209 }
daniele 3:b4047e8a0123 210
daniele 3:b4047e8a0123 211 temp.fdev = f->dev;
daniele 3:b4047e8a0123 212 temp.out_addr = ipv4_hdr->dst.addr;
daniele 3:b4047e8a0123 213 temp.in_addr = ipv4_hdr->src.addr;
daniele 3:b4047e8a0123 214 if (ipv4_hdr->proto == PICO_PROTO_TCP ) {
daniele 3:b4047e8a0123 215 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
daniele 3:b4047e8a0123 216 temp.out_port = short_be(tcp_hdr->trans.dport);
daniele 3:b4047e8a0123 217 temp.in_port = short_be(tcp_hdr->trans.sport);
daniele 3:b4047e8a0123 218 }else if (ipv4_hdr->proto == PICO_PROTO_UDP ) {
daniele 3:b4047e8a0123 219 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
daniele 3:b4047e8a0123 220 temp.out_port = short_be(udp_hdr->trans.dport);
daniele 3:b4047e8a0123 221 temp.in_port = short_be(udp_hdr->trans.sport);
daniele 3:b4047e8a0123 222 } else {
daniele 3:b4047e8a0123 223 temp.out_port = temp.in_port = 0;
daniele 3:b4047e8a0123 224 }
daniele 3:b4047e8a0123 225 temp.proto = ipv4_hdr->proto;
daniele 3:b4047e8a0123 226 temp.priority = f->priority;
daniele 3:b4047e8a0123 227 temp.tos = ipv4_hdr->tos;
daniele 3:b4047e8a0123 228
daniele 3:b4047e8a0123 229
daniele 3:b4047e8a0123 230
daniele 3:b4047e8a0123 231 if ( ((filter->fdev == NULL || filter->fdev == temp.fdev) && \
daniele 3:b4047e8a0123 232 (filter->in_addr == 0 || ((filter->in_addr_netmask == 0) ? (filter->in_addr == temp.in_addr) : 1)) &&\
daniele 3:b4047e8a0123 233 (filter->in_port == 0 || filter->in_port == temp.in_port) &&\
daniele 3:b4047e8a0123 234 (filter->out_addr == 0 || ((filter->out_addr_netmask == 0) ? (filter->out_addr == temp.out_addr) : 1)) && \
daniele 3:b4047e8a0123 235 (filter->out_port == 0 || filter->out_port == temp.out_port) && \
daniele 3:b4047e8a0123 236 (filter->proto == 0 || filter->proto == temp.proto ) &&\
daniele 3:b4047e8a0123 237 (filter->priority == 0 || filter->priority == temp.priority ) &&\
daniele 3:b4047e8a0123 238 (filter->tos == 0 || filter->tos == temp.tos ) &&\
daniele 3:b4047e8a0123 239 (filter->out_addr_netmask == 0 || ((filter->out_addr & filter->out_addr_netmask) == (temp.out_addr & filter->out_addr_netmask)) ) &&\
daniele 3:b4047e8a0123 240 (filter->in_addr_netmask == 0 || ((filter->in_addr & filter->in_addr_netmask) == (temp.in_addr & filter->in_addr_netmask)) )\
daniele 3:b4047e8a0123 241 ) )
daniele 3:b4047e8a0123 242 return 0;
daniele 3:b4047e8a0123 243
daniele 3:b4047e8a0123 244 //No filter match!
daniele 3:b4047e8a0123 245 ipf_dbg("ipfilter> #no match\n");
daniele 3:b4047e8a0123 246 return 1;
daniele 3:b4047e8a0123 247 }
daniele 3:b4047e8a0123 248
daniele 3:b4047e8a0123 249 int ipfilter(struct pico_frame *f)
daniele 3:b4047e8a0123 250 {
daniele 3:b4047e8a0123 251 struct filter_node *work = head;
daniele 3:b4047e8a0123 252
daniele 3:b4047e8a0123 253 /*return 1 if pico_frame is discarded as result of the filtering, 0 for an incomming packet, -1 for faults*/
daniele 3:b4047e8a0123 254 if (!tail || !head) {
daniele 3:b4047e8a0123 255 return 0;
daniele 3:b4047e8a0123 256 }
daniele 3:b4047e8a0123 257
daniele 3:b4047e8a0123 258 if ( match_filter(work, f) == 0 ) {
daniele 3:b4047e8a0123 259 ipf_dbg("ipfilter> # ipfilter match\n");
daniele 3:b4047e8a0123 260 /*filter match, execute filter!*/
daniele 3:b4047e8a0123 261 return work->function_ptr(work, f);
daniele 3:b4047e8a0123 262 }
daniele 3:b4047e8a0123 263 while (tail != work) {
daniele 3:b4047e8a0123 264 ipf_dbg("ipfilter> next filter..\n");
daniele 3:b4047e8a0123 265 work = work->next_filter;
daniele 3:b4047e8a0123 266 if ( match_filter(work, f) == 0 ) {
daniele 3:b4047e8a0123 267 ipf_dbg("ipfilter> # ipfilter match\n");
daniele 3:b4047e8a0123 268 /*filter match, execute filter!*/
daniele 3:b4047e8a0123 269 return work->function_ptr(work, f);
daniele 3:b4047e8a0123 270 }
daniele 3:b4047e8a0123 271 }
daniele 3:b4047e8a0123 272 return 0;
daniele 3:b4047e8a0123 273 }
daniele 3:b4047e8a0123 274