#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 246 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().
00247 { 00248 static enum { 00249 INIT, 00250 PING, 00251 WAIT_REPLY 00252 } state = INIT; 00253 00254 struct ping_info_t *ping_info = &INFO; 00255 static struct raw_pcb *pcb; 00256 00257 switch (state) { 00258 case INIT: 00259 if (init_ping_info(argc, argv, ping_info) != 0) { 00260 printk("Usage: ping [-c count] [-i interval] " \ 00261 "[-s packetsize]\n " \ 00262 "[-w deadline] [-q] destination\n"); 00263 return CMD_DONE; 00264 } 00265 00266 if (!(pcb = raw_new(IP_PROTO_ICMP))) { 00267 printk("could not allocate pcb\n"); 00268 state = INIT; 00269 return CMD_DONE; 00270 } 00271 raw_recv(pcb, ping_recv, ping_info); 00272 raw_bind(pcb, IP_ADDR_ANY); 00273 00274 printk("PING %s %d(%d) bytes of data\n", 00275 ip2str(ping_info->destination), 00276 ping_info->data_size, 00277 ping_info->size); 00278 state = PING; 00279 /* fall through */ 00280 00281 case PING: 00282 if (!netif_is_up(netif_default)) { 00283 printk("netif is down\n"); 00284 raw_remove(pcb); 00285 state = INIT; 00286 return CMD_DONE; 00287 } 00288 00289 if (ping_info->count && ping_info->num_tx == ping_info->count) { 00290 ping_finalize(ping_info); 00291 raw_remove(pcb); 00292 state = INIT; 00293 return CMD_DONE; 00294 } 00295 00296 if (timer_get_ms() < ping_info->last_rx_tm + ping_info->interval) { 00297 return CMD_INPROGRESS; 00298 } 00299 ping_send(pcb, ping_info); 00300 00301 state = WAIT_REPLY; 00302 return CMD_INPROGRESS; 00303 00304 case WAIT_REPLY: 00305 if (ping_info->flags & PING_REPLY) { 00306 ping_info->flags &= (~PING_REPLY); 00307 state = PING; 00308 return CMD_INPROGRESS; 00309 } 00310 00311 if (timer_get_ms() > 00312 ping_info->last_tx_tm + ping_info->timeout) { 00313 if (!ping_info->quiet) 00314 printk("timeout from %s\n", 00315 ip2str(ping_info->destination)); 00316 state = PING; 00317 return CMD_INPROGRESS; 00318 } 00319 00320 if (ping_info->deadline && 00321 timer_get_ms() > 00322 ping_info->first_tx_tm + ping_info->deadline * 1000) { 00323 ping_finalize(ping_info); 00324 raw_remove(pcb); 00325 state = INIT; 00326 return CMD_DONE; 00327 } 00328 00329 return CMD_INPROGRESS; 00330 } 00331 00332 /* unreachable */ 00333 Assert(0); 00334 return CMD_DONE; 00335 }
static int init_ping_info | ( | int | argc, | |
char * | argv[], | |||
struct ping_info_t * | ping_info | |||
) | [static] |
Definition at line 167 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().
00168 { 00169 int c; 00170 ping_complete_cb_t cb; 00171 void *ctx; 00172 00173 cb = ping_info->complete_cb; 00174 ctx = ping_info->ctx; 00175 memset(ping_info, 0, sizeof(struct ping_info_t)); 00176 ping_info->complete_cb = cb; 00177 ping_info->ctx = ctx; 00178 00179 ping_info->deadline = 0; 00180 ping_info->interval = 1000; 00181 ping_info->timeout = 3000; 00182 ping_info->data_size = 32; 00183 ping_info->count = 3; 00184 ping_info->destination = 00185 netif_default ? netif_default->gw : ip_addr_any; 00186 00187 optind = 1; 00188 while ((c = getopt(argc, argv, "c:i:s:w:q")) != -1) { 00189 switch (c) { 00190 case 'c': 00191 ping_info->count = atoi(optarg); 00192 break; 00193 00194 case 'i': 00195 ping_info->interval = atoi(optarg); 00196 break; 00197 00198 case 's': 00199 ping_info->data_size = atoi(optarg); 00200 break; 00201 00202 case 'q': 00203 ping_info->quiet = TRUE; 00204 break; 00205 00206 case 'w': 00207 ping_info->deadline = atoi(optarg); 00208 break; 00209 } 00210 } 00211 00212 ping_info->size = sizeof(struct icmp_echo_hdr) + ping_info->data_size; 00213 00214 if (optind >= argc) 00215 return -1; 00216 00217 ping_info->destination = str2ip(argv[optind]); 00218 if (!ping_info->destination.addr) 00219 return -1; 00220 00221 00222 ping_info->last_rx_tm = timer_get_ms(); 00223 00224 return 0; 00225 }
static void ping_finalize | ( | struct ping_info_t * | ping_info | ) | [static] |
Definition at line 239 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().
00239 { 00240 print_stats(ping_info); 00241 if (ping_info->complete_cb) { 00242 ping_info->complete_cb(ping_info->num_tx, ping_info->num_rx, ping_info->ctx); 00243 } 00244 }
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 = inet_chksum(iecho, ping_info->size); 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 }
static u8_t ping_recv | ( | void * | arg, | |
struct raw_pcb * | pcb, | |||
struct pbuf * | p, | |||
struct ip_addr * | addr | |||
) | [static] |
Definition at line 94 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().
00096 { 00097 struct icmp_echo_hdr *iecho; 00098 struct ip_hdr *ip = p->payload; 00099 struct ping_info_t* ping_info = (struct ping_info_t*) arg; 00100 uint32_t us; 00101 00102 if (pbuf_header( p, -PBUF_IP_HLEN)==0) { 00103 iecho = p->payload; 00104 00105 if ((iecho->id == PING_ID) && 00106 (iecho->seqno == htons(ping_info->seq_num))) { 00107 ping_info->last_rx_tm = timer_get_ms(); 00108 ping_info->num_rx++; 00109 us = 1000 * 00110 (ping_info->last_rx_tm - ping_info->last_tx_tm); 00111 00112 if (!ping_info->quiet) 00113 printk("%d bytes from %s: icmp_seq=%d ttl=%d " \ 00114 "time=%d.%03d ms\n", 00115 p->tot_len, ip2str(ip->src), 00116 iecho->seqno, 00117 IPH_TTL(ip), 00118 us / 1000, us % 1000); 00119 00120 /* do some ping result processing */ 00121 ping_info->flags |= PING_REPLY; 00122 } 00123 } 00124 00125 pbuf_free(p); 00126 return 1; /* eat the event */ 00127 }
static void ping_send | ( | struct raw_pcb * | raw, | |
struct ping_info_t * | ping_info | |||
) | [static] |
Definition at line 129 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().
00130 { 00131 struct pbuf *p; 00132 struct icmp_echo_hdr *iecho; 00133 00134 if (!(p = pbuf_alloc(PBUF_IP, ping_info->size, PBUF_RAM))) { 00135 return; 00136 } 00137 if ((p->len == p->tot_len) && (p->next == NULL)) { 00138 iecho = p->payload; 00139 00140 ping_prepare_echo(iecho, ping_info); 00141 raw_sendto(raw, p, &ping_info->destination); 00142 00143 if (!ping_info->first_tx_tm) 00144 ping_info->first_tx_tm = timer_get_ms(); 00145 ping_info->last_tx_tm = timer_get_ms(); 00146 ping_info->num_tx++; 00147 } 00148 pbuf_free(p); 00149 }
void ping_set_callback | ( | ping_complete_cb_t | cb, | |
void * | ctx | |||
) |
Definition at line 151 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 156 of file ping.c.
References ping_info_t::count, INFO, ping_info_t::num_rx, and ping_info_t::num_tx.
00156 { 00157 struct ping_info_t *ping_info = &INFO; 00158 00159 *tx_cnt = ping_info->num_tx; 00160 *rx_cnt = ping_info->num_rx; 00161 ping_info->count = ping_info->num_tx; 00162 if ( 0 == ping_info->count ) { 00163 ping_info->count = 1; 00164 } 00165 }
static void print_stats | ( | struct ping_info_t * | ping_info | ) | [static] |
Definition at line 227 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().
00228 { 00229 printk("\n--- %s ping statistics ---\n", 00230 ip2str(ping_info->destination)); 00231 printk("%d packets transmitted, %d received, %d%% packet loss, "\ 00232 "time %dms\n\n", 00233 ping_info->num_tx, ping_info->num_rx, 00234 100 * (ping_info->num_tx - ping_info->num_rx) / 00235 ping_info->num_tx, 00236 timer_get_ms() - ping_info->first_tx_tm); 00237 }
struct ping_info_t INFO [static] |
Definition at line 72 of file ping.c.
Referenced by cmd_ping(), ping_set_callback(), and ping_stop().