lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-users] RE : ICMP ping send/receive


From: Frédéric BERNON
Subject: [lwip-users] RE : ICMP ping send/receive
Date: Thu, 11 Oct 2007 17:45:21 +0200

(Note I reply with the list in copy)

This is a part of code I use to send "ping" (I suppose there is some other ping 
availables with netconn & raw api). Note it need CVS HEAD for LWIP_SO_RCVTIMEO 
option (need to be set to 1 in your lwipopts.h). Sorry, comments are in french 
(but code is simple). There is two functions specific to my port (but I think 
you can easily create) :

/**
 * return number of milliseconds since boot time (or any other reference)
 */
u32_t sys_start_tickcount();

/**
 * return number of milliseconds since "ref"
 */
u32_t sys_stop_tickcount( u32_t ref);


/*----------------------------------------------------------------------------*/
int Ping( u32_t addr, u32_t length, int verbose)
/*----------------------------------------------------------------------------*/
{ /* Variables de travail */
  int                   iResult = 0;
#if LWIP_SOCKET && LWIP_ICMP
  static int            seq_num = 0;
  int                   timeout = PING_TIMEOUT;
  int                   err     = 0;
  int                   iIndex;
  int                   hSocket;
  u32_t                 ulTickCount;
  char                  reply[64];
  struct icmp_echo_hdr* pecho;
  struct icmp_echo_hdr* pechoreply=(struct icmp_echo_hdr*)reply;
  struct sockaddr_in    saLocal;
  struct sockaddr_in    to;
  int                   fromlen;
  struct sockaddr_in    from;  

  /* Affichage dans la console */
  if (verbose) printf("Ping %lu.%lu.%lu.%lu : bytes=%i\n", ((addr & 
0x000000FF)>>0), ((addr & 0x0000FF00)>>8), ((addr & 0x00FF0000)>>16), ((addr & 
0xFF000000)>>24), length);

  /* Allocation de la trame à envoyer... */
  if (!(pecho = malloc(sizeof(struct icmp_echo_hdr)+length))) return ENOMEM;
  
  /* Remplissage de la donnée de la trame ICMP "Echo" */
  for( iIndex=0; iIndex<length; iIndex++)
   { ((char*)(pecho))[sizeof(struct icmp_echo_hdr)+iIndex]=('a'+(iIndex%26));
   }
     
  /* Ouverture d'une socket en mode "raw" pour ICMP */
  hSocket = socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP);
  if (hSocket >= 0)
   { /* Préparation de l'Adresse Locale */
     memset(&saLocal, 0, sizeof(saLocal));
     saLocal.sin_family      = AF_INET;
     saLocal.sin_port        = htons(INADDR_ANY);
     saLocal.sin_addr.s_addr = htons(INADDR_ANY);

     /* Liaison à l'Adresse Locale */
     if (bind( hSocket, (struct sockaddr *)&saLocal, sizeof(saLocal))==0)
      { /* Paramétrage du timeout de réception */
        err = setsockopt( hSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, 
sizeof(timeout));

        /* Préparation de la trame ICMP "Echo" */
        ICMPH_TYPE_SET(pecho,ICMP_ECHO);
        pecho->chksum      = 0;
        pecho->id          = htons(0x1234); /* Pour repérer ces "Pings" */
        pecho->seqno       = htons(seq_num++);
        pecho->chksum      = inet_chksum(pecho, sizeof(struct 
icmp_echo_hdr)+length);

        /* Préparation de l'adresse à "pinger" */
        memset( &to, 0, sizeof(to));
        to.sin_len         = sizeof(to);
        to.sin_family      = AF_INET;
        to.sin_port        = htons(INADDR_ANY);
        to.sin_addr.s_addr = addr;
        
        /* Si le "ping" est bien envoyé... */
        if ((err = sendto( hSocket, pecho, sizeof(struct icmp_echo_hdr)+length, 
0, (struct sockaddr*)&to, sizeof(to)))>=0)
         { /* Réception de l' "Echo" (avec mesure du délai en ms) */
           ulTickCount = sys_start_tickcount();
           do
            { err = recvfrom( hSocket, reply, sizeof(reply), 0, (struct 
sockaddr*)&from, (socklen_t *)&fromlen);
            }
           while ((err>0) && ((pechoreply->id!=pecho->id) || 
(pechoreply->seqno!=pecho->seqno)) && 
(sys_stop_tickcount(ulTickCount)<=timeout) );
           ulTickCount = sys_stop_tickcount(ulTickCount);
           
           /* Si le "ping" est bien reçu... */
           if (err>0)
            { /* Affichage dans la console */
              if (verbose) printf("Ping Reply from %lu.%lu.%lu.%lu : bytes=%i, 
delay=%lums\n", ((addr & 0x000000FF)>>0), ((addr & 0x0000FF00)>>8), ((addr & 
0x00FF0000)>>16), ((addr & 0xFF000000)>>24), (err-sizeof(struct 
icmp_echo_hdr))/*length*/, ulTickCount);
              iResult = 0;         
            }
           /* Si on a eu une "non-réception"... */
           else
            { /* Affichage dans la console */
              if (verbose) printf("Ping Request timed out...\n");
              iResult = ETIMEDOUT;
            }
         }
        /* Si on n'a pas pu envoyer... */
        else
         { /* Mémoriser l'erreur */
           iResult = errno;
         
           /* Affichage dans la console */
           if (verbose) printf("Ping sendto==%i\n", iResult);
         }
      }
      
     /* Fermeture de la Socket */
     closesocket(hSocket);
   }
  /* Si on n'a pas pu ouvrir la Socket... */
  else
   { /* Mémoriser l'erreur */
     iResult = errno;
   
     /* Affichage dans la console */
     if (verbose) printf("Ping socket==%i\n", iResult);
   }
   
  /* Désallocation de la trame à envoyer... */
  free(pecho);

