The pbuf leak might still be in there, but the checksum generation has
already been corrected in CVS (I assume you are using 1.3.0, you don't
tell that).
Simon
HM2 wrote:
I ran into a number of issues using the PING app from the contrib section.
I am using RAW mode. The PING app just did requests, so I wrote some
additional code for it to handle replies now as well. That seems to work
fine, but working on this I then noticed some other issues. The previous
first routine ping_prepare_echo() was doing the checksum at the wrong place.
It needs to be last, after the sample data is built, since the checksum
covers that area as well. Also, there was a pbuf leak in the ping_recv()
routine. It needs to free the main pbuf, or after enough pings, the pool is
consumed. The significant portions of my code changes are given below.
Regards, Chris.
// Prepare a ECHO ICMP REQUEST
static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) {
int i;
ICMPH_TYPE_SET(iecho,ICMP_ECHO);
ICMPH_CODE_SET(iecho, 0);
iecho->chksum = 0;
iecho->id = PING_ID;
iecho->seqno = htons(++ping_seq_num);
// fill the additional data buffer with some data
for(i = 0; i < PING_DATA_SIZE; i++) {
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = i+48; // easier to
look at ASCII
}
iecho->chksum = inet_chksum(iecho, len); // CNS, checksum needs to be done
after data
}
// CNS, Prepare a ECHO REPLY
static void ping_prepare_reply( struct icmp_echo_hdr *ireply, u16_t len,
struct icmp_echo_hdr *iecho) {
int i,m;
ICMPH_TYPE_SET(ireply,ICMP_ER); // echo reply
ICMPH_CODE_SET(ireply, 0);
ireply->id = iecho->id; // copy ID from request
ireply->seqno = iecho->seqno; // copy seqno from request
ireply->chksum = 0;
// copy data from echo request
// Ping Size may not be standard, so calc from actual msg size and sub
header
m = len-sizeof(struct icmp_echo_hdr);
for(i = 0; i < m; i++) {
((char*)ireply)[sizeof(struct icmp_echo_hdr) + i] =
((char*)iecho)[sizeof(struct icmp_echo_hdr) + i];
}
ireply->chksum = inet_chksum(ireply, len);
}
// Ping Rcve using the raw ip
static u8_t ping_recv(void *arg, struct raw_pcb *pcb, struct pbuf *p, struct
ip_addr *addr) {
LWIP_UNUSED_ARG(arg);
struct icmp_echo_hdr *iecho;
struct icmp_echo_hdr *ireply;
struct pbuf *r;
int hlen;
struct in_addr val;
if (pbuf_header( p, -PBUF_IP_HLEN)==0) {
iecho = p->payload;
// CNS this section generates REPLY to any ECHO REQUEST
if (iecho->_type_code == ICMP_ECHO) { // rcvd echo, generate echo reply
hlen = p->tot_len; // length of ping request, typ 40 bytes
r = pbuf_alloc(PBUF_IP, hlen, PBUF_RAM); // new pbuf
if (r!=NULL) {
ireply=r->payload;
ping_prepare_reply(ireply, hlen,iecho);
raw_sendto(pcb, r, addr);
pbuf_free(r); // dump new pbuf
r = NULL;
}
}
// this section handles replies to our ECHO REQUEST
if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
val.s_addr = addr->addr;
printf("Ping Reply %s\n", inet_ntoa(val));
LWIP_DEBUGF( PING_DEBUG, ("ping: recv "));
ip_addr_debug_print(PING_DEBUG, addr);
LWIP_DEBUGF( PING_DEBUG, (" %lu ms\n", (sys_now()-ping_time)));
// do some ping result processing
PING_RESULT(1);
}
}
pbuf_free(p); // CNS, free the org pbuf, otherwise leak!
p=NULL;
return 1; // eat the event
}
_______________________________________________
lwip-users mailing list
lwip-users@nongnu.org
http://lists.nongnu.org/mailman/listinfo/lwip-users
_______________________________________________
lwip-users mailing list
lwip-users@nongnu.org
http://lists.nongnu.org/mailman/listinfo/lwip-users