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 Sep 19 13:26:14 2013 +0000
Revision:
68:0847e35d08a6
Child:
125:96003ae6f1d8
Imported from masterbranch, again

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