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 RTOSgeneric mbed Ethernet driverhigh performance NXP LPC1768 specific Ethernet driverMulti-threading support for mbed RTOSBerkeley sockets and integration with the New Socket APIFork of the apps running on top of the New Socket APIScheduling 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.
modules/pico_icmp4.c@155:a70f34550c34, 2016-01-28 (annotated)
- 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?
User | Revision | Line number | New 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 |