diff --git a/lib/libprocstat/Symbol.map b/lib/libprocstat/Symbol.map index a78a4691fe5..31f19d02d72 100644 --- a/lib/libprocstat/Symbol.map +++ b/lib/libprocstat/Symbol.map @@ -6,7 +6,6 @@ FBSD_1.2 { procstat_freefiles; procstat_freeprocs; procstat_get_pipe_info; - procstat_get_socket_info; procstat_getfiles; procstat_getprocs; procstat_open_kvm; @@ -39,5 +38,6 @@ FBSD_1.5 { procstat_get_pts_info; procstat_get_sem_info; procstat_get_shm_info; + procstat_get_socket_info; procstat_get_vnode_info; }; diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c index d674adc4f9e..34ecea1e302 100644 --- a/lib/libprocstat/libprocstat.c +++ b/lib/libprocstat/libprocstat.c @@ -1497,6 +1497,8 @@ procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, } else sock->inp_ppcb = (uintptr_t)inpcb.inp_ppcb; + sock->sendq = s.so_snd.sb_ccc; + sock->recvq = s.so_rcv.sb_ccc; } } break; @@ -1510,6 +1512,8 @@ procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, sock->so_rcv_sb_state = s.so_rcv.sb_state; sock->so_snd_sb_state = s.so_snd.sb_state; sock->unp_conn = (uintptr_t)unpcb.unp_conn; + sock->sendq = s.so_snd.sb_ccc; + sock->recvq = s.so_rcv.sb_ccc; } } break; @@ -1556,17 +1560,22 @@ procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock, switch(sock->dom_family) { case AF_INET: case AF_INET6: - if (sock->proto == IPPROTO_TCP) + if (sock->proto == IPPROTO_TCP) { sock->inp_ppcb = kif->kf_un.kf_sock.kf_sock_inpcb; + sock->sendq = kif->kf_un.kf_sock.kf_sock_sendq; + sock->recvq = kif->kf_un.kf_sock.kf_sock_recvq; + } break; case AF_UNIX: if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) { - sock->so_rcv_sb_state = - kif->kf_un.kf_sock.kf_sock_rcv_sb_state; - sock->so_snd_sb_state = - kif->kf_un.kf_sock.kf_sock_snd_sb_state; - sock->unp_conn = - kif->kf_un.kf_sock.kf_sock_unpconn; + sock->so_rcv_sb_state = + kif->kf_un.kf_sock.kf_sock_rcv_sb_state; + sock->so_snd_sb_state = + kif->kf_un.kf_sock.kf_sock_snd_sb_state; + sock->unp_conn = + kif->kf_un.kf_sock.kf_sock_unpconn; + sock->sendq = kif->kf_un.kf_sock.kf_sock_sendq; + sock->recvq = kif->kf_un.kf_sock.kf_sock_recvq; } break; default: diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h index 7584878252d..2f3e94311d3 100644 --- a/lib/libprocstat/libprocstat.h +++ b/lib/libprocstat/libprocstat.h @@ -157,6 +157,8 @@ struct sockstat { struct sockaddr_storage sa_peer; /* Peer address. */ int type; char dname[32]; + unsigned int sendq; + unsigned int recvq; }; STAILQ_HEAD(filestat_list, filestat); diff --git a/lib/libprocstat/libprocstat_compat.c b/lib/libprocstat/libprocstat_compat.c index 52d80c7afab..3b867e4cbe2 100644 --- a/lib/libprocstat/libprocstat_compat.c +++ b/lib/libprocstat/libprocstat_compat.c @@ -60,12 +60,29 @@ struct freebsd11_shmstat { uint16_t mode; }; +struct freebsd11_sockstat { + uint64_t inp_ppcb; + uint64_t so_addr; + uint64_t so_pcb; + uint64_t unp_conn; + int dom_family; + int proto; + int so_rcv_sb_state; + int so_snd_sb_state; + struct sockaddr_storage sa_local; /* Socket address. */ + struct sockaddr_storage sa_peer; /* Peer address. */ + int type; + char dname[32]; +}; + int freebsd11_procstat_get_pts_info(struct procstat *procstat, struct filestat *fst, struct freebsd11_ptsstat *pts, char *errbuf); int freebsd11_procstat_get_sem_info(struct procstat *procstat, struct filestat *fst, struct freebsd11_semstat *sem, char *errbuf); int freebsd11_procstat_get_shm_info(struct procstat *procstat, struct filestat *fst, struct freebsd11_shmstat *shm, char *errbuf); +int freebsd11_procstat_get_socket_info(struct procstat *procstat, + struct filestat *fst, struct freebsd11_sockstat *sock, char *errbuf); int freebsd11_procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst, struct freebsd11_vnstat *vn, char *errbuf); @@ -115,6 +132,31 @@ freebsd11_procstat_get_shm_info(struct procstat *procstat, return (0); } +int +freebsd11_procstat_get_socket_info(struct procstat *procstat, struct filestat *fst, + struct freebsd11_sockstat *sock_compat, char *errbuf) +{ + struct sockstat sock; + int r; + + r = procstat_get_socket_info(procstat, fst, &sock, errbuf); + if (r != 0) + return (r); + sock_compat->inp_ppcb = sock.inp_ppcb; + sock_compat->so_addr = sock.so_addr; + sock_compat->so_pcb = sock.so_pcb; + sock_compat->unp_conn = sock.unp_conn; + sock_compat->dom_family = sock.dom_family; + sock_compat->proto = sock.proto; + sock_compat->so_rcv_sb_state = sock.so_rcv_sb_state; + sock_compat->so_snd_sb_state = sock.so_snd_sb_state; + sock_compat->sa_local = sock.sa_local; + sock_compat->sa_peer = sock.sa_peer; + sock_compat->type = sock.type; + memcpy(sock_compat->dname, sock.dname, sizeof(sock.dname)); + return (0); +} + int freebsd11_procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst, struct freebsd11_vnstat *vn_compat, char *errbuf) @@ -138,6 +180,8 @@ freebsd11_procstat_get_vnode_info(struct procstat *procstat, } __sym_compat(procstat_get_pts_info, freebsd11_procstat_get_pts_info, FBSD_1.2); +__sym_compat(procstat_get_socket_info, freebsd11_procstat_get_socket_info, + FBSD_1.2); __sym_compat(procstat_get_vnode_info, freebsd11_procstat_get_vnode_info, FBSD_1.2); __sym_compat(procstat_get_sem_info, freebsd11_procstat_get_sem_info, FBSD_1.3); diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c index a30260bfeeb..d912b522864 100644 --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -359,6 +359,10 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) inpcb = (struct inpcb *)(so->so_pcb); kif->kf_un.kf_sock.kf_sock_inpcb = (uintptr_t)inpcb->inp_ppcb; + kif->kf_un.kf_sock.kf_sock_sendq = + sbused(&so->so_snd); + kif->kf_un.kf_sock.kf_sock_recvq = + sbused(&so->so_rcv); } } break; @@ -372,6 +376,10 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) so->so_rcv.sb_state; kif->kf_un.kf_sock.kf_sock_snd_sb_state = so->so_snd.sb_state; + kif->kf_un.kf_sock.kf_sock_sendq = + sbused(&so->so_snd); + kif->kf_un.kf_sock.kf_sock_recvq = + sbused(&so->so_rcv); } } break; diff --git a/sys/sys/user.h b/sys/sys/user.h index ba5e43a7415..548a86e9545 100644 --- a/sys/sys/user.h +++ b/sys/sys/user.h @@ -344,7 +344,8 @@ struct kinfo_file { int64_t kf_offset; /* Seek location. */ union { struct { - uint32_t kf_spareint; + /* Sendq size */ + uint32_t kf_sock_sendq; /* Socket domain. */ int kf_sock_domain0; /* Socket type. */ @@ -365,8 +366,8 @@ struct kinfo_file { uint16_t kf_sock_snd_sb_state; /* Receive buffer state. */ uint16_t kf_sock_rcv_sb_state; - /* Round to 64 bit alignment. */ - uint32_t kf_sock_pad0; + /* Recvq size. */ + uint32_t kf_sock_recvq; } kf_sock; struct { /* Vnode type. */ diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c index 162669792af..373f413e3b6 100644 --- a/usr.bin/procstat/procstat_files.c +++ b/usr.bin/procstat/procstat_files.c @@ -534,6 +534,12 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp) xo_emit("{:protocol/%-3s/%s} ", protocol_to_string(sock.dom_family, sock.type, sock.proto)); + if (sock.proto == IPPROTO_TCP || + sock.proto == IPPROTO_SCTP || + sock.type == SOCK_STREAM) { + xo_emit("{:sendq/%u} ", sock.sendq); + xo_emit("{:recvq/%u} ", sock.recvq); + } /* * While generally we like to print two addresses, * local and peer, for sockets, it turns out to be