#endif /* LWIP_SOCKET && LWIP_ICMP */
  return iResult;
}

I do the same kind of probe with my gateway. The code I do is something like 
that :

           // Si la Gateway est définie et qu'on ne ping pas la Gateway...
           if (netPing( inet_addr(szIPGateway), 32, TRUE)!=0)
            { iPingErrors++;
              if (iPingErrors>=MAXPINGERRORS)// Environ MAXPINGERRORS*50sec
               { // Log du problème du PING
                 tmSyslog( LOG_MAKEPRI(LOG_LOCAL0,LOG_EMERG), "PING Gateway 
Failure...");
                 // Enregistrer le fichier de Log en Flash
                 XmlSave( lpXML_IPPNX_LOG_TABLE, IPPNX_LOG_TABLE_FILENAME);
                 // Déclencher le "Software reset"
                 tmEncMp4XcastPicmat_SoftwareReset();
               }
            }
           else
            { // Réinitialisation du compteur
              iPingErrors = 0;
            }
 
I hope it can help you.
  
====================================
Frédéric BERNON 
HYMATOM SA 
Chef de projet informatique 
Microsoft Certified Professional 
Tél. : +33 (0)4-67-87-61-10 
Fax. : +33 (0)4-67-70-85-44 
Email : address@hidden 
Web Site : http://www.hymatom.fr 
====================================
P Avant d'imprimer, penser à l'environnement
 


-----Message d'origine-----
De : Andy Kunz [mailto:address@hidden 
Envoyé : jeudi 11 octobre 2007 17:14
À : Frédéric BERNON
Objet : ICMP ping send/receive



Frédéric,

Thanks for your efforts on lwIP.  I have enjoyed quite a bit of growth of my 
own understanding as a result of reading through the code.

This question comes to you after reading item # 7272 regarding optional ICMP.

I am working on an lwIP/FreeRTOS project and we are having occasional trouble 
with the IP stack locking up.  Sometimes only for 1/2 hour, sometimes it never 
recovers (after days).  (Sniffers show us that when "locked up", the board does 
not reply to a ping even though it sometimes will generate SNMP traps). 
We have experienced problems with TCP messages, for instance, not coming out of 
the system in a timely manner as well - perhaps this is the same problem.

With as intermittent as the problem is, I was instructed to "hide" it rather 
than delve into the inner workings of the stack to find the source of the 
issue.  (Our customer is pushing for a shipment of _something_ rather than 
nothing).

The implementation I was told to create is this:

The code should send several pings to the gateway.  If no reply is received, 
assume the worst and reset the controller.

Attempting to write a ping send/response has turned out to be much more 
difficult than I would have expected.  Rather than a simple socket setup such 
as used here

http://www.jbox.dk/sanos/source/utils/sh/ping.c.html

(which doesn't work because among other things IPPROTO_ICMP is not supported).

After googling for the past few days and all this morning for various 
possibilities, I do not find any relatively simple ability to create an ICMP 
echo request message using facilities in lwIP (unless I am overlooking 
something in a gross manner).  I suppose I can capture the reply in
icmp_input() in icmp.c.  There does not appear to be something of this sort 
available as part of the lwIP downloads.

My question to you is, do you know of a ping generator that runs in lwIP?  I 
would expect it to only require a few lines of code - ICMP is supposed to be 
simple.

Any feedback (even negative comments!) would be appreciated!

Thanks.

Andy


_______________________________________________
  Message sent via/by Savannah
  http://savannah.nongnu.org/

Attachment: Frédéric BERNON.vcf
Description: Frédéric BERNON.vcf


reply via email to

[Prev in Thread] Current Thread [Next in Thread]