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 Dec 05 12:38:26 2013 +0000
Revision:
129:dbf9eddc9109
Parent:
127:476fed453d4d
Child:
142:35da43068894
Integrated SLAACv4 to repo.; If DHCP fails, the ip address is auto configured.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 29:1a47b7151851 1 /*
daniele 29:1a47b7151851 2 *
daniele 29:1a47b7151851 3 * PicoTCP Socket interface for mbed.
daniele 29:1a47b7151851 4 * Copyright (C) 2013 TASS Belgium NV
daniele 29:1a47b7151851 5 *
daniele 29:1a47b7151851 6 * Released under GPL v2
daniele 29:1a47b7151851 7 *
daniele 29:1a47b7151851 8 * Other licensing models might apply at the sole discretion of the copyright holders.
daniele 29:1a47b7151851 9 *
daniele 29:1a47b7151851 10 *
daniele 29:1a47b7151851 11 * This software is based on the mbed.org EthernetInterface implementation:
daniele 29:1a47b7151851 12 * Copyright (C) 2012 mbed.org, MIT License
daniele 29:1a47b7151851 13 *
daniele 29:1a47b7151851 14 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
daniele 29:1a47b7151851 15 * and associated documentation files (the "Software"), to deal in the Software without restriction,
daniele 29:1a47b7151851 16 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
daniele 29:1a47b7151851 17 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
daniele 29:1a47b7151851 18 * furnished to do so, subject to the following conditions:
daniele 29:1a47b7151851 19 *
daniele 29:1a47b7151851 20 * The above copyright notice and this permission notice shall be included in all copies or
daniele 29:1a47b7151851 21 * substantial portions of the Software.
daniele 29:1a47b7151851 22 *
daniele 29:1a47b7151851 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
daniele 29:1a47b7151851 24 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
daniele 29:1a47b7151851 25 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
daniele 29:1a47b7151851 26 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
daniele 29:1a47b7151851 27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
daniele 29:1a47b7151851 28 */
daniele 29:1a47b7151851 29
daniele 29:1a47b7151851 30 #include "EthernetInterface.h"
daniele 29:1a47b7151851 31 #include "Queue.h"
daniele 29:1a47b7151851 32 #include "wrapper.h"
daniele 29:1a47b7151851 33 #include "proxy_endpoint.h"
daniele 29:1a47b7151851 34 #include "pico_dev_mbed_emac.h"
daniele 29:1a47b7151851 35 #include "mbed.h"
daniele 29:1a47b7151851 36 #include "PicoCondition.h"
daniele 29:1a47b7151851 37 extern "C"{
daniele 29:1a47b7151851 38 #include "pico_stack.h"
daniele 29:1a47b7151851 39 #include "pico_config.h"
daniele 29:1a47b7151851 40 #include "cmsis_os.h"
daniele 29:1a47b7151851 41 #include "pico_dhcp_client.h"
daniele 29:1a47b7151851 42 #include "pico_dns_client.h"
tass 125:96003ae6f1d8 43 #include "pico_ipfilter.h"
tass 129:dbf9eddc9109 44 #include "pico_slaacv4.h"
tass 44:ffd9a11d4f95 45 //#define eth_dbg mbed_dbg
tass 42:13e557b44f68 46 #define eth_dbg(...)
tass 42:13e557b44f68 47
daniele 29:1a47b7151851 48 void (*linkCb)(uint32_t link) = NULL;
daniele 29:1a47b7151851 49 }
daniele 29:1a47b7151851 50
daniele 29:1a47b7151851 51 //DigitalOutput led(LED3);
daniele 29:1a47b7151851 52 /* TCP/IP and Network Interface Initialisation */
daniele 29:1a47b7151851 53 static struct pico_device *lpc_eth;
daniele 29:1a47b7151851 54
daniele 29:1a47b7151851 55 static uint32_t dhcp_xid = 0;
daniele 29:1a47b7151851 56 static PicoCondition dhcp_mx;
daniele 29:1a47b7151851 57 static int dhcp_retval = -1;
daniele 29:1a47b7151851 58
daniele 29:1a47b7151851 59 static char mac_addr[19];
daniele 29:1a47b7151851 60 static char ip_addr[17] = "\0";
daniele 29:1a47b7151851 61 static char gw_addr[17] = "\0";
tass 127:476fed453d4d 62 static char nm_addr[17] = "\0";
daniele 29:1a47b7151851 63 static bool use_dhcp = false;
daniele 29:1a47b7151851 64 static bool is_initialized = false;
daniele 29:1a47b7151851 65
tass 129:dbf9eddc9109 66 void slaacv4_cb(struct pico_ip4 *ip, uint8_t code)
tass 129:dbf9eddc9109 67 {
tass 129:dbf9eddc9109 68 struct pico_ip4 nm_ip4;
tass 129:dbf9eddc9109 69 if(code == 0 && ip)
tass 129:dbf9eddc9109 70 {
tass 129:dbf9eddc9109 71 dhcp_retval = 0;
tass 129:dbf9eddc9109 72
tass 129:dbf9eddc9109 73 pico_ipv4_to_string(ip_addr, ip->addr);
tass 129:dbf9eddc9109 74 nm_ip4.addr = long_be(0xFFFF0000);
tass 129:dbf9eddc9109 75 pico_ipv4_to_string(nm_addr,nm_ip4.addr);
tass 129:dbf9eddc9109 76 }
tass 129:dbf9eddc9109 77 else
tass 129:dbf9eddc9109 78 dhcp_retval = -1;
tass 129:dbf9eddc9109 79
tass 129:dbf9eddc9109 80 dhcp_mx.unlock();
tass 129:dbf9eddc9109 81 }
tass 129:dbf9eddc9109 82
daniele 29:1a47b7151851 83 static void dhcp_cb(void *cli, int code)
daniele 29:1a47b7151851 84 {
daniele 29:1a47b7151851 85 void *id = NULL;
tass 127:476fed453d4d 86 struct pico_ip4 address, gateway, netmask, zero = {};
tass 41:4c18c62b31b9 87
tass 42:13e557b44f68 88 if (PICO_DHCP_ERROR == code)
daniele 29:1a47b7151851 89 goto fail;
tass 99:1c92cc810ecb 90
tass 99:1c92cc810ecb 91 if (PICO_DHCP_RESET == code)
tass 99:1c92cc810ecb 92 goto reset;
tass 99:1c92cc810ecb 93
daniele 29:1a47b7151851 94 id = pico_dhcp_get_identifier(dhcp_xid);
daniele 29:1a47b7151851 95 if (!id)
daniele 29:1a47b7151851 96 goto fail;
daniele 29:1a47b7151851 97 address = pico_dhcp_get_address(id);
daniele 29:1a47b7151851 98 gateway = pico_dhcp_get_gateway(id);
tass 127:476fed453d4d 99 netmask = pico_dhcp_get_netmask(id);
daniele 29:1a47b7151851 100 //if (address) ? // still needed
tass 127:476fed453d4d 101
daniele 29:1a47b7151851 102 pico_ipv4_to_string(ip_addr, address.addr);
tass 127:476fed453d4d 103 pico_ipv4_to_string(gw_addr,gateway.addr);
tass 127:476fed453d4d 104 pico_ipv4_to_string(nm_addr,netmask.addr);
tass 127:476fed453d4d 105
tass 53:f3ea2e39a7b2 106 eth_dbg("IP assigned : %s\n",ip_addr);
daniele 29:1a47b7151851 107
daniele 29:1a47b7151851 108 if (gateway.addr != 0) {
daniele 29:1a47b7151851 109 pico_ipv4_to_string(gw_addr, gateway.addr);
tass 53:f3ea2e39a7b2 110 eth_dbg("Default gateway assigned : %s\n",gw_addr);
daniele 29:1a47b7151851 111 pico_ipv4_route_add(zero, zero, gateway, 1, NULL);
daniele 29:1a47b7151851 112 }
tass 43:5f2146814b83 113
tass 43:5f2146814b83 114 dhcp_retval = 0;
daniele 29:1a47b7151851 115 dhcp_mx.unlock();
tass 41:4c18c62b31b9 116
daniele 29:1a47b7151851 117 return;
daniele 29:1a47b7151851 118
daniele 29:1a47b7151851 119 fail:
tass 129:dbf9eddc9109 120 pico_slaacv4_claimip(lpc_eth,slaacv4_cb);
tass 99:1c92cc810ecb 121
tass 99:1c92cc810ecb 122 reset:
tass 99:1c92cc810ecb 123 eth_dbg("DHCP reset!\n");
daniele 29:1a47b7151851 124 }
daniele 29:1a47b7151851 125
daniele 29:1a47b7151851 126 static void init_eth(void)
daniele 29:1a47b7151851 127 {
daniele 29:1a47b7151851 128 if (!is_initialized) {
daniele 29:1a47b7151851 129 pico_stack_init();
daniele 29:1a47b7151851 130 picotcp_init();
daniele 29:1a47b7151851 131 lpc_eth = pico_emac_create("mbed0");
daniele 29:1a47b7151851 132 is_initialized = true;
daniele 29:1a47b7151851 133 pico_dns_client_init();
daniele 29:1a47b7151851 134 }
daniele 29:1a47b7151851 135 if (lpc_eth) {
daniele 29:1a47b7151851 136 snprintf(mac_addr, 19, "%02X:%02X:%02X:%02X:%02X:%02X", lpc_eth->eth->mac.addr[0], lpc_eth->eth->mac.addr[1],
daniele 29:1a47b7151851 137 lpc_eth->eth->mac.addr[2], lpc_eth->eth->mac.addr[3], lpc_eth->eth->mac.addr[4], lpc_eth->eth->mac.addr[5]);
daniele 29:1a47b7151851 138 }
tass 41:4c18c62b31b9 139
tass 41:4c18c62b31b9 140 if(lpc_eth)
tass 42:13e557b44f68 141 eth_dbg("Ethernet initialized...\n");
tass 41:4c18c62b31b9 142 else
tass 42:13e557b44f68 143 eth_dbg("Failed to start Ethernet...\n");
tass 41:4c18c62b31b9 144
daniele 29:1a47b7151851 145 }
daniele 29:1a47b7151851 146
daniele 29:1a47b7151851 147 int EthernetInterface::init()
daniele 29:1a47b7151851 148 {
daniele 29:1a47b7151851 149 init_eth();
daniele 29:1a47b7151851 150 /* use dhcp to retrieve address and gateway. */
daniele 29:1a47b7151851 151 use_dhcp = true;
daniele 29:1a47b7151851 152 return 0;
daniele 29:1a47b7151851 153 }
daniele 29:1a47b7151851 154
daniele 29:1a47b7151851 155 int EthernetInterface::init(const char* ip, const char* mask, const char* gateway) {
daniele 29:1a47b7151851 156 pico_ip4 pico_addr, pico_netmask, pico_gw = {0}, zero = {0};
daniele 29:1a47b7151851 157
tass 94:7bdeb5f4d111 158 if(strcmp(ip,gateway) == 0)
tass 94:7bdeb5f4d111 159 return -1;
tass 94:7bdeb5f4d111 160
daniele 29:1a47b7151851 161 init_eth();
daniele 29:1a47b7151851 162
daniele 29:1a47b7151851 163 use_dhcp = false;
daniele 29:1a47b7151851 164 strcpy(ip_addr, ip);
tass 127:476fed453d4d 165 strcpy(nm_addr, mask);
tass 127:476fed453d4d 166 strcpy(gw_addr,gateway);
daniele 29:1a47b7151851 167
daniele 29:1a47b7151851 168 pico_string_to_ipv4(ip, &pico_addr.addr);
daniele 29:1a47b7151851 169 pico_string_to_ipv4(mask, &pico_netmask.addr);
daniele 29:1a47b7151851 170 if (gateway) {
tass 94:7bdeb5f4d111 171 pico_string_to_ipv4(gateway, &pico_gw.addr);
daniele 29:1a47b7151851 172 }
daniele 29:1a47b7151851 173 pico_ipv4_link_add(lpc_eth, pico_addr, pico_netmask);
daniele 29:1a47b7151851 174
daniele 29:1a47b7151851 175 if (pico_gw.addr)
daniele 29:1a47b7151851 176 pico_ipv4_route_add(zero, zero, pico_gw, 1, NULL);
daniele 29:1a47b7151851 177
daniele 29:1a47b7151851 178 return 0;
daniele 29:1a47b7151851 179 }
daniele 29:1a47b7151851 180
daniele 29:1a47b7151851 181 int EthernetInterface::connect(unsigned int timeout_ms) {
tass 99:1c92cc810ecb 182 IGNORE_PARAMETER(timeout_ms);
daniele 29:1a47b7151851 183 //dhcp_mx.lock(); do we still need this ?
daniele 29:1a47b7151851 184 if (use_dhcp) {
daniele 29:1a47b7151851 185 if (pico_dhcp_initiate_negotiation(lpc_eth, &dhcp_cb, &dhcp_xid) < 0)
daniele 29:1a47b7151851 186 return -1;
daniele 29:1a47b7151851 187
tass 99:1c92cc810ecb 188 dhcp_mx.lock(); // wait for a sign
tass 99:1c92cc810ecb 189 //timeout_ms removed because rtos limit lock timeout to approximate 65 seconds.
tass 41:4c18c62b31b9 190
daniele 29:1a47b7151851 191 return dhcp_retval;
daniele 29:1a47b7151851 192
daniele 29:1a47b7151851 193 } else {
daniele 29:1a47b7151851 194 return 0;
daniele 29:1a47b7151851 195 }
daniele 29:1a47b7151851 196 }
daniele 29:1a47b7151851 197
daniele 29:1a47b7151851 198 int EthernetInterface::disconnect() {
daniele 29:1a47b7151851 199 if (use_dhcp) {
daniele 29:1a47b7151851 200 }
daniele 29:1a47b7151851 201 pico_device_destroy(lpc_eth);
daniele 29:1a47b7151851 202 lpc_eth = NULL;
daniele 29:1a47b7151851 203 return 0;
daniele 29:1a47b7151851 204 }
daniele 29:1a47b7151851 205
daniele 29:1a47b7151851 206 char* EthernetInterface::getMACAddress() {
daniele 29:1a47b7151851 207 return mac_addr;
daniele 29:1a47b7151851 208 }
daniele 29:1a47b7151851 209
daniele 29:1a47b7151851 210 char* EthernetInterface::getIPAddress() {
daniele 29:1a47b7151851 211 return ip_addr;
daniele 29:1a47b7151851 212 }
daniele 29:1a47b7151851 213
tass 127:476fed453d4d 214 char* EthernetInterface::getIPGateway() {
tass 127:476fed453d4d 215 return gw_addr;
tass 127:476fed453d4d 216 }
tass 127:476fed453d4d 217
tass 127:476fed453d4d 218 char* EthernetInterface::getIPNetmask() {
tass 127:476fed453d4d 219 return nm_addr;
tass 127:476fed453d4d 220 }
tass 127:476fed453d4d 221
daniele 29:1a47b7151851 222 int EthernetInterface::registerLinkStatus(void (*cb)(uint32_t linkStatus))
daniele 29:1a47b7151851 223 {
daniele 29:1a47b7151851 224 ::linkCb = cb;
daniele 29:1a47b7151851 225 return 0;
daniele 29:1a47b7151851 226 }
daniele 29:1a47b7151851 227
daniele 29:1a47b7151851 228 int EthernetInterface::setDnsServer(const char * name)
daniele 29:1a47b7151851 229 {
daniele 29:1a47b7151851 230 struct pico_ip4 addr;
daniele 29:1a47b7151851 231 pico_string_to_ipv4(name,&addr.addr);
daniele 29:1a47b7151851 232 return pico_dns_client_nameserver(&addr,PICO_DNS_NS_ADD);
daniele 29:1a47b7151851 233 }
tass 125:96003ae6f1d8 234
tass 125:96003ae6f1d8 235 int EthernetInterface::createIpFilter(char *ipAddress, char * netmask, int port, filter_type filter)
tass 125:96003ae6f1d8 236 {
tass 125:96003ae6f1d8 237 struct pico_ip4 addr, nm, local;
tass 125:96003ae6f1d8 238 if(!ipAddress) addr.addr = 0;
tass 125:96003ae6f1d8 239 else pico_string_to_ipv4(ipAddress,&addr.addr);
tass 125:96003ae6f1d8 240
tass 125:96003ae6f1d8 241 if(!netmask) nm.addr = 0;
tass 125:96003ae6f1d8 242 else pico_string_to_ipv4(netmask,&nm.addr);
tass 125:96003ae6f1d8 243
tass 125:96003ae6f1d8 244 pico_string_to_ipv4(ip_addr,&local.addr);
tass 125:96003ae6f1d8 245
tass 125:96003ae6f1d8 246 if(filter == INPUT_FILTER)
tass 125:96003ae6f1d8 247 {
tass 125:96003ae6f1d8 248 return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&local,&nm,&addr,&nm,0,port,0,0,FILTER_REJECT);
tass 125:96003ae6f1d8 249 }
tass 125:96003ae6f1d8 250 else if(filter == OUTPUT_FILTER)
tass 125:96003ae6f1d8 251 {
tass 125:96003ae6f1d8 252 return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&addr,&nm,&local,&nm,port,0,0,0,FILTER_DROP);
tass 125:96003ae6f1d8 253 }
tass 125:96003ae6f1d8 254 else
tass 125:96003ae6f1d8 255 return -1;
tass 125:96003ae6f1d8 256 }
tass 125:96003ae6f1d8 257
tass 125:96003ae6f1d8 258 int EthernetInterface::createIpFilter(char *src, char * src_netmask, int src_port, char *dst, char * dst_netmask, int dst_port)
tass 125:96003ae6f1d8 259 {
tass 125:96003ae6f1d8 260 struct pico_ip4 src4,src_nm4,dst4,dst_nm4;
tass 125:96003ae6f1d8 261
tass 125:96003ae6f1d8 262 if(!src)
tass 125:96003ae6f1d8 263 src4.addr=0;
tass 125:96003ae6f1d8 264 else
tass 125:96003ae6f1d8 265 pico_string_to_ipv4(src,&src4.addr);
tass 125:96003ae6f1d8 266
tass 125:96003ae6f1d8 267 if(!src_netmask)
tass 125:96003ae6f1d8 268 src_nm4.addr=0;
tass 125:96003ae6f1d8 269 else
tass 125:96003ae6f1d8 270 pico_string_to_ipv4(src,&src_nm4.addr);
tass 125:96003ae6f1d8 271
tass 125:96003ae6f1d8 272 if(!dst)
tass 125:96003ae6f1d8 273 dst4.addr=0;
tass 125:96003ae6f1d8 274 else
tass 125:96003ae6f1d8 275 pico_string_to_ipv4(src,&dst4.addr);
tass 125:96003ae6f1d8 276
tass 125:96003ae6f1d8 277 if(!dst_netmask)
tass 125:96003ae6f1d8 278 dst_nm4.addr=0;
tass 125:96003ae6f1d8 279 else
tass 125:96003ae6f1d8 280 pico_string_to_ipv4(src,&dst_nm4.addr);
tass 125:96003ae6f1d8 281
tass 125:96003ae6f1d8 282 return pico_ipv4_filter_add(NULL,PICO_PROTO_IPV4,&dst4,&dst_nm4,&src4,&src_nm4,dst_port,src_port,0,0,FILTER_DROP);
tass 125:96003ae6f1d8 283 }
tass 125:96003ae6f1d8 284
tass 125:96003ae6f1d8 285 int EthernetInterface::destroyIpFilter(int filter_id)
tass 125:96003ae6f1d8 286 {
tass 125:96003ae6f1d8 287 return pico_ipv4_filter_del(filter_id);
tass 125:96003ae6f1d8 288 }