#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/raw.h"
#include "lwip/icmp.h"
#include "lwip/netif.h"
#include "lwip/sys.h"
#include "lwip/sockets.h"
#include "lwip/inet.h"
#include "lwip/inet_chksum.h"
#include "ping.h"
#include "timer.h"
#include "wl_util.h"
#include "util.h"
#include "getopt.h"
Go to the source code of this file.
Data Structures | |
struct | ping_info_t |
Defines | |
#define | PING_ID 0xAFAF |
#define | PING_REPLY (1 << 0) |
Functions | |
cmd_state_t | cmd_ping (int argc, char *argv[], void *ctx) |
static int | init_ping_info (int argc, char *argv[], struct ping_info_t *ping_info) |
static void | ping_finalize (struct ping_info_t *ping_info) |
static void | ping_prepare_echo (struct icmp_echo_hdr *iecho, struct ping_info_t *ping_info) |
Prepare a echo ICMP request. | |
static u8_t | ping_recv (void *arg, struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *addr) |
static void | ping_send (struct raw_pcb *raw, struct ping_info_t *ping_info) |
void | ping_set_callback (ping_complete_cb_t cb, void *ctx) |
void | ping_stop (uint32_t *tx_cnt, uint32_t *rx_cnt) |
static void | print_stats (struct ping_info_t *ping_info) |
Variables | |
static struct ping_info_t | INFO |
#define PING_ID 0xAFAF |
#define PING_REPLY (1 << 0) |
cmd_state_t cmd_ping | ( | int | argc, | |
char * | argv[], | |||
void * | ctx | |||
) |
Definition at line 248 of file ping.c.
References CMD_DONE, CMD_INPROGRESS, ping_info_t::count, ping_info_t::data_size, ping_info_t::deadline, ping_info_t::destination, ping_info_t::first_tx_tm, ping_info_t::flags, INFO, init_ping_info(), ping_info_t::interval, ip2str(), ping_info_t::last_rx_tm, ping_info_t::last_tx_tm, ping_info_t::num_tx, pcb, ping_finalize(), ping_recv(), PING_REPLY, ping_send(), printk(), ping_info_t::quiet, ping_info_t::size, ping_info_t::timeout, and timer_get_ms().
Referenced by wl_init_complete_cb().
00249 { 00250 static enum { 00251 INIT, 00252 PING, 00253 WAIT_REPLY 00254 } state = INIT; 00255 00256 struct ping_info_t *ping_info = &INFO; 00257 static struct raw_pcb *pcb; 00258 00259 switch (state) { 00260 case INIT: 00261 if (init_ping_info(argc, argv, ping_info) != 0) { 00262 printk("Usage: ping [-c count] [-i interval] " \ 00263 "[-s packetsize]\n " \ 00264 "[-w deadline] [-q] destination\n"); 00265 return CMD_DONE; 00266 } 00267 00268 if (!(pcb = raw_new(IP_PROTO_ICMP))) { 00269 printk("could not allocate pcb\n"); 00270 state = INIT; 00271 return CMD_DONE; 00272 } 00273 raw_recv(pcb, ping_recv, ping_info); 00274 raw_bind(pcb, IP_ADDR_ANY); 00275 00276 printk("PING %s %d(%d) bytes of data\n", 00277 ip2str(ping_info->destination), 00278 ping_info->data_size, 00279 ping_info->size); 00280 state = PING; 00281 /* fall through */ 00282 00283 case PING: 00284 if (!netif_is_up(netif_default)) { 00285 printk("netif is down\n"); 00286 raw_remove(pcb); 00287 state = INIT; 00288 return CMD_DONE; 00289 } 00290 00291 if (ping_info->count && ping_info->num_tx == ping_info->count) { 00292 ping_finalize(ping_info); 00293 raw_remove(pcb); 00294 state = INIT; 00295 return CMD_DONE; 00296 } 00297 00298 00299 if (timer_get_ms() < ping_info->last_rx_tm + ping_info->interval) { 00300 return CMD_INPROGRESS; 00301 } 00302 ping_send(pcb, ping_info); 00303 00304 state = WAIT_REPLY; 00305 return CMD_INPROGRESS; 00306 00307 case WAIT_REPLY: 00308 if (ping_info->flags & PING_REPLY) { 00309 ping_info->flags &= (~PING_REPLY); 00310 state = PING; 00311 return CMD_INPROGRESS; 00312 } 00313 00314 if (timer_get_ms() > 00315 ping_info->last_tx_tm + ping_info->timeout) { 00316 if (!ping_info->quiet) 00317 printk("timeout from %s\n", 00318 ip2str(ping_info->destination)); 00319 state = PING; 00320 return CMD_INPROGRESS; 00321 } 00322 00323 if (ping_info->deadline && 00324 timer_get_ms() > 00325 ping_info->first_tx_tm + ping_info->deadline * 1000) { 00326 ping_finalize(ping_info); 00327 raw_remove(pcb); 00328 state = INIT; 00329 return CMD_DONE; 00330 } 00331 00332 return CMD_INPROGRESS; 00333 } 00334 00335 /* unreachable */ 00336 Assert(0); 00337 return CMD_DONE; 00338 }
static int init_ping_info | ( | int | argc, | |
char * | argv[], | |||
struct ping_info_t * | ping_info | |||
) | [static] |
Definition at line 169 of file ping.c.
References cb, ping_info_t::complete_cb, ping_info_t::count, ping_info_t::ctx, ctx, ping_info_t::data_size, ping_info_t::deadline, ping_info_t::destination, ping_info_t::interval, ping_info_t::quiet, ping_info_t::size, str2ip(), ping_info_t::timeout, timer_get_ms(), and TRUE.
Referenced by cmd_ping().
00170 { 00171 int c; 00172 ping_complete_cb_t cb; 00173 void *ctx; 00174 00175 cb = ping_info->complete_cb; 00176 ctx = ping_info->ctx; 00177 memset(ping_info, 0, sizeof(struct ping_info_t)); 00178 ping_info->complete_cb = cb; 00179 ping_info->ctx = ctx; 00180 00181 ping_info->deadline = 0; 00182 ping_info->interval = 1000; 00183 ping_info->timeout = 3000; 00184 ping_info->data_size = 32; 00185 ping_info->count = 3; 00186 ping_info->destination = 00187 netif_default ? netif_default->gw : ip_addr_any; 00188 00189 optind = 1; 00190 while ((c = getopt(argc, argv, "c:i:s:w:q")) != -1) { 00191 switch (c) { 00192 case 'c': 00193 ping_info->count = atoi(optarg); 00194 break; 00195 00196 case 'i': 00197 ping_info->interval = atoi(optarg); 00198 break; 00199 00200 case 's': 00201 ping_info->data_size = atoi(optarg); 00202 break; 00203 00204 case 'q': 00205 ping_info->quiet = TRUE; 00206 break; 00207 00208 case 'w': 00209 ping_info->deadline = atoi(optarg); 00210 break; 00211 } 00212 } 00213 00214 ping_info->size = sizeof(struct icmp_echo_hdr) + ping_info->data_size; 00215 00216 if (optind >= argc) 00217 return -1; 00218 00219 ping_info->destination = str2ip(argv[optind]); 00220 if (!ping_info->destination.addr) 00221 return -1; 00222 00223 00224 ping_info->last_rx_tm = timer_get_ms(); 00225 00226 return 0; 00227 }
static void ping_finalize | ( | struct ping_info_t * | ping_info | ) | [static] |
Definition at line 241 of file ping.c.
References ping_info_t::complete_cb, ping_info_t::ctx, ping_info_t::num_rx, ping_info_t::num_tx, and print_stats().
Referenced by cmd_ping().
00241 { 00242 print_stats(ping_info); 00243 if (ping_info->complete_cb) { 00244 ping_info->complete_cb(ping_info->num_tx, ping_info->num_rx, ping_info->ctx); 00245 } 00246 }
static void ping_prepare_echo | ( | struct icmp_echo_hdr * | iecho, | |
struct ping_info_t * | ping_info | |||
) | [static] |
Prepare a echo ICMP request.
Definition at line 75 of file ping.c.
References ping_info_t::data_size, PING_ID, ping_info_t::seq_num, and ping_info_t::size.
Referenced by ping_send().
00077 { 00078 int i; 00079 00080 ICMPH_TYPE_SET(iecho,ICMP_ECHO); 00081 ICMPH_CODE_SET(iecho, 0); 00082 iecho->chksum = 0; 00083 iecho->id = PING_ID; 00084 iecho->seqno = htons(++ping_info->seq_num); 00085 iecho->chksum = 0; 00086 00087 /* fill the additional data buffer with some data */ 00088 for(i = 0; i < ping_info->data_size; i++) { 00089 ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = i; 00090 } 00091 00092 iecho->chksum = inet_chksum(iecho, ping_info->size); 00093 }
static u8_t ping_recv | ( | void * | arg, | |
struct raw_pcb * | pcb, | |||
struct pbuf * | p, | |||
struct ip_addr * | addr | |||
) | [static] |
Definition at line 96 of file ping.c.
References ping_info_t::flags, ip2str(), ping_info_t::last_rx_tm, ping_info_t::last_tx_tm, ping_info_t::num_rx, PING_ID, PING_REPLY, printk(), ping_info_t::quiet, ping_info_t::seq_num, and timer_get_ms().
Referenced by cmd_ping().
00098 { 00099 struct icmp_echo_hdr *iecho; 00100 struct ip_hdr *ip = p->payload; 00101 struct ping_info_t* ping_info = (struct ping_info_t*) arg; 00102 uint32_t us; 00103 00104 if (pbuf_header( p, -PBUF_IP_HLEN)==0) { 00105 iecho = p->payload; 00106 00107 if ((iecho->id == PING_ID) && 00108 (iecho->seqno == htons(ping_info->seq_num))) { 00109 ping_info->last_rx_tm = timer_get_ms(); 00110 ping_info->num_rx++; 00111 us = 1000 * 00112 (ping_info->last_rx_tm - ping_info->last_tx_tm); 00113 00114 if (!ping_info->quiet) 00115 printk("%d bytes from %s: icmp_seq=%d ttl=%d " \ 00116 "time=%d.%03d ms\n", 00117 p->tot_len, ip2str(ip->src), 00118 iecho->seqno, 00119 IPH_TTL(ip), 00120 us / 1000, us % 1000); 00121 00122 /* do some ping result processing */ 00123 ping_info->flags |= PING_REPLY; 00124 } 00125 } 00126 00127 pbuf_free(p); 00128 return 1; /* eat the event */ 00129 }
static void ping_send | ( | struct raw_pcb * | raw, | |
struct ping_info_t * | ping_info | |||
) | [static] |
Definition at line 131 of file ping.c.
References ping_info_t::destination, ping_info_t::first_tx_tm, ping_info_t::last_tx_tm, ping_info_t::num_tx, ping_prepare_echo(), ping_info_t::size, and timer_get_ms().
Referenced by cmd_ping().
00132 { 00133 struct pbuf *p; 00134 struct icmp_echo_hdr *iecho; 00135 00136 if (!(p = pbuf_alloc(PBUF_IP, ping_info->size, PBUF_RAM))) { 00137 return; 00138 } 00139 if ((p->len == p->tot_len) && (p->next == NULL)) { 00140 iecho = p->payload; 00141 00142 ping_prepare_echo(iecho, ping_info); 00143 raw_sendto(raw, p, &ping_info->destination); 00144 00145 if (!ping_info->first_tx_tm) 00146 ping_info->first_tx_tm = timer_get_ms(); 00147 ping_info->last_tx_tm = timer_get_ms(); 00148 ping_info->num_tx++; 00149 } 00150 pbuf_free(p); 00151 }
void ping_set_callback | ( | ping_complete_cb_t | cb, | |
void * | ctx | |||
) |
Definition at line 153 of file ping.c.
References ping_info_t::complete_cb, ping_info_t::ctx, and INFO.
void ping_stop | ( | uint32_t * | tx_cnt, | |
uint32_t * | rx_cnt | |||
) |
Definition at line 158 of file ping.c.
References ping_info_t::count, INFO, ping_info_t::num_rx, and ping_info_t::num_tx.
00158 { 00159 struct ping_info_t *ping_info = &INFO; 00160 00161 *tx_cnt = ping_info->num_tx; 00162 *rx_cnt = ping_info->num_rx; 00163 ping_info->count = ping_info->num_tx; 00164 if ( 0 == ping_info->count ) { 00165 ping_info->count = 1; 00166 } 00167 }
static void print_stats | ( | struct ping_info_t * | ping_info | ) | [static] |
Definition at line 229 of file ping.c.
References ping_info_t::destination, ping_info_t::first_tx_tm, ip2str(), ping_info_t::num_rx, ping_info_t::num_tx, printk(), and timer_get_ms().
Referenced by ping_finalize().
00230 { 00231 printk("\n--- %s ping statistics ---\n", 00232 ip2str(ping_info->destination)); 00233 printk("%d packets transmitted, %d received, %d%% packet loss, "\ 00234 "time %dms\n\n", 00235 ping_info->num_tx, ping_info->num_rx, 00236 100 * (ping_info->num_tx - ping_info->num_rx) / 00237 ping_info->num_tx, 00238 timer_get_ms() - ping_info->first_tx_tm); 00239 }
struct ping_info_t INFO [static] |
Definition at line 72 of file ping.c.
Referenced by cmd_ping(), ping_set_callback(), and ping_stop().