Hi Lianbo, thank you for the update. For a few details.. On 2023/03/03 16:23, 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: > > 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) > 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 > > 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 | 109 +++++++++++++++++++++++++++++++++++++++++++++++++----- > symbols.c | 6 +++ > 3 files changed, 112 insertions(+), 9 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..6bca2a5d0098 100644 > --- a/net.c > +++ b/net.c > @@ -71,6 +71,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 +115,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"); > + 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 +474,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)\n", > mkstring(upper_case(net->netdevice, buf), > flen, CENTER|LJUST, NULL)); > > @@ -475,9 +483,10 @@ show_net_devices(ulong task) > mkstring(buf, flen, CENTER|RJUST|LONG_HEX, MKSTR(next))); > > get_device_name(next, buf); > - fprintf(fp, "%-6s ", buf); > + fprintf(fp, "%-10s ", buf); > > - buflen = get_device_address(next, &buf, buflen); > + get_device_address(next, &buf, buflen); > + get_device_ip6_address(next, &buf, buflen); > fprintf(fp, "%s\n", buf); > > readmem(next+net->dev_next, KVADDR, &next, > @@ -503,7 +512,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)\n", > mkstring(upper_case(net->netdevice, buf), > flen, CENTER|LJUST, NULL)); > > @@ -528,9 +537,10 @@ show_net_devices_v2(ulong task) > MKSTR(ld->list_ptr[i]))); > > get_device_name(ld->list_ptr[i], buf); > - fprintf(fp, "%-6s ", buf); > + fprintf(fp, "%-10s ", buf); > > - buflen = get_device_address(ld->list_ptr[i], &buf, buflen); > + get_device_address(ld->list_ptr[i], &buf, buflen); > + get_device_ip6_address(ld->list_ptr[i], &buf, buflen); > fprintf(fp, "%s\n", buf); > } > > @@ -556,7 +566,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)\n", > mkstring(upper_case(net->netdevice, buf), > flen, CENTER|LJUST, NULL)); > > @@ -591,9 +601,10 @@ show_net_devices_v3(ulong task) > MKSTR(ld->list_ptr[i]))); > > get_device_name(ld->list_ptr[i], buf); > - fprintf(fp, "%-6s ", buf); > + fprintf(fp, "%-10s ", buf); > > - buflen = get_device_address(ld->list_ptr[i], &buf, buflen); > + get_device_address(ld->list_ptr[i], &buf, buflen); > + get_device_ip6_address(ld->list_ptr[i], &buf, buflen); > fprintf(fp, "%s\n", buf); > } > > @@ -925,6 +936,86 @@ 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, pos = 0, bufsize = buflen, addr = 0; > + struct in6_addr ip6_addr; > + char *buf; > + char str[INET6_ADDRSTRLEN + 1] = {0}; > + char buffer[INET6_ADDRSTRLEN + 4] = {0}; What are the +1 and +4 for? Looking at the example in the man page of inet_pton(3), INET6_ADDRSTRLEN seems enough for the str and contains a null char. The buffer can have a comma and a space (", ") so +2 is enough? i.e. char str[INET6_ADDRSTRLEN] = {0}; char buffer[INET6_ADDRSTRLEN + 2] = {0}; > + uint len = 0; > + > + buf = *bufp; > + pos = strlen(buf); Ah nicely done :) > + > + readmem(devaddr + OFFSET(net_device_ip6_ptr), KVADDR, > + &ip6_ptr, sizeof(ulong), "ip6_ptr", FAULT_ON_ERROR); > + > + if (!ip6_ptr) > + return; > + > + if (VALID_MEMBER(inet6_ifaddr_if_list)) { > + struct list_data list_data, *ld; > + ulong cnt = 0, i; > + > + 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++) { > + > + addr = ld->list_ptr[i] + OFFSET(inet6_ifaddr_addr); > + addr -= OFFSET(inet6_ifaddr_if_list); This line can be removed with ld->list_head_offset parameter? i.e. ld->start = ip6_ptr + OFFSET(inet6_dev_addr_list); + ld->list_head_offset = OFFSET(inet6_ifaddr_if_list); cnt = do_list(ld); > + 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); > + return; > + } > + > + /* > + * 502a2ffd7376 ("ipv6: convert idev_list to list macros") > + * v2.6.35-rc1~473^2~733 > + */ This should be moved before the if block above? > + readmem(ip6_ptr + OFFSET(inet6_dev_addr_list), KVADDR, > + &addr, sizeof(void *), "inet6_dev.addr_list", FAULT_ON_ERROR); > + > + while (addr) { > + 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; > + readmem(addr + OFFSET(inet6_ifaddr_if_next), KVADDR, &addr, > + sizeof(void *), "inet6_ifaddr.if_next", FAULT_ON_ERROR); > + } > +} > + > /* > * Get the family, type, local and destination address/port pairs. > */ > diff --git a/symbols.c b/symbols.c > index a974fc9141a0..3efcdddfcadb 100644 > --- a/symbols.c > +++ b/symbols.c > @@ -9787,6 +9787,7 @@ 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, " net_device_dev_list: %ld\n", > OFFSET(net_device_dev_list)); > fprintf(fp, " net_dev_base_head: %ld\n", > @@ -9839,6 +9840,11 @@ dump_offset_table(char *spec, ulong makestruct) > fprintf(fp, " inet_opt_num: %ld\n", > OFFSET(inet_opt_num)); > > + 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, " ipv6_pinfo_rcv_saddr: %ld\n", > OFFSET(ipv6_pinfo_rcv_saddr)); > fprintf(fp, " ipv6_pinfo_daddr: %ld\n", Thanks, good! 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