implement ping using new network stack
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
17f1f5b3b7
commit
98ff00b6d2
145
net/ping.c
145
net/ping.c
|
@ -2,102 +2,103 @@
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <clock.h>
|
#include <clock.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
|
||||||
static ushort PingSeqNo;
|
static uint16_t ping_sequence_number;
|
||||||
|
|
||||||
static IPaddr_t NetPingIP; /* the ip address to ping */
|
static IPaddr_t net_ping_ip; /* the ip address to ping */
|
||||||
|
|
||||||
static int PingSend(void)
|
#define PING_STATE_INIT 0
|
||||||
|
#define PING_STATE_SUCCESS 1
|
||||||
|
|
||||||
|
static int ping_state;
|
||||||
|
|
||||||
|
static struct net_connection *ping_con;
|
||||||
|
|
||||||
|
static int ping_send(void)
|
||||||
{
|
{
|
||||||
static uchar mac[6];
|
unsigned char *payload;
|
||||||
IP_t *ip;
|
struct icmphdr *icmp;
|
||||||
ushort *s;
|
uint64_t ts;
|
||||||
uchar *pkt;
|
|
||||||
|
|
||||||
/* XXX always send arp request */
|
icmp = ping_con->icmp;
|
||||||
|
|
||||||
memcpy(mac, NetEtherNullAddr, 6);
|
icmp->type = ICMP_ECHO_REQUEST;
|
||||||
|
icmp->code = 0;
|
||||||
|
icmp->checksum = 0;
|
||||||
|
icmp->un.echo.id = 0;
|
||||||
|
icmp->un.echo.sequence = htons(ping_sequence_number);
|
||||||
|
|
||||||
pr_debug("sending ARP for %08lx\n", NetPingIP);
|
ping_sequence_number++;
|
||||||
|
|
||||||
NetArpWaitPacketIP = NetPingIP;
|
payload = (char *)(icmp + 1);
|
||||||
NetArpWaitPacketMAC = mac;
|
ts = get_time_ns();
|
||||||
|
memcpy(payload, &ts, sizeof(ts));
|
||||||
pkt = NetArpWaitTxPacket;
|
payload[8] = 0xab;
|
||||||
pkt += NetSetEther(pkt, mac, PROT_IP);
|
payload[9] = 0xcd;
|
||||||
|
return net_icmp_send(ping_con, 9);
|
||||||
ip = (IP_t *)pkt;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Construct an IP and ICMP header. (need to set no fragment bit - XXX)
|
|
||||||
*/
|
|
||||||
ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
|
|
||||||
ip->ip_tos = 0;
|
|
||||||
ip->ip_len = htons(IP_HDR_SIZE_NO_UDP + 8);
|
|
||||||
ip->ip_id = htons(NetIPID++);
|
|
||||||
ip->ip_off = htons(0x4000); /* No fragmentation */
|
|
||||||
ip->ip_ttl = 255;
|
|
||||||
ip->ip_p = 0x01; /* ICMP */
|
|
||||||
ip->ip_sum = 0;
|
|
||||||
NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
|
|
||||||
NetCopyIP((void*)&ip->ip_dst, &NetPingIP); /* - "" - */
|
|
||||||
ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
|
|
||||||
|
|
||||||
s = &ip->udp_src; /* XXX ICMP starts here */
|
|
||||||
s[0] = htons(0x0800); /* echo-request, code */
|
|
||||||
s[1] = 0; /* checksum */
|
|
||||||
s[2] = 0; /* identifier */
|
|
||||||
s[3] = htons(PingSeqNo++); /* sequence number */
|
|
||||||
s[1] = ~NetCksum((uchar *)s, 8/2);
|
|
||||||
|
|
||||||
/* size of the waiting packet */
|
|
||||||
NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8;
|
|
||||||
|
|
||||||
/* and do the ARP request */
|
|
||||||
NetArpWaitTimerStart = get_time_ns();
|
|
||||||
ArpRequest();
|
|
||||||
return 1; /* waiting */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void ping_handler(char *pkt, unsigned len)
|
||||||
PingTimeout (void)
|
|
||||||
{
|
|
||||||
NetState = NETLOOP_FAIL; /* we did not get the reply */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
|
|
||||||
{
|
{
|
||||||
IPaddr_t tmp;
|
IPaddr_t tmp;
|
||||||
IP_t *ip = (IP_t *)pkt;
|
struct iphdr *ip = net_eth_to_iphdr(pkt);
|
||||||
|
|
||||||
tmp = NetReadIP((void *)&ip->ip_src);
|
tmp = net_read_ip((void *)&ip->saddr);
|
||||||
if (tmp != NetPingIP)
|
if (tmp != net_ping_ip)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
NetState = NETLOOP_SUCCESS;
|
ping_state = PING_STATE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_ping(struct command *cmdtp, int argc, char *argv[])
|
int do_ping(struct command *cmdtp, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
if (argc < 2 || string_to_ip(argv[1], &NetPingIP))
|
int ret;
|
||||||
|
uint64_t ping_start = 0;
|
||||||
|
|
||||||
|
if (argc < 2 || string_to_ip(argv[1], &net_ping_ip))
|
||||||
return COMMAND_ERROR_USAGE;
|
return COMMAND_ERROR_USAGE;
|
||||||
|
|
||||||
if (NetLoopInit(PING) < 0)
|
ping_con = net_icmp_new(net_ping_ip, ping_handler);
|
||||||
return 1;
|
if (IS_ERR(ping_con)) {
|
||||||
|
ret = PTR_ERR(ping_con);
|
||||||
NetSetTimeout (10 * SECOND, PingTimeout);
|
goto out;
|
||||||
NetSetHandler (PingHandler);
|
|
||||||
PingSend();
|
|
||||||
|
|
||||||
if (NetLoop() < 0) {
|
|
||||||
printf("ping failed; host %s is not alive\n", argv[1]);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("host %s is alive\n", argv[1]);
|
ping_start = get_time_ns();
|
||||||
|
ret = ping_send();
|
||||||
|
if (ret)
|
||||||
|
goto out_unreg;
|
||||||
|
|
||||||
return 0;
|
ping_state = PING_STATE_INIT;
|
||||||
|
ping_sequence_number = 0;
|
||||||
|
|
||||||
|
while (ping_state == PING_STATE_INIT) {
|
||||||
|
if (ctrlc()) {
|
||||||
|
ret = -EINTR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
net_poll();
|
||||||
|
|
||||||
|
if (is_timeout(ping_start, 10 * SECOND)) {
|
||||||
|
ping_start = get_time_ns();
|
||||||
|
ret = ping_send();
|
||||||
|
if (ret)
|
||||||
|
goto out_unreg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
printf("host %s is alive\n", argv[1]);
|
||||||
|
|
||||||
|
out_unreg:
|
||||||
|
net_unregister(ping_con);
|
||||||
|
out:
|
||||||
|
if (ret)
|
||||||
|
printf("ping failed: %s\n", strerror(-ret));
|
||||||
|
return ping_state == PING_STATE_SUCCESS ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAREBOX_CMD_START(ping)
|
BAREBOX_CMD_START(ping)
|
||||||
|
|
Loading…
Reference in New Issue