Re: [PATCH v2] Enhance "net" command to display IPv6 address of network interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2023/02/27 23:49, Lianbo Jiang wrote:
> Currently, the "net" command displays only the IPv4 address of a network
> interface, it doesn't support outputting IPv6 address yet. For example:

Thanks!  This has been on my to-do list for a long time.. :-)

> 
> Without the patch:
>    crash> net
>       NET_DEVICE     NAME   IP ADDRESS(ES)
>    ffff8d01b1205000  lo     127.0.0.1
>    ffff8d0087e40000  eno1   192.168.122.2
> 
> With the patch:
>    crash> net
>       NET_DEVICE     NAME   IP ADDRESS(ES)   INET6 ADDRESS
>    ffff8d01b1205000  lo     127.0.0.1 ::1
>    ffff8d0087e40000  eno1   192.168.122.2 xxxx:xx:x:xxxx:xxxx:xxx:xxxx:xxxx, yyyy::yyyy:yyy:yyyy:yyyy

The indent looks odd, and I think that adding the new column
"INET6 ADDRESS" may not be so useful because secondary addresses
are often seen in the field as the header says "IP ADDRESS(ES)".
For example, on one of my machines:

crash> net
    NET_DEVICE     NAME   IP ADDRESS(ES)   INET6 ADDRESS
ffff9752fc7b1000  lo     127.0.0.1 ::1
ffff9752e4b94000  enp1s0f0
ffff9752e739c000  enp1s0f1
ffff975242ba6000  virbr0 192.168.122.1
ffff9752c7ff4000  virbr0-nic
ffff975261be4000  vnet0                 fe80::fc54:ff:fe1d:5abe
ffff9751031c0000  vnet1                 fe80::fc54:ff:fe06:735d
ffff9752d87d5000  bond0  192.168.0.171, 192.168.0.172, 192.168.0.173 fe80::xxxx:xxxx:xxxx:xxxx
ffff973bac3ab000  bond0.100 192.168.100.171, 192.168.100.172, 192.168.100.173

IPv6 addresses can be distinguished from IPv4 ones with itself, so
how about just adding them to IPv4 ones? without the new column:

crash> net
    NET_DEVICE     NAME        IP ADDRESS(ES)
ffff9752fc7b1000  lo          127.0.0.1, ::1
ffff9752e4b94000  enp1s0f0
ffff9752e739c000  enp1s0f1
ffff975242ba6000  virbr0      192.168.122.1
ffff9752c7ff4000  virbr0-nic
ffff975261be4000  vnet0       fe80::fc54:ff:fe1d:5abe
ffff9751031c0000  vnet1       fe80::fc54:ff:fe06:735d
ffff9752d87d5000  bond0       192.168.0.171, 192.168.0.172, 192.168.0.173, fe80::xxxx:xxxx:xxxx:xxxx
ffff973bac3ab000  bond0.100   192.168.100.171, 192.168.100.172, 192.168.100.173

And these days, device names tend to be longer than before, so
I would like to extend it to "%-10s " or so at this opportunity
like the above.

