[PATCH v2] cmd: net: Add the "arp" command

Joe Xue lgxue at hotmail.com
Sat Apr 10 02:48:36 CEST 2021


Yes or No,

Yes, we can store the MAC from the ARP packet then show it when the "arp" command is called as Linux system. And we need lots of change to achieve this.
No, because U-boot net system runs in passive mode, it doesn't receive any network packet without sending the packet.

For the "yes" above, we can turn on the network and monitor all ARP request packet then show thoseIP/MAC pairs but we cannot show the specific host pair. it needs t work
with "ping" command to do so.

Overall, we choose the way that the arp command sends the request to a specific IP and extracts the MAC of it.

It is still useful compared to the Linux command in several cases which I met:
1 the host is not pingable (host firewall or other reason)
2 two hosts have been configured the same IP by mistake (I used a long time to figure out why I can ping bug cannot use TFTP).
3 when debugging network driver.

Thanks

Joe Xue

________________________________
From: Heinrich Schuchardt <xypron.glpk at gmx.de>
Sent: April 9, 2021 8:18 PM
To: lgxue at hotmail.com <lgxue at hotmail.com>; u-boot at lists.denx.de <u-boot at lists.denx.de>
Cc: bmeng.cn at gmail.com <bmeng.cn at gmail.com>; frederic.danis at collabora.com <frederic.danis at collabora.com>; joe.hershberger at ni.com <joe.hershberger at ni.com>; Olaf.Krebs at emh-metering.com <Olaf.Krebs at emh-metering.com>; patrick.delaunay at foss.st.com <patrick.delaunay at foss.st.com>; peng.fan at nxp.com <peng.fan at nxp.com>; philippe.reynes at softathome.com <philippe.reynes at softathome.com>; rfried.dev at gmail.com <rfried.dev at gmail.com>; sjg at chromium.org <sjg at chromium.org>
Subject: Re: [PATCH v2] cmd: net: Add the "arp" command

On 4/9/21 11:46 PM, lgxue at hotmail.com wrote:
> From: Joe Xue <lgxue at hotmail.com>
>
> The command is to query and show mac address of a specific ipAddress.
>
> Signed-off-by: Joe Xue <lgxue at hotmail.com>
> ---
>
>   cmd/Kconfig       |  6 ++++++
>   cmd/net.c         | 36 ++++++++++++++++++++++++++++++++++++
>   doc/usage/arp.rst | 31 +++++++++++++++++++++++++++++++
>   include/net.h     |  5 +++++
>   net/arp.c         | 24 ++++++++++++++++++++++++
>   net/arp.h         |  4 ++++
>   net/net.c         |  8 ++++++++
>   7 files changed, 114 insertions(+)
>   create mode 100644 doc/usage/arp.rst
>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 9bf5e863e4..1da4cb67f6 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -1587,6 +1587,12 @@ config CMD_PING
>        help
>          Send ICMP ECHO_REQUEST to network host
>
> +config CMD_ARP
> +     bool "arp"
> +     help
> +       Sends ARP_REQUEST to network host and shows the result if there is arp
> +       response.
> +
>   config CMD_CDP
>        bool "cdp"
>        help
> diff --git a/cmd/net.c b/cmd/net.c
> index beb2877dfd..369d15474c 100644
> --- a/cmd/net.c
> +++ b/cmd/net.c
> @@ -479,4 +479,40 @@ U_BOOT_CMD(
>        ""
>   );
>

Have a look at the #ifdef above in the code. I assume that the
dependency on CONFIG_CMD_LINK_LOCAL was not your intention.

> +#ifdef CONFIG_CMD_ARP
> +static int do_arp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
> +{
> +     u8 *ethaddr = arp_query_ethaddr;
> +
> +     if (argc < 2)
> +             return CMD_RET_USAGE;
> +
> +     arp_query_ip = string_to_ip(argv[1]);
> +     if (arp_query_ip.s_addr == 0)
> +             return CMD_RET_USAGE;
> +
> +     if ((arp_query_ip.s_addr & net_netmask.s_addr) !=
> +         (net_ip.s_addr & net_netmask.s_addr)) {
> +             printf("The host %s is not in the same network\n", argv[1]);
> +             return CMD_RET_SUCCESS;
> +     }
> +
> +     if (net_loop(ARP) < 0) {
> +             printf("arp failed; host %s is not alive\n", argv[1]);
> +             return CMD_RET_FAILURE;
> +     }
> +
> +     printf("%s\t%02x:%02x:%02x:%02x:%02x:%02x\n", argv[1], ethaddr[0],
> +            ethaddr[1], ethaddr[2], ethaddr[3], ethaddr[4], ethaddr[5]);
> +
> +     return CMD_RET_SUCCESS;
> +}
> +
> +U_BOOT_CMD(
> +     arp,    2,      1,      do_arp,
> +     "send ARP ARP_REQUEST to network host",
> +     "ipAddress"
> +);
> +#endif
> +
>   #endif  /* CONFIG_CMD_LINK_LOCAL */
> diff --git a/doc/usage/arp.rst b/doc/usage/arp.rst
> new file mode 100644
> index 0000000000..b1f08a2ae9
> --- /dev/null
> +++ b/doc/usage/arp.rst
> @@ -0,0 +1,31 @@
> +arp command
> +===========
> +
> +Synopis
> +-------
> +
> +::
> +
> +    arp ipAddress
> +
> +Description
> +-----------
> +
> +The arp command is used to send ARP_REQUEST to network host and show the result.
> +
> +ipAddress
> +    the host ip address

