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

From: Joe Xue lgxue@hotmail.com
The command is to query and show mac address of a specific ipAddress.
Signed-off-by: Joe Xue lgxue@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( "" );
+#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 + +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();

On 4/9/21 11:46 PM, lgxue@hotmail.com wrote:
From: Joe Xue lgxue@hotmail.com
The command is to query and show mac address of a specific ipAddress.
Signed-off-by: Joe Xue lgxue@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();

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@gmx.de Sent: April 9, 2021 8:18 PM To: lgxue@hotmail.com lgxue@hotmail.com; u-boot@lists.denx.de u-boot@lists.denx.de Cc: bmeng.cn@gmail.com bmeng.cn@gmail.com; frederic.danis@collabora.com frederic.danis@collabora.com; joe.hershberger@ni.com joe.hershberger@ni.com; Olaf.Krebs@emh-metering.com Olaf.Krebs@emh-metering.com; patrick.delaunay@foss.st.com patrick.delaunay@foss.st.com; peng.fan@nxp.com peng.fan@nxp.com; philippe.reynes@softathome.com philippe.reynes@softathome.com; rfried.dev@gmail.com rfried.dev@gmail.com; sjg@chromium.org sjg@chromium.org Subject: Re: [PATCH v2] cmd: net: Add the "arp" command
On 4/9/21 11:46 PM, lgxue@hotmail.com wrote:
From: Joe Xue lgxue@hotmail.com
The command is to query and show mac address of a specific ipAddress.
Signed-off-by: Joe Xue lgxue@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();
participants (3)
-
Heinrich Schuchardt
-
Joe Xue
-
lgxue@hotmail.com