> 
> Related kernel commit:
> 502a2ffd7376 ("ipv6: convert idev_list to list macros")
> 
> Reported-by: Buland Kumar Singh <bsingh@xxxxxxxxxx>
> Signed-off-by: Lianbo Jiang <lijiang@xxxxxxxxxx>
> ---
>   defs.h    |   6 +++
>   net.c     | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++---
>   symbols.c |  12 ++++++
>   3 files changed, 135 insertions(+), 6 deletions(-)
> 
> diff --git a/defs.h b/defs.h
> index e76af3c78b69..1f2cf6e0ce01 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2208,6 +2208,12 @@ struct offset_table {                    /* stash of commonly-used offsets */
>   	long sock_common_skc_v6_daddr;
>   	long sock_common_skc_v6_rcv_saddr;
>   	long inactive_task_frame_bp;
> +	long net_device_ip6_ptr;
> +	long inet6_dev_addr_list;
> +	long inet6_ifaddr_addr;
> +	long inet6_ifaddr_if_list;
> +	long inet6_ifaddr_if_next;
> +	long in6_addr_in6_u;
>   };
>   
>   struct size_table {         /* stash of commonly-used sizes */
> diff --git a/net.c b/net.c
> index aa445ab7ee13..52336762c85c 100644
> --- a/net.c
> +++ b/net.c
> @@ -41,6 +41,7 @@ struct net_table {
>   	long in_ifaddr_ifa_next;
>   	long in_ifaddr_ifa_address;
>   	int net_device_name_index;

> +	long dev_ip6_ptr;

This looks unnecessary, because this is set only to
OFFSET(net_device_ip6_ptr).

>   } net_table = { 0 };
>   
>   struct net_table *net = &net_table;
> @@ -71,6 +72,7 @@ static void print_neighbour_q(ulong, int);
>   static void get_netdev_info(ulong, struct devinfo *);
>   static void get_device_name(ulong, char *);
>   static long get_device_address(ulong, char **, long);
> +static void get_device_ip6_address(ulong, char **, long);
>   static void get_sock_info(ulong, char *);
>   static void dump_arp(void);
>   static void arp_state_to_flags(unsigned char);
> @@ -114,6 +116,13 @@ net_init(void)
>   		net->dev_ip_ptr = MEMBER_OFFSET_INIT(net_device_ip_ptr,
>   			"net_device", "ip_ptr");
>   		MEMBER_OFFSET_INIT(net_device_dev_list, "net_device", "dev_list");
> +		net->dev_ip6_ptr = MEMBER_OFFSET_INIT(net_device_ip6_ptr, "net_device", "ip6_ptr");
> +		MEMBER_OFFSET_INIT(inet6_dev_addr_list, "inet6_dev", "addr_list");
> +		MEMBER_OFFSET_INIT(inet6_ifaddr_addr, "inet6_ifaddr", "addr");
> +		MEMBER_OFFSET_INIT(inet6_ifaddr_if_list, "inet6_ifaddr", "if_list");
> +		MEMBER_OFFSET_INIT(inet6_ifaddr_if_next, "inet6_ifaddr", "if_next");
> +		MEMBER_OFFSET_INIT(in6_addr_in6_u, "in6_addr", "in6_u");
> +
>   		MEMBER_OFFSET_INIT(net_dev_base_head, "net", "dev_base_head");
>   		ARRAY_LENGTH_INIT(net->net_device_name_index,
>   			net_device_name, "net_device.name", NULL, sizeof(char));
> @@ -466,7 +475,7 @@ show_net_devices(ulong task)
>   	buf = GETBUF(buflen);
>   	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
>   
> -	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
> +	fprintf(fp, "%s  NAME   IP ADDRESS(ES)   INET6 ADDRESS\n",
>   		mkstring(upper_case(net->netdevice, buf),
>   			flen, CENTER|LJUST, NULL));
>   

Just memo:
   v2.6.24 introduced init_net      --> show_net_devices_v3()
   v2.6.22 introduced dev_base_head --> show_net_devices_v2()
   earlier used dev_base            --> show_net_devices()

The patch works even on v2.6.16 vmcore :-)

crash> net
    NET_DEVICE     NAME   IP ADDRESS(ES)   INET6 ADDRESS
ffffffff803c1480  lo     127.0.0.1 ::1
ffff81003eb73000  eth0   xx.xx.xxx.xx fe80::xxx:xxxx:xxxx:xxxx

> @@ -477,7 +486,14 @@ show_net_devices(ulong task)
>   		get_device_name(next, buf);
>   		fprintf(fp, "%-6s ", buf);
>   
> -		buflen = get_device_address(next, &buf, buflen);
> +		get_device_address(next, &buf, buflen);
> +
> +		if (strlen(buf) > 0)
> +			fprintf(fp, "%-6s ", buf);
> +		else
> +			fprintf(fp, "\t\t");

(It would be better to avoid using '\t' in output usually for indent
because it can vary with the terminal or something, I think.)

