ping.c File Reference

#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 Documentation

#define PING_ID   0xAFAF

Definition at line 49 of file ping.c.

Referenced by ping_prepare_echo(), and ping_recv().

#define PING_REPLY   (1 << 0)

Definition at line 69 of file ping.c.

Referenced by cmd_ping(), and ping_recv().


Function Documentation

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.

00151                                                          {
00152         INFO.complete_cb = cb;
00153         INFO.ctx = ctx;
00154 }

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 }


Variable Documentation

struct ping_info_t INFO [static]

Definition at line 72 of file ping.c.

Referenced by cmd_ping(), ping_set_callback(), and ping_stop().


Generated on Thu Dec 17 19:57:55 2009 for AVR32 - H&D by  doxygen 1.5.5