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:
Thu Nov 28 13:53:18 2013 +0000
Revision:
125:96003ae6f1d8
Parent:
68:0847e35d08a6
Child:
128:ae39e6e81531
Added IP Filter support to ethernet interface.; Synced with master branch.

Who changed what in which revision?

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