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 Jan 28 15:12:00 2016 +0100
Revision:
155:a70f34550c34
Parent:
152:a3d286bf94e5
Adding TCP flag for FIN.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
tass 152:a3d286bf94e5 2 PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. 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 .
tass 68:0847e35d08a6 6
TASS Belgium NV 131:4758606c9316 7 Authors: Daniele Lacamera
TASS Belgium NV 131:4758606c9316 8 *********************************************************************/
tass 68:0847e35d08a6 9
tass 68:0847e35d08a6 10
tass 68:0847e35d08a6 11 #include "pico_icmp4.h"
tass 68:0847e35d08a6 12 #include "pico_config.h"
tass 68:0847e35d08a6 13 #include "pico_ipv4.h"
tass 68:0847e35d08a6 14 #include "pico_eth.h"
tass 68:0847e35d08a6 15 #include "pico_device.h"
tass 68:0847e35d08a6 16 #include "pico_stack.h"
tass 68:0847e35d08a6 17 #include "pico_tree.h"
tass 68:0847e35d08a6 18
tass 68:0847e35d08a6 19 /* Queues */
TASS Belgium NV 131:4758606c9316 20 static struct pico_queue icmp_in = {
TASS Belgium NV 131:4758606c9316 21 0
TASS Belgium NV 131:4758606c9316 22 };
TASS Belgium NV 131:4758606c9316 23 static struct pico_queue icmp_out = {
TASS Belgium NV 131:4758606c9316 24 0
TASS Belgium NV 131:4758606c9316 25 };
tass 68:0847e35d08a6 26
tass 68:0847e35d08a6 27
tass 68:0847e35d08a6 28 /* Functions */
tass 68:0847e35d08a6 29
tass 68:0847e35d08a6 30 static int pico_icmp4_checksum(struct pico_frame *f)
tass 68:0847e35d08a6 31 {
TASS Belgium NV 131:4758606c9316 32 struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 33 if (!hdr) {
TASS Belgium NV 131:4758606c9316 34 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 35 return -1;
TASS Belgium NV 131:4758606c9316 36 }
TASS Belgium NV 131:4758606c9316 37
TASS Belgium NV 131:4758606c9316 38 hdr->crc = 0;
TASS Belgium NV 131:4758606c9316 39 hdr->crc = short_be(pico_checksum(hdr, f->transport_len));
TASS Belgium NV 131:4758606c9316 40 return 0;
tass 68:0847e35d08a6 41 }
tass 68:0847e35d08a6 42
tass 68:0847e35d08a6 43 #ifdef PICO_SUPPORT_PING
tass 68:0847e35d08a6 44 static void ping_recv_reply(struct pico_frame *f);
tass 68:0847e35d08a6 45 #endif
tass 68:0847e35d08a6 46
tass 68:0847e35d08a6 47 static int pico_icmp4_process_in(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 48 {
TASS Belgium NV 131:4758606c9316 49 struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
tass 152:a3d286bf94e5 50 static int firstpkt = 1;
tass 152:a3d286bf94e5 51 static uint16_t last_id = 0;
tass 152:a3d286bf94e5 52 static uint16_t last_seq = 0;
TASS Belgium NV 131:4758606c9316 53 IGNORE_PARAMETER(self);
TASS Belgium NV 131:4758606c9316 54
TASS Belgium NV 131:4758606c9316 55 if (hdr->type == PICO_ICMP_ECHO) {
TASS Belgium NV 131:4758606c9316 56 hdr->type = PICO_ICMP_ECHOREPLY;
TASS Belgium NV 131:4758606c9316 57 /* outgoing frames require a f->len without the ethernet header len */
tass picotcp@tass.be 149:5f4cb161cec3 58 if (f->dev && f->dev->eth)
TASS Belgium NV 131:4758606c9316 59 f->len -= PICO_SIZE_ETHHDR;
tass 68:0847e35d08a6 60
tass 152:a3d286bf94e5 61 if (!firstpkt && (hdr->hun.ih_idseq.idseq_id == last_id) && (last_seq == hdr->hun.ih_idseq.idseq_seq)) {
tass 152:a3d286bf94e5 62 /* The network duplicated the echo. Do not reply. */
tass 152:a3d286bf94e5 63 pico_frame_discard(f);
tass 152:a3d286bf94e5 64 return 0;
tass 152:a3d286bf94e5 65 }
tass 152:a3d286bf94e5 66
tass 152:a3d286bf94e5 67 firstpkt = 0;
tass 152:a3d286bf94e5 68 last_id = hdr->hun.ih_idseq.idseq_id;
tass 152:a3d286bf94e5 69 last_seq = hdr->hun.ih_idseq.idseq_seq;
TASS Belgium NV 131:4758606c9316 70 pico_icmp4_checksum(f);
TASS Belgium NV 131:4758606c9316 71 pico_ipv4_rebound(f);
TASS Belgium NV 131:4758606c9316 72 } else if (hdr->type == PICO_ICMP_UNREACH) {
TASS Belgium NV 131:4758606c9316 73 f->net_hdr = f->transport_hdr + PICO_ICMPHDR_UN_SIZE;
TASS Belgium NV 131:4758606c9316 74 pico_ipv4_unreachable(f, hdr->code);
TASS Belgium NV 131:4758606c9316 75 } else if (hdr->type == PICO_ICMP_ECHOREPLY) {
tass 68:0847e35d08a6 76 #ifdef PICO_SUPPORT_PING
TASS Belgium NV 131:4758606c9316 77 ping_recv_reply(f);
tass 68:0847e35d08a6 78 #endif
TASS Belgium NV 131:4758606c9316 79 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 80 } else {
TASS Belgium NV 131:4758606c9316 81 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 82 }
TASS Belgium NV 131:4758606c9316 83
TASS Belgium NV 131:4758606c9316 84 return 0;
tass 68:0847e35d08a6 85 }
tass 68:0847e35d08a6 86
tass 68:0847e35d08a6 87 static int pico_icmp4_process_out(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 88 {
TASS Belgium NV 131:4758606c9316 89 IGNORE_PARAMETER(self);
TASS Belgium NV 131:4758606c9316 90 IGNORE_PARAMETER(f);
TASS Belgium NV 131:4758606c9316 91 dbg("Called %s\n", __FUNCTION__);
TASS Belgium NV 131:4758606c9316 92 return 0;
tass 68:0847e35d08a6 93 }
tass 68:0847e35d08a6 94
tass 68:0847e35d08a6 95 /* Interface: protocol definition */
tass 68:0847e35d08a6 96 struct pico_protocol pico_proto_icmp4 = {
TASS Belgium NV 131:4758606c9316 97 .name = "icmp4",
TASS Belgium NV 131:4758606c9316 98 .proto_number = PICO_PROTO_ICMP4,
TASS Belgium NV 131:4758606c9316 99 .layer = PICO_LAYER_TRANSPORT,
TASS Belgium NV 131:4758606c9316 100 .process_in = pico_icmp4_process_in,
TASS Belgium NV 131:4758606c9316 101 .process_out = pico_icmp4_process_out,
TASS Belgium NV 131:4758606c9316 102 .q_in = &icmp_in,
TASS Belgium NV 131:4758606c9316 103 .q_out = &icmp_out,
tass 68:0847e35d08a6 104 };
tass 68:0847e35d08a6 105
tass 68:0847e35d08a6 106 static int pico_icmp4_notify(struct pico_frame *f, uint8_t type, uint8_t code)
tass 68:0847e35d08a6 107 {
TASS Belgium NV 131:4758606c9316 108 struct pico_frame *reply;
TASS Belgium NV 131:4758606c9316 109 struct pico_icmp4_hdr *hdr;
TASS Belgium NV 131:4758606c9316 110 struct pico_ipv4_hdr *info;
tass 152:a3d286bf94e5 111 uint16_t f_tot_len;
tass 152:a3d286bf94e5 112
tass 152:a3d286bf94e5 113 f_tot_len = short_be(((struct pico_ipv4_hdr *)f->net_hdr)->len);
tass 152:a3d286bf94e5 114
tass 152:a3d286bf94e5 115 if (f_tot_len < (sizeof(struct pico_ipv4_hdr)))
tass 152:a3d286bf94e5 116 return -1;
tass 152:a3d286bf94e5 117
tass 152:a3d286bf94e5 118 /* Truncate tot len to be at most 8 bytes + iphdr */
tass 152:a3d286bf94e5 119 if (f_tot_len > (sizeof(struct pico_ipv4_hdr) + 8u)) {
tass 152:a3d286bf94e5 120 f_tot_len = (sizeof(struct pico_ipv4_hdr) + 8u);
tass 152:a3d286bf94e5 121 }
tass 152:a3d286bf94e5 122
TASS Belgium NV 131:4758606c9316 123 if (f == NULL) {
TASS Belgium NV 131:4758606c9316 124 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 125 return -1;
TASS Belgium NV 131:4758606c9316 126 }
TASS Belgium NV 131:4758606c9316 127
tass 152:a3d286bf94e5 128 reply = pico_proto_ipv4.alloc(&pico_proto_ipv4, (uint16_t) (f_tot_len + PICO_ICMPHDR_UN_SIZE));
TASS Belgium NV 131:4758606c9316 129 info = (struct pico_ipv4_hdr*)(f->net_hdr);
TASS Belgium NV 131:4758606c9316 130 hdr = (struct pico_icmp4_hdr *) reply->transport_hdr;
TASS Belgium NV 131:4758606c9316 131 hdr->type = type;
TASS Belgium NV 131:4758606c9316 132 hdr->code = code;
TASS Belgium NV 131:4758606c9316 133 hdr->hun.ih_pmtu.ipm_nmtu = short_be(1500);
TASS Belgium NV 131:4758606c9316 134 hdr->hun.ih_pmtu.ipm_void = 0;
tass 152:a3d286bf94e5 135 reply->transport_len = (uint16_t)(f_tot_len + PICO_ICMPHDR_UN_SIZE);
TASS Belgium NV 131:4758606c9316 136 reply->payload = reply->transport_hdr + PICO_ICMPHDR_UN_SIZE;
tass 152:a3d286bf94e5 137 memcpy(reply->payload, f->net_hdr, f_tot_len);
TASS Belgium NV 131:4758606c9316 138 pico_icmp4_checksum(reply);
TASS Belgium NV 131:4758606c9316 139 pico_ipv4_frame_push(reply, &info->src, PICO_PROTO_ICMP4);
TASS Belgium NV 131:4758606c9316 140 return 0;
tass 68:0847e35d08a6 141 }
tass 68:0847e35d08a6 142
tass 68:0847e35d08a6 143 int pico_icmp4_port_unreachable(struct pico_frame *f)
tass 68:0847e35d08a6 144 {
TASS Belgium NV 131:4758606c9316 145 /*Parameter check executed in pico_icmp4_notify*/
TASS Belgium NV 131:4758606c9316 146 return pico_icmp4_notify(f, PICO_ICMP_UNREACH, PICO_ICMP_UNREACH_PORT);
tass 68:0847e35d08a6 147 }
tass 68:0847e35d08a6 148
tass 68:0847e35d08a6 149 int pico_icmp4_proto_unreachable(struct pico_frame *f)
tass 68:0847e35d08a6 150 {
TASS Belgium NV 131:4758606c9316 151 /*Parameter check executed in pico_icmp4_notify*/
TASS Belgium NV 131:4758606c9316 152 return pico_icmp4_notify(f, PICO_ICMP_UNREACH, PICO_ICMP_UNREACH_PROTOCOL);
tass 68:0847e35d08a6 153 }
tass 68:0847e35d08a6 154
tass 68:0847e35d08a6 155 int pico_icmp4_dest_unreachable(struct pico_frame *f)
tass 68:0847e35d08a6 156 {
TASS Belgium NV 131:4758606c9316 157 /*Parameter check executed in pico_icmp4_notify*/
TASS Belgium NV 131:4758606c9316 158 return pico_icmp4_notify(f, PICO_ICMP_UNREACH, PICO_ICMP_UNREACH_HOST);
tass 68:0847e35d08a6 159 }
tass 68:0847e35d08a6 160
tass 68:0847e35d08a6 161 int pico_icmp4_ttl_expired(struct pico_frame *f)
tass 68:0847e35d08a6 162 {
TASS Belgium NV 131:4758606c9316 163 /*Parameter check executed in pico_icmp4_notify*/
TASS Belgium NV 131:4758606c9316 164 return pico_icmp4_notify(f, PICO_ICMP_TIME_EXCEEDED, PICO_ICMP_TIMXCEED_INTRANS);
tass 68:0847e35d08a6 165 }
tass 68:0847e35d08a6 166
tass 152:a3d286bf94e5 167 MOCKABLE int pico_icmp4_frag_expired(struct pico_frame *f)
tass 152:a3d286bf94e5 168 {
tass 152:a3d286bf94e5 169 /*Parameter check executed in pico_icmp4_notify*/
tass 152:a3d286bf94e5 170 return pico_icmp4_notify(f, PICO_ICMP_TIME_EXCEEDED, PICO_ICMP_TIMXCEED_REASS);
tass 152:a3d286bf94e5 171 }
tass 152:a3d286bf94e5 172
tass picotcp@tass.be 149:5f4cb161cec3 173 int pico_icmp4_mtu_exceeded(struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 174 {
tass picotcp@tass.be 149:5f4cb161cec3 175 /*Parameter check executed in pico_icmp4_notify*/
tass picotcp@tass.be 149:5f4cb161cec3 176 return pico_icmp4_notify(f, PICO_ICMP_UNREACH, PICO_ICMP_UNREACH_NEEDFRAG);
tass picotcp@tass.be 149:5f4cb161cec3 177 }
tass picotcp@tass.be 149:5f4cb161cec3 178
tass 68:0847e35d08a6 179 int pico_icmp4_packet_filtered(struct pico_frame *f)
tass 68:0847e35d08a6 180 {
TASS Belgium NV 131:4758606c9316 181 /*Parameter check executed in pico_icmp4_notify*/
TASS Belgium NV 131:4758606c9316 182 /*Packet Filtered: type 3, code 13 (Communication Administratively Prohibited)*/
TASS Belgium NV 131:4758606c9316 183 return pico_icmp4_notify(f, PICO_ICMP_UNREACH, PICO_ICMP_UNREACH_FILTER_PROHIB);
tass 68:0847e35d08a6 184 }
tass 68:0847e35d08a6 185
tass 152:a3d286bf94e5 186 int pico_icmp4_param_problem(struct pico_frame *f, uint8_t code)
tass 152:a3d286bf94e5 187 {
tass 152:a3d286bf94e5 188 return pico_icmp4_notify(f, PICO_ICMP_PARAMPROB, code);
tass 152:a3d286bf94e5 189 }
tass 152:a3d286bf94e5 190
tass 68:0847e35d08a6 191 /***********************/
tass 68:0847e35d08a6 192 /* Ping implementation */
tass 68:0847e35d08a6 193 /***********************/
tass 68:0847e35d08a6 194 /***********************/
tass 68:0847e35d08a6 195 /***********************/
tass 68:0847e35d08a6 196 /***********************/
tass 68:0847e35d08a6 197
tass 68:0847e35d08a6 198
tass 68:0847e35d08a6 199 #ifdef PICO_SUPPORT_PING
tass 68:0847e35d08a6 200
tass 68:0847e35d08a6 201
tass 68:0847e35d08a6 202 struct pico_icmp4_ping_cookie
tass 68:0847e35d08a6 203 {
TASS Belgium NV 131:4758606c9316 204 struct pico_ip4 dst;
TASS Belgium NV 131:4758606c9316 205 uint16_t err;
TASS Belgium NV 131:4758606c9316 206 uint16_t id;
TASS Belgium NV 131:4758606c9316 207 uint16_t seq;
TASS Belgium NV 131:4758606c9316 208 uint16_t size;
TASS Belgium NV 131:4758606c9316 209 int count;
TASS Belgium NV 131:4758606c9316 210 pico_time timestamp;
TASS Belgium NV 131:4758606c9316 211 int interval;
TASS Belgium NV 131:4758606c9316 212 int timeout;
TASS Belgium NV 131:4758606c9316 213 void (*cb)(struct pico_icmp4_stats*);
tass 68:0847e35d08a6 214 };
tass 68:0847e35d08a6 215
tass 68:0847e35d08a6 216 static int cookie_compare(void *ka, void *kb)
tass 68:0847e35d08a6 217 {
TASS Belgium NV 131:4758606c9316 218 struct pico_icmp4_ping_cookie *a = ka, *b = kb;
TASS Belgium NV 131:4758606c9316 219 if (a->id < b->id)
TASS Belgium NV 131:4758606c9316 220 return -1;
TASS Belgium NV 131:4758606c9316 221
TASS Belgium NV 131:4758606c9316 222 if (a->id > b->id)
TASS Belgium NV 131:4758606c9316 223 return 1;
TASS Belgium NV 131:4758606c9316 224
TASS Belgium NV 131:4758606c9316 225 return (a->seq - b->seq);
tass 68:0847e35d08a6 226 }
tass 68:0847e35d08a6 227
TASS Belgium NV 131:4758606c9316 228 PICO_TREE_DECLARE(Pings, cookie_compare);
tass 68:0847e35d08a6 229
tass picotcp@tass.be 149:5f4cb161cec3 230 static int8_t pico_icmp4_send_echo(struct pico_icmp4_ping_cookie *cookie)
tass 68:0847e35d08a6 231 {
TASS Belgium NV 131:4758606c9316 232 struct pico_frame *echo = pico_proto_ipv4.alloc(&pico_proto_ipv4, (uint16_t)(PICO_ICMPHDR_UN_SIZE + cookie->size));
TASS Belgium NV 131:4758606c9316 233 struct pico_icmp4_hdr *hdr;
tass picotcp@tass.be 149:5f4cb161cec3 234 if (!echo) {
tass picotcp@tass.be 149:5f4cb161cec3 235 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 236 }
tass 68:0847e35d08a6 237
TASS Belgium NV 131:4758606c9316 238 hdr = (struct pico_icmp4_hdr *) echo->transport_hdr;
tass 68:0847e35d08a6 239
TASS Belgium NV 131:4758606c9316 240 hdr->type = PICO_ICMP_ECHO;
TASS Belgium NV 131:4758606c9316 241 hdr->code = 0;
TASS Belgium NV 131:4758606c9316 242 hdr->hun.ih_idseq.idseq_id = short_be(cookie->id);
TASS Belgium NV 131:4758606c9316 243 hdr->hun.ih_idseq.idseq_seq = short_be(cookie->seq);
TASS Belgium NV 131:4758606c9316 244 echo->transport_len = (uint16_t)(PICO_ICMPHDR_UN_SIZE + cookie->size);
TASS Belgium NV 131:4758606c9316 245 echo->payload = echo->transport_hdr + PICO_ICMPHDR_UN_SIZE;
TASS Belgium NV 131:4758606c9316 246 echo->payload_len = cookie->size;
TASS Belgium NV 131:4758606c9316 247 /* XXX: Fill payload */
TASS Belgium NV 131:4758606c9316 248 pico_icmp4_checksum(echo);
TASS Belgium NV 131:4758606c9316 249 pico_ipv4_frame_push(echo, &cookie->dst, PICO_PROTO_ICMP4);
TASS Belgium NV 131:4758606c9316 250 return 0;
tass 68:0847e35d08a6 251 }
tass 68:0847e35d08a6 252
tass 68:0847e35d08a6 253
tass 128:ae39e6e81531 254 static void ping_timeout(pico_time now, void *arg)
tass 68:0847e35d08a6 255 {
TASS Belgium NV 131:4758606c9316 256 struct pico_icmp4_ping_cookie *cookie = (struct pico_icmp4_ping_cookie *)arg;
TASS Belgium NV 131:4758606c9316 257 IGNORE_PARAMETER(now);
tass 68:0847e35d08a6 258
TASS Belgium NV 131:4758606c9316 259 if(pico_tree_findKey(&Pings, cookie)) {
TASS Belgium NV 131:4758606c9316 260 if (cookie->err == PICO_PING_ERR_PENDING) {
TASS Belgium NV 131:4758606c9316 261 struct pico_icmp4_stats stats;
TASS Belgium NV 131:4758606c9316 262 stats.dst = cookie->dst;
TASS Belgium NV 131:4758606c9316 263 stats.seq = cookie->seq;
TASS Belgium NV 131:4758606c9316 264 stats.time = 0;
TASS Belgium NV 131:4758606c9316 265 stats.size = cookie->size;
TASS Belgium NV 131:4758606c9316 266 stats.err = PICO_PING_ERR_TIMEOUT;
TASS Belgium NV 131:4758606c9316 267 dbg(" ---- Ping timeout!!!\n");
TASS Belgium NV 131:4758606c9316 268 cookie->cb(&stats);
TASS Belgium NV 131:4758606c9316 269 }
TASS Belgium NV 131:4758606c9316 270
TASS Belgium NV 131:4758606c9316 271 pico_tree_delete(&Pings, cookie);
tass picotcp@tass.be 149:5f4cb161cec3 272 PICO_FREE(cookie);
tass 68:0847e35d08a6 273 }
tass 68:0847e35d08a6 274 }
tass 68:0847e35d08a6 275
tass 128:ae39e6e81531 276 static void next_ping(pico_time now, void *arg);
tass 68:0847e35d08a6 277 static inline void send_ping(struct pico_icmp4_ping_cookie *cookie)
tass 68:0847e35d08a6 278 {
TASS Belgium NV 131:4758606c9316 279 pico_icmp4_send_echo(cookie);
TASS Belgium NV 131:4758606c9316 280 cookie->timestamp = pico_tick;
TASS Belgium NV 131:4758606c9316 281 pico_timer_add((uint32_t)cookie->timeout, ping_timeout, cookie);
tass picotcp@tass.be 149:5f4cb161cec3 282 if (cookie->seq < (uint16_t)cookie->count)
TASS Belgium NV 131:4758606c9316 283 pico_timer_add((uint32_t)cookie->interval, next_ping, cookie);
tass 68:0847e35d08a6 284 }
tass 68:0847e35d08a6 285
tass 128:ae39e6e81531 286 static void next_ping(pico_time now, void *arg)
tass 68:0847e35d08a6 287 {
TASS Belgium NV 131:4758606c9316 288 struct pico_icmp4_ping_cookie *newcookie, *cookie = (struct pico_icmp4_ping_cookie *)arg;
TASS Belgium NV 131:4758606c9316 289 IGNORE_PARAMETER(now);
tass 68:0847e35d08a6 290
TASS Belgium NV 131:4758606c9316 291 if(pico_tree_findKey(&Pings, cookie)) {
tass 152:a3d286bf94e5 292 if (cookie->err == PICO_PING_ERR_ABORTED)
tass 152:a3d286bf94e5 293 return;
tass 152:a3d286bf94e5 294
tass picotcp@tass.be 149:5f4cb161cec3 295 if (cookie->seq < (uint16_t)cookie->count) {
tass picotcp@tass.be 149:5f4cb161cec3 296 newcookie = PICO_ZALLOC(sizeof(struct pico_icmp4_ping_cookie));
TASS Belgium NV 131:4758606c9316 297 if (!newcookie)
TASS Belgium NV 131:4758606c9316 298 return;
tass 68:0847e35d08a6 299
TASS Belgium NV 131:4758606c9316 300 memcpy(newcookie, cookie, sizeof(struct pico_icmp4_ping_cookie));
TASS Belgium NV 131:4758606c9316 301 newcookie->seq++;
TASS Belgium NV 131:4758606c9316 302
TASS Belgium NV 131:4758606c9316 303 pico_tree_insert(&Pings, newcookie);
TASS Belgium NV 131:4758606c9316 304 send_ping(newcookie);
TASS Belgium NV 131:4758606c9316 305 }
tass 68:0847e35d08a6 306 }
tass 68:0847e35d08a6 307 }
tass 68:0847e35d08a6 308
tass 68:0847e35d08a6 309
tass 68:0847e35d08a6 310 static void ping_recv_reply(struct pico_frame *f)
tass 68:0847e35d08a6 311 {
TASS Belgium NV 131:4758606c9316 312 struct pico_icmp4_ping_cookie test, *cookie;
TASS Belgium NV 131:4758606c9316 313 struct pico_icmp4_hdr *hdr = (struct pico_icmp4_hdr *) f->transport_hdr;
TASS Belgium NV 131:4758606c9316 314 test.id = short_be(hdr->hun.ih_idseq.idseq_id );
TASS Belgium NV 131:4758606c9316 315 test.seq = short_be(hdr->hun.ih_idseq.idseq_seq);
tass 68:0847e35d08a6 316
TASS Belgium NV 131:4758606c9316 317 cookie = pico_tree_findKey(&Pings, &test);
TASS Belgium NV 131:4758606c9316 318 if (cookie) {
TASS Belgium NV 131:4758606c9316 319 struct pico_icmp4_stats stats;
tass 152:a3d286bf94e5 320 if (cookie->err == PICO_PING_ERR_ABORTED)
tass 152:a3d286bf94e5 321 return;
tass 152:a3d286bf94e5 322
TASS Belgium NV 131:4758606c9316 323 cookie->err = PICO_PING_ERR_REPLIED;
tass picotcp@tass.be 149:5f4cb161cec3 324 stats.dst = ((struct pico_ipv4_hdr *)f->net_hdr)->src;
TASS Belgium NV 131:4758606c9316 325 stats.seq = cookie->seq;
TASS Belgium NV 131:4758606c9316 326 stats.size = cookie->size;
TASS Belgium NV 131:4758606c9316 327 stats.time = pico_tick - cookie->timestamp;
TASS Belgium NV 131:4758606c9316 328 stats.err = cookie->err;
TASS Belgium NV 131:4758606c9316 329 stats.ttl = ((struct pico_ipv4_hdr *)f->net_hdr)->ttl;
TASS Belgium NV 131:4758606c9316 330 if(cookie->cb != NULL)
TASS Belgium NV 131:4758606c9316 331 cookie->cb(&stats);
TASS Belgium NV 131:4758606c9316 332 } else {
TASS Belgium NV 131:4758606c9316 333 dbg("Reply for seq=%d, not found.\n", test.seq);
TASS Belgium NV 131:4758606c9316 334 }
tass 68:0847e35d08a6 335 }
tass 68:0847e35d08a6 336
tass 68:0847e35d08a6 337 int pico_icmp4_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp4_stats *))
tass 68:0847e35d08a6 338 {
TASS Belgium NV 131:4758606c9316 339 static uint16_t next_id = 0x91c0;
TASS Belgium NV 131:4758606c9316 340 struct pico_icmp4_ping_cookie *cookie;
tass 68:0847e35d08a6 341
TASS Belgium NV 131:4758606c9316 342 if((dst == NULL) || (interval == 0) || (timeout == 0) || (count == 0)) {
TASS Belgium NV 131:4758606c9316 343 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 344 return -1;
TASS Belgium NV 131:4758606c9316 345 }
tass 68:0847e35d08a6 346
tass picotcp@tass.be 149:5f4cb161cec3 347 cookie = PICO_ZALLOC(sizeof(struct pico_icmp4_ping_cookie));
TASS Belgium NV 131:4758606c9316 348 if (!cookie) {
TASS Belgium NV 131:4758606c9316 349 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 350 return -1;
TASS Belgium NV 131:4758606c9316 351 }
tass 68:0847e35d08a6 352
tass picotcp@tass.be 149:5f4cb161cec3 353 if (pico_string_to_ipv4(dst, (uint32_t *)&cookie->dst.addr) < 0) {
TASS Belgium NV 131:4758606c9316 354 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 355 PICO_FREE(cookie);
TASS Belgium NV 131:4758606c9316 356 return -1;
TASS Belgium NV 131:4758606c9316 357 }
tass 68:0847e35d08a6 358
TASS Belgium NV 131:4758606c9316 359 cookie->seq = 1;
TASS Belgium NV 131:4758606c9316 360 cookie->id = next_id++;
TASS Belgium NV 131:4758606c9316 361 cookie->err = PICO_PING_ERR_PENDING;
TASS Belgium NV 131:4758606c9316 362 cookie->size = (uint16_t)size;
TASS Belgium NV 131:4758606c9316 363 cookie->interval = interval;
TASS Belgium NV 131:4758606c9316 364 cookie->timeout = timeout;
TASS Belgium NV 131:4758606c9316 365 cookie->cb = cb;
TASS Belgium NV 131:4758606c9316 366 cookie->count = count;
tass 68:0847e35d08a6 367
TASS Belgium NV 131:4758606c9316 368 pico_tree_insert(&Pings, cookie);
TASS Belgium NV 131:4758606c9316 369 send_ping(cookie);
TASS Belgium NV 131:4758606c9316 370
tass 152:a3d286bf94e5 371 return cookie->id;
tass 68:0847e35d08a6 372
tass 68:0847e35d08a6 373 }
tass 68:0847e35d08a6 374
tass 152:a3d286bf94e5 375 int pico_icmp4_ping_abort(int id)
tass 152:a3d286bf94e5 376 {
tass 152:a3d286bf94e5 377 struct pico_tree_node *node;
tass 152:a3d286bf94e5 378 int found = 0;
tass 152:a3d286bf94e5 379 pico_tree_foreach(node, &Pings)
tass 152:a3d286bf94e5 380 {
tass 152:a3d286bf94e5 381 struct pico_icmp4_ping_cookie *ck =
tass 152:a3d286bf94e5 382 (struct pico_icmp4_ping_cookie *) node->keyValue;
tass 152:a3d286bf94e5 383 if (ck->id == (uint16_t)id) {
tass 152:a3d286bf94e5 384 ck->err = PICO_PING_ERR_ABORTED;
tass 152:a3d286bf94e5 385 found++;
tass 152:a3d286bf94e5 386 }
tass 152:a3d286bf94e5 387 }
tass 152:a3d286bf94e5 388 if (found > 0)
tass 152:a3d286bf94e5 389 return 0; /* OK if at least one pending ping has been canceled */
tass 152:a3d286bf94e5 390
tass 152:a3d286bf94e5 391 pico_err = PICO_ERR_ENOENT;
tass 152:a3d286bf94e5 392 return -1;
tass 152:a3d286bf94e5 393 }
tass 152:a3d286bf94e5 394
tass 68:0847e35d08a6 395 #endif