> +
> +		get_device_ip6_address(next, &buf, buflen);
>   		fprintf(fp, "%s\n", buf);
>   
>           	readmem(next+net->dev_next, KVADDR, &next,
> @@ -503,7 +519,7 @@ show_net_devices_v2(ulong task)
>   	buf = GETBUF(buflen);
>   	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
>   
> -	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
> +	fprintf(fp, "%s  NAME   IP ADDRESS(ES)   INET6 ADDRESS\n",
>   		mkstring(upper_case(net->netdevice, buf),
>   			flen, CENTER|LJUST, NULL));
>   
> @@ -530,7 +546,14 @@ show_net_devices_v2(ulong task)
>   		get_device_name(ld->list_ptr[i], buf);
>   		fprintf(fp, "%-6s ", buf);
>   
> -		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
> +		get_device_address(ld->list_ptr[i], &buf, buflen);
> +
> +		if (strlen(buf) > 0)
> +			fprintf(fp, "%-6s ", buf);
> +		else
> +			fprintf(fp, "\t\t");
> +
> +		get_device_ip6_address(ld->list_ptr[i], &buf, buflen);
>   		fprintf(fp, "%s\n", buf);
>   	}
>   	
> @@ -556,7 +579,7 @@ show_net_devices_v3(ulong task)
>   	buf = GETBUF(buflen);
>   	flen = MAX(VADDR_PRLEN, strlen(net->netdevice));
>   
> -	fprintf(fp, "%s  NAME   IP ADDRESS(ES)\n",
> +	fprintf(fp, "%s  NAME   IP ADDRESS(ES)   INET6 ADDRESS\n",
>   		mkstring(upper_case(net->netdevice, buf),
>   			flen, CENTER|LJUST, NULL));
>   
> @@ -593,7 +616,14 @@ show_net_devices_v3(ulong task)
>   		get_device_name(ld->list_ptr[i], buf);
>   		fprintf(fp, "%-6s ", buf);
>   
> -		buflen = get_device_address(ld->list_ptr[i], &buf, buflen);
> +		get_device_address(ld->list_ptr[i], &buf, buflen);
> +
> +		if (strlen(buf) > 0)
> +			fprintf(fp, "%-6s ", buf);
> +		else
> +			fprintf(fp, "\t\t");
> +
> +		get_device_ip6_address(ld->list_ptr[i], &buf, buflen);
>   		fprintf(fp, "%s\n", buf);
>   	}
>   	
> @@ -925,6 +955,87 @@ get_device_address(ulong devaddr, char **bufp, long buflen)
>   	return buflen;
>   }
>   
> +static void
> +get_device_ip6_address(ulong devaddr, char **bufp, long buflen)
> +{
> +	ulong ip6_ptr = 0, i, cnt = 0, pos = 0, bufsize = buflen;
> +	struct list_data list_data, *ld;
> +	struct in6_addr ip6_addr;
> +	char *buf;
> +	char str[INET6_ADDRSTRLEN + 1] = {0};
> +	char buffer[INET6_ADDRSTRLEN + 4] = {0};
> +	uint len = 0;
> +
> +	buf = *bufp;
> +	BZERO(buf, buflen);
> +
> +	readmem(devaddr + net->dev_ip6_ptr, KVADDR,
> +		&ip6_ptr, sizeof(ulong), "ip6_ptr", FAULT_ON_ERROR);
> +
> +	if (!ip6_ptr)
> +		return;
> +
> +	if (MEMBER_TYPE("inet6_dev", "addr_list") == TYPE_CODE_PTR) {

This can be replaced with VALID_MEMBER(inet6_ifaddr_if_next)?
It will be faster than MEMBER_TYPE().

> +		ulong addrp = 0;
> +		/*
> +		 * 502a2ffd7376 ("ipv6: convert idev_list to list macros")
> +		 * v2.6.35-rc1~473^2~733
> +		 */
> +		readmem(ip6_ptr + OFFSET(inet6_dev_addr_list), KVADDR,
> +			&addrp, sizeof(void *), "addr_list", FAULT_ON_ERROR);

"inet6_dev.addr_list" is better.

> +
> +		while (addrp) {
> +			readmem(addrp + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr,
> +				sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR);
> +			inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN);
> +			sprintf(buffer, "%s%s", pos ? ", " : "", str);
> +			len = strlen(buffer);
> +
> +			if (pos + len >= bufsize) {
> +				RESIZEBUF(*bufp, bufsize, bufsize + buflen);
> +				buf = *bufp;
> +				BZERO(buf + bufsize, buflen);
> +				bufsize += buflen;
> +			}
> +			BCOPY(buffer, &buf[pos], len);
> +			pos += len;
> +			readmem(addrp + OFFSET(inet6_ifaddr_if_next), KVADDR, &addrp,
> +				sizeof(void *), "inet6_ifaddr.if_next", FAULT_ON_ERROR);
> +		}
> +
> +		return;
> +	}
> +
> +	ld =  &list_data;
> +	BZERO(ld, sizeof(struct list_data));
> +	ld->flags |= LIST_ALLOCATE;
> +	ld->start = ip6_ptr + OFFSET(inet6_dev_addr_list);
> +	cnt = do_list(ld);
> +
> +	for (i = 1; i < cnt; i++) {
> +		ulong addr;
> +
> +		addr = ld->list_ptr[i] + OFFSET(inet6_ifaddr_addr);
> +		addr -= OFFSET(inet6_ifaddr_if_list);
> +		readmem(addr + OFFSET(in6_addr_in6_u), KVADDR, &ip6_addr,
> +			sizeof(struct in6_addr), "in6_addr.in6_u", FAULT_ON_ERROR);
> +
> +		inet_ntop(AF_INET6, (void*)&ip6_addr, str, INET6_ADDRSTRLEN);
> +		sprintf(buffer, "%s%s", pos ? ", " : "", str);
> +		len = strlen(buffer);
> +
> +		if (pos + len >= bufsize) {
> +			RESIZEBUF(*bufp, bufsize, bufsize + buflen);
> +			buf = *bufp;
> +			BZERO(buf + bufsize, buflen);
> +			bufsize += buflen;
> +		}
> +		BCOPY(buffer, &buf[pos], len);
> +		pos += len;
> +	}
> +
> +	FREEBUF(ld->list_ptr);
> +}
>   /*
>    *  Get the family, type, local and destination address/port pairs.
>    */
> diff --git a/symbols.c b/symbols.c
> index a974fc9141a0..c8bdeb841cdc 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -9787,6 +9787,18 @@ dump_offset_table(char *spec, ulong makestruct)
>           	OFFSET(net_device_addr_len));
>   	fprintf(fp, "             net_device_ip_ptr: %ld\n",
>           	OFFSET(net_device_ip_ptr));
> +	fprintf(fp, "            net_device_ip6_ptr: %ld\n",
> +		OFFSET(net_device_ip6_ptr));
> +	fprintf(fp, "           inet6_dev_addr_list: %ld\n",
> +		OFFSET(inet6_dev_addr_list));
> +	fprintf(fp, "             inet6_ifaddr_addr: %ld\n",
> +		OFFSET(inet6_ifaddr_addr));
> +	fprintf(fp, "          inet6_ifaddr_if_list: %ld\n",
> +		OFFSET(inet6_ifaddr_if_list));
> +	fprintf(fp, "          inet6_ifaddr_if_next: %ld\n",
> +		OFFSET(inet6_ifaddr_if_next));
> +	fprintf(fp, "                in6_addr_in6_u: %ld\n",
> +		OFFSET(in6_addr_in6_u));
>   	fprintf(fp, "           net_device_dev_list: %ld\n",
>   		OFFSET(net_device_dev_list));
>   	fprintf(fp, "             net_dev_base_head: %ld\n",

Please change each of these to one line for readability, and..

crash> help -o
...
            net_device_addr_len: 493
              net_device_ip_ptr: 616
             net_device_ip6_ptr: 632
            inet6_dev_addr_list: 8
              inet6_ifaddr_addr: 0
           inet6_ifaddr_if_list: 232
           inet6_ifaddr_if_next: -1
                 in6_addr_in6_u: 0
            net_device_dev_list: 80

please don't separate the same "net_device" struct members..
How about this? putting ipv6 related ones together.

            net_device_addr_len: 493
              net_device_ip_ptr: 616
+           net_device_ip6_ptr: 632
            net_device_dev_list: 80
...
                 inet_opt_sport: 784
                   inet_opt_num: 14
+          inet6_dev_addr_list: 8
+            inet6_ifaddr_addr: 0
+         inet6_ifaddr_if_list: 232
+         inet6_ifaddr_if_next: -1
+               in6_addr_in6_u: 0
           ipv6_pinfo_rcv_saddr: -1
               ipv6_pinfo_daddr: -1

Thanks,
Kazu
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/crash-utility
Contribution Guidelines: https://github.com/crash-utility/crash/wiki




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux