Add "show socket" command written by Hiroki SUENAGA. It prints usage of

system's socket buffers.
This commit is contained in:
msaitoh 2018-07-20 08:26:25 +00:00
parent 1b8eee7796
commit 502cc4207c
4 changed files with 239 additions and 7 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: ddb.4,v 1.179 2018/07/17 05:52:07 msaitoh Exp $
.\" $NetBSD: ddb.4,v 1.180 2018/07/20 08:26:25 msaitoh Exp $
.\"
.\" Copyright (c) 1997 - 2009 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -56,7 +56,7 @@
.\" any improvements or extensions that they make and grant Carnegie Mellon
.\" the rights to redistribute these changes.
.\"
.Dd July 17, 2018
.Dd July 20, 2018
.Dt DDB 4
.Os
.Sh NAME
@ -750,6 +750,25 @@ of LWPs will be shown.
If the run queue has LWPs, but the sched_whichqs bit is not set for that
queue, the queue index will be prefixed with a
.Sq \&! .
.It Ic show socket Ns Oo Cm /ampv Oc
Print usage of system's socket buffers.
By default, empty socket isn't printed.
.Bl -tag -width 4n -compact
.It Cm /a
Print all processes which use the socket.
.It Cm /m
Print mbuf chain in the socket buffer.
.It Cm /p
By default, a process which use the socket is printed (only one socket).
If
.Cm /p
is specified, the process isn't printed.
.It Cm /v
Verbose mode.
If
.Cm /v
is specified, all sockets are printed.
.El
.It Ic show uvmexp
Print a selection of UVM counters and statistics.
.It Ic show kernhist Oo Ar addr Oc

View File

@ -1,4 +1,4 @@
/* $NetBSD: db_command.c,v 1.153 2018/03/19 08:41:21 ozaki-r Exp $ */
/* $NetBSD: db_command.c,v 1.154 2018/07/20 08:26:25 msaitoh Exp $ */
/*
* Copyright (c) 1996, 1997, 1998, 1999, 2002, 2009 The NetBSD Foundation, Inc.
@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.153 2018/03/19 08:41:21 ozaki-r Exp $");
__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.154 2018/07/20 08:26:25 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_aio.h"
@ -89,6 +89,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.153 2018/03/19 08:41:21 ozaki-r Exp
#include <sys/buf.h>
#include <sys/module.h>
#include <sys/kernhist.h>
#include <sys/socketvar.h>
/*include queue macros*/
#include <sys/queue.h>
@ -203,6 +204,7 @@ static void db_show_all_pages(db_expr_t, bool, db_expr_t, const char *);
static void db_pool_print_cmd(db_expr_t, bool, db_expr_t, const char *);
static void db_reboot_cmd(db_expr_t, bool, db_expr_t, const char *);
static void db_sifting_cmd(db_expr_t, bool, db_expr_t, const char *);
static void db_socket_print_cmd(db_expr_t, bool, db_expr_t, const char *);
static void db_stack_trace_cmd(db_expr_t, bool, db_expr_t, const char *);
static void db_sync_cmd(db_expr_t, bool, db_expr_t, const char *);
static void db_whatis_cmd(db_expr_t, bool, db_expr_t, const char *);
@ -257,6 +259,7 @@ static const struct db_command db_show_cmds[] = {
"Print statistics of locks", NULL, NULL) },
{ DDB_ADD_CMD("map", db_map_print_cmd, 0,
"Print the vm_map at address.", "[/f] address",NULL) },
{ DDB_ADD_CMD("socket", db_socket_print_cmd, 0,NULL,NULL,NULL) },
{ DDB_ADD_CMD("module", db_show_module_cmd, 0,
"Print kernel modules", NULL, NULL) },
{ DDB_ADD_CMD("mount", db_mount_print_cmd, 0,
@ -1211,6 +1214,17 @@ db_uvmexp_print_cmd(db_expr_t addr, bool have_addr,
#endif
}
/*ARGSUSED */
static void
db_socket_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
const char *modif)
{
#ifdef _KERNEL /* XXX CRASH(8) */
socket_print(modif, db_printf);
#endif
}
#ifdef KERNHIST
/*ARGSUSED*/
static void

View File

@ -1,4 +1,4 @@
/* $NetBSD: uipc_socket2.c,v 1.130 2018/06/06 09:46:46 roy Exp $ */
/* $NetBSD: uipc_socket2.c,v 1.131 2018/07/20 08:26:25 msaitoh Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -58,9 +58,10 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uipc_socket2.c,v 1.130 2018/06/06 09:46:46 roy Exp $");
__KERNEL_RCSID(0, "$NetBSD: uipc_socket2.c,v 1.131 2018/07/20 08:26:25 msaitoh Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
#include "opt_mbuftrace.h"
#include "opt_sb_max.h"
#endif
@ -81,6 +82,10 @@ __KERNEL_RCSID(0, "$NetBSD: uipc_socket2.c,v 1.130 2018/06/06 09:46:46 roy Exp $
#include <sys/pool.h>
#include <sys/uidinfo.h>
#ifdef DDB
#include <sys/filedesc.h>
#endif
/*
* Primitive routines for operating on sockets and socket buffers.
*
@ -687,6 +692,7 @@ sbreserve(struct sockbuf *sb, u_long cc, struct socket *so)
sb->sb_mbmax = min(cc * 2, sb_max);
if (sb->sb_lowat > sb->sb_hiwat)
sb->sb_lowat = sb->sb_hiwat;
return (1);
}
@ -1541,3 +1547,192 @@ sowait(struct socket *so, bool catch_p, int timo)
solockretry(so, lock);
return error;
}
#ifdef DDB
/*
* Currently, sofindproc() is used only from DDB. It could be used from others
* by using db_mutex_enter()
*/
static inline int
db_mutex_enter(kmutex_t *mtx)
{
extern int db_active;
int rv;
if (!db_active) {
mutex_enter(mtx);
rv = 1;
} else
rv = mutex_tryenter(mtx);
return rv;
}
int
sofindproc(struct socket *so, int all, void (*pr)(const char *, ...))
{
proc_t *p;
filedesc_t *fdp;
fdtab_t *dt;
fdfile_t *ff;
file_t *fp = NULL;
int found = 0;
int i, t;
if (so == NULL)
return 0;
t = db_mutex_enter(proc_lock);
if (!t) {
pr("could not acquire proc_lock mutex\n");
return 0;
}
PROCLIST_FOREACH(p, &allproc) {
if (p->p_stat == SIDL)
continue;
fdp = p->p_fd;
t = db_mutex_enter(&fdp->fd_lock);
if (!t) {
pr("could not acquire fd_lock mutex\n");
continue;
}
dt = fdp->fd_dt;
for (i = 0; i < dt->dt_nfiles; i++) {
ff = dt->dt_ff[i];
if (ff == NULL)
continue;
fp = ff->ff_file;
if (fp == NULL)
continue;
t = db_mutex_enter(&fp->f_lock);
if (!t) {
pr("could not acquire f_lock mutex\n");
continue;
}
if ((struct socket *)fp->f_data != so) {
mutex_exit(&fp->f_lock);
continue;
}
found++;
if (pr)
pr("socket %p: owner %s(pid=%d)\n",
so, p->p_comm, p->p_pid);
mutex_exit(&fp->f_lock);
if (all == 0)
break;
}
mutex_exit(&fdp->fd_lock);
if (all == 0 && found != 0)
break;
}
mutex_exit(proc_lock);
return found;
}
void
socket_print(const char *modif, void (*pr)(const char *, ...))
{
file_t *fp;
struct socket *so;
struct sockbuf *sb_snd, *sb_rcv;
struct mbuf *m_rec, *m;
bool opt_v = false;
bool opt_m = false;
bool opt_a = false;
bool opt_p = false;
int nrecs, nmbufs;
char ch;
const char *family;
while ( (ch = *(modif++)) != '\0') {
switch (ch) {
case 'v':
opt_v = true;
break;
case 'm':
opt_m = true;
break;
case 'a':
opt_a = true;
break;
case 'p':
opt_p = true;
break;
}
}
if (opt_v == false && pr)
(pr)("Ignore empty sockets. use /v to print all.\n");
if (opt_p == true && pr)
(pr)("Don't search owner process.\n");
LIST_FOREACH(fp, &filehead, f_list) {
if (fp->f_type != DTYPE_SOCKET)
continue;
so = (struct socket *)fp->f_data;
if (so == NULL)
continue;
if (so->so_proto->pr_domain->dom_family == AF_INET)
family = "INET";
#ifdef INET6
else if (so->so_proto->pr_domain->dom_family == AF_INET6)
family = "INET6";
#endif
else if (so->so_proto->pr_domain->dom_family == pseudo_AF_KEY)
family = "KEY";
else if (so->so_proto->pr_domain->dom_family == AF_ROUTE)
family = "ROUTE";
else
continue;
sb_snd = &so->so_snd;
sb_rcv = &so->so_rcv;
if (opt_v != true &&
sb_snd->sb_cc == 0 && sb_rcv->sb_cc == 0)
continue;
pr("---SOCKET %p: type %s\n", so, family);
if (opt_p != true)
sofindproc(so, opt_a == true ? 1 : 0, pr);
pr("Send Buffer Bytes: %d [bytes]\n", sb_snd->sb_cc);
pr("Send Buffer mbufs:\n");
m_rec = m = sb_snd->sb_mb;
nrecs = 0;
nmbufs = 0;
while (m_rec) {
nrecs++;
if (opt_m == true)
pr(" mbuf chain %p\n", m_rec);
while (m) {
nmbufs++;
m = m->m_next;
}
m_rec = m = m_rec->m_nextpkt;
}
pr(" Total %d records, %d mbufs.\n", nrecs, nmbufs);
pr("Recv Buffer Usage: %d [bytes]\n", sb_rcv->sb_cc);
pr("Recv Buffer mbufs:\n");
m_rec = m = sb_rcv->sb_mb;
nrecs = 0;
nmbufs = 0;
while (m_rec) {
nrecs++;
if (opt_m == true)
pr(" mbuf chain %p\n", m_rec);
while (m) {
nmbufs++;
m = m->m_next;
}
m_rec = m = m_rec->m_nextpkt;
}
pr(" Total %d records, %d mbufs.\n", nrecs, nmbufs);
}
}
#endif /* DDB */

View File

@ -1,4 +1,4 @@
/* $NetBSD: socketvar.h,v 1.156 2018/06/06 09:46:46 roy Exp $ */
/* $NetBSD: socketvar.h,v 1.157 2018/07/20 08:26:25 msaitoh Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -575,6 +575,10 @@ SYSCTL_DECL(_net_inet_accf);
#endif
void accept_filter_init(void);
#endif
#ifdef DDB
int sofindproc(struct socket *so, int all, void (*pr)(const char *, ...));
void socket_print(const char *modif, void (*pr)(const char *, ...));
#endif
#endif /* _KERNEL */