mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-09-03 04:51:35 +02:00
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"' I failed to notice that b4 noticed it was based on next and so took that as the base commit and merged that part of next to master. This reverts commit c8ffd1356d42223cbb8c86280a083cc3c93e6426, reversing changes made to 2ee6f3a5f7550de3599faef9704e166e5dcace35. Reported-by: Jonas Karlman <jonas@kwiboo.se> Signed-off-by: Tom Rini <trini@konsulko.com>
119 lines
2.6 KiB
C
119 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2013 Allied Telesis Labs NZ
|
|
* Chris Packham, <judge.packham@gmail.com>
|
|
*
|
|
* Copyright (C) 2022 YADRO
|
|
* Viacheslav Mitrofanov <v.v.mitrofanov@yadro.com>
|
|
*/
|
|
|
|
/* Simple ping6 implementation */
|
|
|
|
#include <common.h>
|
|
#include <net.h>
|
|
#include <net6.h>
|
|
#include "ndisc.h"
|
|
|
|
static ushort seq_no;
|
|
|
|
/* the ipv6 address to ping */
|
|
struct in6_addr net_ping_ip6;
|
|
|
|
int
|
|
ip6_make_ping(uchar *eth_dst_addr, struct in6_addr *neigh_addr, uchar *pkt)
|
|
{
|
|
struct echo_msg *msg;
|
|
u16 len;
|
|
u16 csum_p;
|
|
uchar *pkt_old = pkt;
|
|
|
|
len = sizeof(struct echo_msg);
|
|
|
|
pkt += net_set_ether(pkt, eth_dst_addr, PROT_IP6);
|
|
pkt += ip6_add_hdr(pkt, &net_ip6, neigh_addr, PROT_ICMPV6,
|
|
IPV6_NDISC_HOPLIMIT, len);
|
|
|
|
/* ICMPv6 - Echo */
|
|
msg = (struct echo_msg *)pkt;
|
|
msg->icmph.icmp6_type = IPV6_ICMP_ECHO_REQUEST;
|
|
msg->icmph.icmp6_code = 0;
|
|
msg->icmph.icmp6_cksum = 0;
|
|
msg->icmph.icmp6_identifier = 0;
|
|
msg->icmph.icmp6_sequence = htons(seq_no++);
|
|
msg->id = msg->icmph.icmp6_identifier; /* these seem redundant */
|
|
msg->sequence = msg->icmph.icmp6_sequence;
|
|
|
|
/* checksum */
|
|
csum_p = csum_partial((u8 *)msg, len, 0);
|
|
msg->icmph.icmp6_cksum = csum_ipv6_magic(&net_ip6, neigh_addr, len,
|
|
PROT_ICMPV6, csum_p);
|
|
|
|
pkt += len;
|
|
|
|
return pkt - pkt_old;
|
|
}
|
|
|
|
int ping6_send(void)
|
|
{
|
|
uchar *pkt;
|
|
static uchar mac[6];
|
|
|
|
/* always send neighbor solicit */
|
|
|
|
memcpy(mac, net_null_ethaddr, 6);
|
|
|
|
net_nd_sol_packet_ip6 = net_ping_ip6;
|
|
net_nd_packet_mac = mac;
|
|
|
|
pkt = net_nd_tx_packet;
|
|
pkt += ip6_make_ping(mac, &net_ping_ip6, pkt);
|
|
|
|
/* size of the waiting packet */
|
|
net_nd_tx_packet_size = (pkt - net_nd_tx_packet);
|
|
|
|
/* and do the ARP request */
|
|
net_nd_try = 1;
|
|
net_nd_timer_start = get_timer(0);
|
|
ndisc_request();
|
|
return 1; /* waiting */
|
|
}
|
|
|
|
static void ping6_timeout(void)
|
|
{
|
|
eth_halt();
|
|
net_set_state(NETLOOP_FAIL); /* we did not get the reply */
|
|
}
|
|
|
|
void ping6_start(void)
|
|
{
|
|
printf("Using %s device\n", eth_get_name());
|
|
net_set_timeout_handler(10000UL, ping6_timeout);
|
|
|
|
ping6_send();
|
|
}
|
|
|
|
int ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len)
|
|
{
|
|
struct icmp6hdr *icmp =
|
|
(struct icmp6hdr *)(((uchar *)ip6) + IP6_HDR_SIZE);
|
|
struct in6_addr src_ip;
|
|
|
|
switch (icmp->icmp6_type) {
|
|
case IPV6_ICMP_ECHO_REPLY:
|
|
src_ip = ip6->saddr;
|
|
if (memcmp(&net_ping_ip6, &src_ip, sizeof(struct in6_addr)))
|
|
return -EINVAL;
|
|
net_set_state(NETLOOP_SUCCESS);
|
|
break;
|
|
case IPV6_ICMP_ECHO_REQUEST:
|
|
/* ignore for now.... */
|
|
debug("Got ICMPv6 ECHO REQUEST from %pI6c\n", &ip6->saddr);
|
|
return -EINVAL;
|
|
default:
|
|
debug("Unexpected ICMPv6 type 0x%x\n", icmp->icmp6_type);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|