@ -14,22 +14,128 @@
DECLARE_GLOBAL_DATA_PTR ;
/**
* struct eth_sandbox_priv - memory for sandbox mock driver
*
* fake_host_hwaddr : MAC address of mocked machine
* fake_host_ipaddr : IP address of mocked machine
* recv_packet_buffer : buffer of the packet returned as received
* recv_packet_length : length of the packet returned as received
*/
struct eth_sandbox_priv {
uchar fake_host_hwaddr [ ARP_HLEN ] ;
IPaddr_t fake_host_ipaddr ;
uchar * recv_packet_buffer ;
int recv_packet_length ;
} ;
static int sb_eth_start ( struct udevice * dev )
{
struct eth_sandbox_priv * priv = dev_get_priv ( dev ) ;
debug ( " eth_sandbox: Start \n " ) ;
fdtdec_get_byte_array ( gd - > fdt_blob , dev - > of_offset , " fake-host-hwaddr " ,
priv - > fake_host_hwaddr , ARP_HLEN ) ;
priv - > recv_packet_buffer = net_rx_packets [ 0 ] ;
return 0 ;
}
static int sb_eth_send ( struct udevice * dev , void * packet , int length )
{
struct eth_sandbox_priv * priv = dev_get_priv ( dev ) ;
struct ethernet_hdr * eth = packet ;
debug ( " eth_sandbox: Send packet %d \n " , length ) ;
if ( ntohs ( eth - > et_protlen ) = = PROT_ARP ) {
struct arp_hdr * arp = packet + ETHER_HDR_SIZE ;
if ( ntohs ( arp - > ar_op ) = = ARPOP_REQUEST ) {
struct ethernet_hdr * eth_recv ;
struct arp_hdr * arp_recv ;
/* store this as the assumed IP of the fake host */
priv - > fake_host_ipaddr = NetReadIP ( & arp - > ar_tpa ) ;
/* Formulate a fake response */
eth_recv = ( void * ) priv - > recv_packet_buffer ;
memcpy ( eth_recv - > et_dest , eth - > et_src , ARP_HLEN ) ;
memcpy ( eth_recv - > et_src , priv - > fake_host_hwaddr ,
ARP_HLEN ) ;
eth_recv - > et_protlen = htons ( PROT_ARP ) ;
arp_recv = ( void * ) priv - > recv_packet_buffer +
ETHER_HDR_SIZE ;
arp_recv - > ar_hrd = htons ( ARP_ETHER ) ;
arp_recv - > ar_pro = htons ( PROT_IP ) ;
arp_recv - > ar_hln = ARP_HLEN ;
arp_recv - > ar_pln = ARP_PLEN ;
arp_recv - > ar_op = htons ( ARPOP_REPLY ) ;
memcpy ( & arp_recv - > ar_sha , priv - > fake_host_hwaddr ,
ARP_HLEN ) ;
NetWriteIP ( & arp_recv - > ar_spa , priv - > fake_host_ipaddr ) ;
memcpy ( & arp_recv - > ar_tha , & arp - > ar_sha , ARP_HLEN ) ;
NetCopyIP ( & arp_recv - > ar_tpa , & arp - > ar_spa ) ;
priv - > recv_packet_length = ETHER_HDR_SIZE +
ARP_HDR_SIZE ;
}
} else if ( ntohs ( eth - > et_protlen ) = = PROT_IP ) {
struct ip_udp_hdr * ip = packet + ETHER_HDR_SIZE ;
if ( ip - > ip_p = = IPPROTO_ICMP ) {
struct icmp_hdr * icmp = ( struct icmp_hdr * ) & ip - > udp_src ;
if ( icmp - > type = = ICMP_ECHO_REQUEST ) {
struct ethernet_hdr * eth_recv ;
struct ip_udp_hdr * ipr ;
struct icmp_hdr * icmpr ;
/* reply to the ping */
memcpy ( priv - > recv_packet_buffer , packet ,
length ) ;
eth_recv = ( void * ) priv - > recv_packet_buffer ;
ipr = ( void * ) priv - > recv_packet_buffer +
ETHER_HDR_SIZE ;
icmpr = ( struct icmp_hdr * ) & ipr - > udp_src ;
memcpy ( eth_recv - > et_dest , eth - > et_src ,
ARP_HLEN ) ;
memcpy ( eth_recv - > et_src , priv - > fake_host_hwaddr ,
ARP_HLEN ) ;
ipr - > ip_sum = 0 ;
ipr - > ip_off = 0 ;
NetCopyIP ( ( void * ) & ipr - > ip_dst , & ip - > ip_src ) ;
NetWriteIP ( ( void * ) & ipr - > ip_src ,
priv - > fake_host_ipaddr ) ;
ipr - > ip_sum = compute_ip_checksum ( ipr ,
IP_HDR_SIZE ) ;
icmpr - > type = ICMP_ECHO_REPLY ;
icmpr - > checksum = 0 ;
icmpr - > checksum = compute_ip_checksum ( icmpr ,
ICMP_HDR_SIZE ) ;
priv - > recv_packet_length = length ;
}
}
}
return 0 ;
}
static int sb_eth_recv ( struct udevice * dev , uchar * * packetp )
{
struct eth_sandbox_priv * priv = dev_get_priv ( dev ) ;
if ( priv - > recv_packet_length ) {
int lcl_recv_packet_length = priv - > recv_packet_length ;
debug ( " eth_sandbox: received packet %d \n " ,
priv - > recv_packet_length ) ;
priv - > recv_packet_length = 0 ;
* packetp = priv - > recv_packet_buffer ;
return lcl_recv_packet_length ;
}
return 0 ;
}
@ -80,5 +186,6 @@ U_BOOT_DRIVER(eth_sandbox) = {
. ofdata_to_platdata = sb_eth_ofdata_to_platdata ,
. remove = sb_eth_remove ,
. ops = & sb_eth_ops ,
. priv_auto_alloc_size = sizeof ( struct eth_sandbox_priv ) ,
. platdata_auto_alloc_size = sizeof ( struct eth_pdata ) ,
} ;