初级会员
- 积分
- 79
- 金钱
- 79
- 注册时间
- 2015-5-26
- 在线时间
- 10 小时
|
楼主 |
发表于 2016-8-2 18:22:05
|
显示全部楼层
太久没回来看帖,帐号直接被冻结。
其实机制很简单,ICMP其实基于IP层的,发送的时候只需要根据ICMP包的协议自己组一个一样的协议包就可以。至于时间的计算就是在发送的时候先获取一下单片机的运行时间,然后在ICMP Respond解析那里再一次获取一下单片机的运行时间,两个时间一减就是PING包的时间,不过肯定是有点延时的,但现在用起来其实还可以。
上码,不BB。
ICMP发送:
err_t
udp_sendicmp(struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *dst_ip, u16_t dst_port)
{
struct netif *netif;
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | 3, ("udp_send\n"));
/* find the outgoing network interface for this packet */
#if LWIP_IGMP
netif = ip_route((ip_addr_ismulticast(dst_ip))?(&(pcb->multicast_ip))dst_ip));
#else
netif = ip_route(dst_ip);
#endif /* LWIP_IGMP */
/* no outgoing network interface could be found? */
if (netif == NULL) {
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", dst_ip->addr));
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
return udp_sendto_ping(pcb, p, dst_ip, dst_port, netif);
}
err_t
udp_sendto_ping(struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif)
{
// struct udp_hdr *udphdr;
struct ip_addr *src_ip;
err_t err;
struct pbuf *q; /* q will be sent down the stack */
struct icmp_echo_hdr *icmphdr; //kaishui
/* not enough space to add an UDP header to first pbuf in given p chain? */
if (pbuf_header(p, sizeof(struct icmp_echo_hdr))) {
/* allocate header in a separate new pbuf */
// q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr), PBUF_RAM);
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr)+ IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
PBUF_RAM);
/* new header pbuf could not be allocated? */
/* chain header q in front of given pbuf p */
pbuf_chain(q, p);
/* first pbuf q points to header pbuf */
}
/* q now represents the packet to be sent */
icmphdr = (struct icmp_echo_hdr *)q->payload;
icmphdr->type = 8;
icmphdr->code = 0;
icmphdr->id =htons(0x0100) ;
icmphdr->seqno =htons(0x51d1);
icmphdr->chksum = 0;
// icmphdr->chksum = inet_chksum(p->payload, 10);
icmphdr->chksum = inet_chksum(icmphdr, q->len);
/* PCB local address is IP_ANY_ADDR? */
if (ip_addr_isany(&pcb->local_ip))
{
/* use outgoing network interface IP address as source address */
src_ip = &(netif->ip_addr);
}
else
{
/* check if UDP PCB local IP address is correct
* this could be an old address if netif->ip_addr has changed */
/* use UDP PCB local IP address as source address */
src_ip = &(pcb->local_ip);
}
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_ICMP, netif);
snmp_inc_udpoutdatagrams();
/* did we chain a separate header pbuf earlier? */
if (q != p)
{
/* free the header pbuf */
pbuf_free(q);
q = NULL;
/* p is still referenced by the caller, and will live on */
}
UDP_STATS_INC(udp.xmit);
pbuf_free(p);//important
return err;
}
void PingInit(void)
{
struct ip_addr ipaddr;
unsigned int port = 2000; //69
p = pbuf_alloc(PBUF_RAW,10,PBUF_RAM);
p->payload=(void *)UDPData;
IP4_ADDR(&ipaddr,0,0,0,0);
UDPpcb = udp_new();
udp_bind(UDPpcb,&ipaddr, port);
}
void ICMP_Ping(void)
{
struct ip_addr dstipaddr;
p = pbuf_alloc(PBUF_RAW,10,PBUF_RAM);
p->payload=(void *)UDPData;
OSTimeDlyHMSM(0, 0, 0, 500); //wait 200ms
memcpy(&dstipaddr.addr,&flash_read.lwip_msg->dns2,4);
if(mt_client.respond_flag ==0)
{
cnt_1ms = 0;
}
else
{
mt_client.ping_end.end_time.tv_usec = 1000;
mt_client.timeout_flag = 1;
}
udp_sendicmp(UDPpcb,p,&dstipaddr,2000);
mt_client.respond_flag = 1;
ntx_packet++;
mt_client.ping_before.end_time.tv_sec = get_running_time();
mt_client.ping_before.end_time.tv_usec = get_1mstime();//ms
}
ICMP接收:(icmp.c)
void
icmp_input(struct pbuf *p, struct netif *inp)
{
....
case ICMP_ER:
/* This is OK, echo reply might have been parsed by a raw PCB
(as obviously, an echo request has been sent, too). */
#ifdef PINGPACK_TEST
nrx_packet ++;
mt_client.ping_after.end_time.tv_sec = get_running_time();
mt_client.ping_after.end_time.tv_usec = get_1mstime();//ms
mt_client.ping_end.end_time.tv_sec = 0;
mt_client.ping_end.end_time.tv_usec = mt_client.ping_after.end_time.tv_usec - mt_client.ping_before.end_time.tv_usec;
mt_client.respond_flag = 0;
if(mt_client.ping_end.end_time.tv_usec > 10)//ms
{
mt_client.timeout_flag = 1;
}
#endif
break;
...
} |
|