%s/ip/IP/

Why should the IP address be a required parameter? The most interesting
use case for the arp command is discovering neighbors.

On Linux 'arp -n' gives me the list of *all* devices in the same network
segment with both MAC address and IP address.

Can we do the same in U-Boot?

Best regards

Heinrich

> +
> +Example
> +-------
> +
> +::
> +
> +    => arp 192.168.0.1
> +    Using host_ens33 device
> +    192.168.0.1 84:94:8c:5f:e1:62
> +
> +Return value
> +------------
> +
> +The return value $? is 0 if the comand running was successful else 1
> diff --git a/include/net.h b/include/net.h
> index b95d6a6f60..60b4bf610e 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -580,6 +580,11 @@ extern char *net_dns_env_var;            /* the env var to put the ip into */
>   extern struct in_addr net_ping_ip;  /* the ip address to ping */
>   #endif
>
> +#if defined(CONFIG_CMD_ARP)
> +extern u8 arp_query_ethaddr[6];              /* the arp query result */
> +extern struct in_addr arp_query_ip; /* the ip address to arp query */
> +#endif
> +
>   #if defined(CONFIG_CMD_CDP)
>   /* when CDP completes these hold the return values */
>   extern ushort cdp_native_vlan;              /* CDP returned native VLAN */
> diff --git a/net/arp.c b/net/arp.c
> index 1d06ed2572..83c24072d7 100644
> --- a/net/arp.c
> +++ b/net/arp.c
> @@ -220,11 +220,20 @@ void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len)
>                        net_get_arp_handler()((uchar *)arp, 0, reply_ip_addr,
>                                              0, len);
>
> +#ifdef CONFIG_CMD_ARP
> +                     if (arp_query_ip.s_addr != 0) {
> +                             arp_query_ip.s_addr = 0;
> +                             net_set_state(NETLOOP_SUCCESS);
> +                     } else {
> +#endif
>                        /* set the mac address in the waiting packet's header
>                           and transmit it */
>                        memcpy(((struct ethernet_hdr *)net_tx_packet)->et_dest,
>                               &arp->ar_sha, ARP_HLEN);
>                        net_send_packet(net_tx_packet, arp_wait_tx_packet_size);
> +#ifdef CONFIG_CMD_ARP
> +                     }
> +#endif
>
>                        /* no arp request pending now */
>                        net_arp_wait_packet_ip.s_addr = 0;
> @@ -243,3 +252,18 @@ bool arp_is_waiting(void)
>   {
>        return !!net_arp_wait_packet_ip.s_addr;
>   }
> +
> +#ifdef CONFIG_CMD_ARP
> +u8 arp_query_ethaddr[6];
> +struct in_addr arp_query_ip;
> +
> +void arp_query(void)
> +{
> +     arp_wait_packet_ethaddr = arp_query_ethaddr;
> +     net_arp_wait_packet_ip = arp_query_ip;
> +
> +     arp_wait_timer_start = get_timer(0);
> +     printf("Using %s device\n", eth_get_name());
> +     arp_request();
> +}
> +#endif
> diff --git a/net/arp.h b/net/arp.h
> index 25b3c00d5c..f3e5cb8504 100644
> --- a/net/arp.h
> +++ b/net/arp.h
> @@ -29,4 +29,8 @@ void arp_raw_request(struct in_addr source_ip, const uchar *targetEther,
>   int arp_timeout_check(void);
>   void arp_receive(struct ethernet_hdr *et, struct ip_udp_hdr *ip, int len);
>
> +#ifdef CONFIG_CMD_ARP
> +void arp_query(void);
> +#endif
> +
>   #endif /* __ARP_H__ */
> diff --git a/net/net.c b/net/net.c
> index b58f3062b2..21623562e8 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -492,6 +492,11 @@ restart:
>                        rarp_request();
>                        break;
>   #endif
> +#if defined(CONFIG_CMD_ARP)
> +             case ARP:
> +                     arp_query();
> +                     break;
> +#endif
>   #if defined(CONFIG_CMD_PING)
>                case PING:
>                        ping_start();
> @@ -1385,6 +1390,9 @@ common:
>        case CDP:
>        case DHCP:
>        case LINKLOCAL:
> +#ifdef CONFIG_CMD_ARP
> +     case ARP:
> +#endif
>                if (memcmp(net_ethaddr, "\0\0\0\0\0\0", 6) == 0) {
>                        int num = eth_get_dev_index();
>
>



More information about the U-Boot mailing list