Page MenuHomeFreeBSD

D50629.1794103902.diff
No OneTemporary

Authored By
Unknown
Size
11 KB
Referenced Files
None
Subscribers
None

D50629.1794103902.diff

diff --git a/share/man/man4/ddb.4 b/share/man/man4/ddb.4
--- a/share/man/man4/ddb.4
+++ b/share/man/man4/ddb.4
@@ -24,7 +24,7 @@
.\" any improvements or extensions that they make and grant Carnegie Mellon
.\" the rights to redistribute these changes.
.\"
-.Dd May 28, 2025
+.Dd June 10, 2025
.Dt DDB 4
.Os
.Sh NAME
@@ -604,9 +604,12 @@
modifier will print command line arguments for each process.
.\"
.Pp
-.It Ic show Cm all tcpcbs Ns Op Li / Ns Cm l
+.It Ic show Cm all tcpcbs Ns Op Li / Ns Cm b Ns Cm l
Show the same output as "show tcpcb" does, but for all
TCP control blocks within the system.
+The
+.Cm b
+modifier will request BBLog entries to be printed.
Using the
.Cm l
modifier will limit the output to TCP control blocks, which are locked.
@@ -1103,7 +1106,7 @@
Not present on some platforms.
.\"
.Pp
-.It Ic show Cm tcpcb Ar addr
+.It Ic show Cm tcpcb Ns Oo Li / Ns Cm b Oc Ar addr
Print TCP control block
.Vt struct tcpcb
lying at address
@@ -1111,6 +1114,9 @@
For exact interpretation of output, visit
.Pa netinet/tcp.h
header file.
+The
+.Cm b
+modifier will request BBLog entries to be printed.
.\"
.Pp
.It Ic show Cm thread Op Ar addr | tid
diff --git a/sys/netinet/tcp_log_buf.h b/sys/netinet/tcp_log_buf.h
--- a/sys/netinet/tcp_log_buf.h
+++ b/sys/netinet/tcp_log_buf.h
@@ -585,5 +585,9 @@
}
#endif /* TCP_BLACKBOX */
+#ifdef DDB
+void db_print_bblog_entries(struct tcp_log_stailq *log_entries, int indent);
+#endif
+
#endif /* _KERNEL */
#endif /* __tcp_log_buf_h__ */
diff --git a/sys/netinet/tcp_log_buf.c b/sys/netinet/tcp_log_buf.c
--- a/sys/netinet/tcp_log_buf.c
+++ b/sys/netinet/tcp_log_buf.c
@@ -29,6 +29,7 @@
#include <sys/cdefs.h>
#include "opt_inet.h"
+#include "opt_ddb.h"
#include <sys/param.h>
#include <sys/arb.h>
#include <sys/hash.h>
@@ -43,11 +44,18 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
+#ifdef DDB
+#include <sys/time.h>
+#endif
#include <sys/tree.h>
#include <sys/stats.h> /* Must come after qmath.h and tree.h */
#include <sys/counter.h>
#include <dev/tcp_log/tcp_log_dev.h>
+#ifdef DDB
+#include <ddb/ddb.h>
+#endif
+
#include <net/if.h>
#include <net/if_var.h>
#include <net/vnet.h>
@@ -2972,3 +2980,376 @@
done:
INP_WUNLOCK(inp);
}
+
+#ifdef DDB
+static void
+db_print_indent(int indent)
+{
+ int i;
+
+ for (i = 0; i < indent; i++)
+ db_printf(" ");
+}
+
+static void
+db_print_tcphdr(struct tcp_log_buffer *tlm_buf)
+{
+ struct sackblk sack;
+ struct tcphdr *th;
+ int cnt, i, j, opt, optlen, num_sacks;
+ uint32_t val, ecr;
+ uint16_t mss;
+ uint16_t flags;
+
+ if ((tlm_buf->tlb_eventflags & TLB_FLAG_HDR) == 0) {
+ return;
+ }
+ th = &tlm_buf->tlb_th;
+ flags = tcp_get_flags(th);
+ if (flags & TH_FIN) {
+ db_printf("F");
+ }
+ if (flags & TH_SYN) {
+ db_printf("S");
+ }
+ if (flags & TH_RST) {
+ db_printf("R");
+ }
+ if (flags & TH_PUSH) {
+ db_printf("P");
+ }
+ if (flags & TH_ACK) {
+ db_printf(".");
+ }
+ if (flags & TH_URG) {
+ db_printf("U");
+ }
+ if (flags & TH_ECE) {
+ db_printf("E");
+ }
+ if (flags & TH_FIN) {
+ db_printf("F");
+ }
+ if (flags & TH_CWR) {
+ db_printf("W");
+ }
+ if (flags & TH_FIN) {
+ db_printf("F");
+ }
+ if (flags & TH_AE) {
+ db_printf("A");
+ }
+ db_printf(" %u:%u(%u)", ntohl(th->th_seq),
+ ntohl(th->th_seq) + tlm_buf->tlb_len, tlm_buf->tlb_len);
+ if (flags & TH_ACK) {
+ db_printf(" ack %u", ntohl(th->th_ack));
+ }
+ db_printf(" win %u", ntohs(th->th_win));
+ if (flags & TH_URG) {
+ db_printf(" urg %u", ntohs(th->th_urp));
+ }
+ cnt = (th->th_off << 2) - sizeof(struct tcphdr);
+ if (cnt > 0) {
+ db_printf(" <");
+ for (i = 0; i < cnt; i += optlen) {
+ opt = tlm_buf->tlb_opts[i];
+ if (opt == TCPOPT_EOL || opt == TCPOPT_NOP) {
+ optlen = 1;
+ } else {
+ if (cnt - i < 2) {
+ break;
+ }
+ optlen = tlm_buf->tlb_opts[i + 1];
+ if (optlen < 2 || optlen > cnt - i) {
+ break;
+ }
+ }
+ if (i > 0) {
+ db_printf(",");
+ }
+ switch (opt) {
+ case TCPOPT_EOL:
+ db_printf("eol");
+ break;
+ case TCPOPT_NOP:
+ db_printf("nop");
+ break;
+ case TCPOPT_MAXSEG:
+ if (optlen != TCPOLEN_MAXSEG) {
+ break;
+ }
+ bcopy(tlm_buf->tlb_opts + i + 2, &mss,
+ sizeof(uint16_t));
+ db_printf("mss %u", ntohs(mss));
+ break;
+ case TCPOPT_WINDOW:
+ if (optlen != TCPOLEN_WINDOW) {
+ break;
+ }
+ db_printf("wscale %u",
+ tlm_buf->tlb_opts[i + 2]);
+ break;
+ case TCPOPT_SACK_PERMITTED:
+ if (optlen != TCPOLEN_SACK_PERMITTED) {
+ break;
+ }
+ db_printf("sackOK");
+ break;
+ case TCPOPT_SACK:
+ if (optlen == TCPOLEN_SACKHDR ||
+ (optlen - 2) % TCPOLEN_SACK != 0) {
+ break;
+ }
+ num_sacks = (optlen - 2) / TCPOLEN_SACK;
+ db_printf("sack");
+ for (j = 0; j < num_sacks; j++) {
+ bcopy(tlm_buf->tlb_opts + i + 2 +
+ j * TCPOLEN_SACK, &sack,
+ TCPOLEN_SACK);
+ db_printf(" %u:%u", ntohl(sack.start),
+ ntohl(sack.end));
+ }
+ break;
+ case TCPOPT_TIMESTAMP:
+ if (optlen != TCPOLEN_TIMESTAMP) {
+ break;
+ }
+ bcopy(tlm_buf->tlb_opts + i + 2, &val,
+ sizeof(uint32_t));
+ bcopy(tlm_buf->tlb_opts + i + 6, &ecr,
+ sizeof(uint32_t));
+ db_printf("TS val %u ecr %u", ntohl(val),
+ ntohl(ecr));
+ break;
+ case TCPOPT_SIGNATURE:
+ db_printf("md5");
+ if (optlen > 2) {
+ db_printf(" ");
+ }
+ for (j = 0; j < optlen - 2; j++) {
+ db_printf("%02x",
+ tlm_buf->tlb_opts[i + 2 + j]);
+ }
+ break;
+ case TCPOPT_FAST_OPEN:
+ db_printf("FO");
+ if (optlen > 2) {
+ db_printf(" ");
+ }
+ for (j = 0; j < optlen - 2; j++) {
+ db_printf("%02x",
+ tlm_buf->tlb_opts[i + 2 + j]);
+ }
+ break;
+ default:
+ db_printf("opt=%u len=%u", opt, optlen);
+ break;
+ }
+ }
+ db_printf(">");
+ }
+}
+static void
+db_print_pru(struct tcp_log_buffer *tlm_buf)
+{
+ switch (tlm_buf->tlb_flex1) {
+ case PRU_ATTACH:
+ db_printf("ATTACH");
+ break;
+ case PRU_DETACH:
+ db_printf("DETACH");
+ break;
+ case PRU_BIND:
+ db_printf("BIND");
+ break;
+ case PRU_LISTEN:
+ db_printf("LISTEN");
+ break;
+ case PRU_CONNECT:
+ db_printf("CONNECT");
+ break;
+ case PRU_ACCEPT:
+ db_printf("ACCEPT");
+ break;
+ case PRU_DISCONNECT:
+ db_printf("DISCONNECT");
+ break;
+ case PRU_SHUTDOWN:
+ db_printf("SHUTDOWN");
+ break;
+ case PRU_RCVD:
+ db_printf("RCVD");
+ break;
+ case PRU_SEND:
+ db_printf("SEND");
+ break;
+ case PRU_ABORT:
+ db_printf("ABORT");
+ break;
+ case PRU_CONTROL:
+ db_printf("CONTROL");
+ break;
+ case PRU_SENSE:
+ db_printf("SENSE");
+ break;
+ case PRU_RCVOOB:
+ db_printf("RCVOOB");
+ break;
+ case PRU_SENDOOB:
+ db_printf("SENDOOB");
+ break;
+ case PRU_SOCKADDR:
+ db_printf("SOCKADDR");
+ break;
+ case PRU_PEERADDR:
+ db_printf("PEERADDR");
+ break;
+ case PRU_CONNECT2:
+ db_printf("CONNECT2");
+ break;
+ case PRU_FASTTIMO:
+ db_printf("FASTTIMO");
+ break;
+ case PRU_SLOWTIMO:
+ db_printf("SLOWTIMO");
+ break;
+ case PRU_PROTORCV:
+ db_printf("PROTORCV");
+ break;
+ case PRU_PROTOSEND:
+ db_printf("PROTOSEND");
+ break;
+ case PRU_SEND_EOF:
+ db_printf("SEND_EOF");
+ break;
+ case PRU_SOSETLABEL:
+ db_printf("SOSETLABEL");
+ break;
+ case PRU_CLOSE:
+ db_printf("CLOSE");
+ break;
+ case PRU_FLUSH:
+ db_printf("FLUSH");
+ break;
+ default:
+ db_printf("Unknown PRU (%u)", tlm_buf->tlb_flex1);
+ break;
+ }
+ if (tlm_buf->tlb_errno >= 0) {
+ db_printf(", error: %d", tlm_buf->tlb_errno);
+ }
+}
+
+static void
+db_print_rto(struct tcp_log_buffer *tlm_buf)
+{
+ tt_what what;
+ tt_which which;
+
+ what = (tlm_buf->tlb_flex1 & 0xffffff00) >> 8;
+ which = tlm_buf->tlb_flex1 & 0x000000ff;
+ switch (what) {
+ case TT_PROCESSING:
+ db_printf("Processing ");
+ break;
+ case TT_PROCESSED:
+ db_printf("Processed ");
+ break;
+ case TT_STARTING:
+ db_printf("Starting ");
+ break;
+ case TT_STOPPING:
+ db_printf("Stopping ");
+ break;
+ default:
+ db_printf("Unknown operation (%u) for ", what);
+ break;
+ }
+ switch (which) {
+ case TT_REXMT:
+ db_printf("Retransmission ");
+ break;
+ case TT_PERSIST:
+ db_printf("Persist ");
+ break;
+ case TT_KEEP:
+ db_printf("Keepalive ");
+ break;
+ case TT_2MSL:
+ db_printf("2 MSL ");
+ break;
+ case TT_DELACK:
+ db_printf("Delayed ACK ");
+ break;
+ default:
+ db_printf("Unknown (%u) ", which);
+ break;
+ }
+ db_printf("timer");
+ if (what == TT_STARTING) {
+ db_printf(": %u ms", tlm_buf->tlb_flex2);
+ }
+}
+
+static void
+db_print_usersend(struct tcp_log_buffer *tlm_buf)
+{
+ if ((tlm_buf->tlb_eventflags & TLB_FLAG_RXBUF) == 0) {
+ return;
+ }
+ if ((tlm_buf->tlb_eventflags & TLB_FLAG_TXBUF) == 0) {
+ return;
+ }
+ db_printf("usersend: rcv.acc: %u rcv.ccc: %u snd.acc: %u snd.ccc: %u",
+ tlm_buf->tlb_rxbuf.tls_sb_acc, tlm_buf->tlb_rxbuf.tls_sb_ccc,
+ tlm_buf->tlb_txbuf.tls_sb_acc, tlm_buf->tlb_txbuf.tls_sb_ccc);
+}
+
+void
+db_print_bblog_entries(struct tcp_log_stailq *log_entries, int indent)
+{
+ struct tcp_log_mem *log_entry;
+ struct tcp_log_buffer *tlm_buf, *prev_tlm_buf;
+ int64_t delta_t;
+
+ indent += 2;
+ prev_tlm_buf = NULL;
+ STAILQ_FOREACH(log_entry, log_entries, tlm_queue) {
+ db_print_indent(indent);
+ tlm_buf = &log_entry->tlm_buf;
+ if (prev_tlm_buf == NULL) {
+ db_printf(" 0.000 ");
+ } else {
+ delta_t = sbttoms(tvtosbt(tlm_buf->tlb_tv) -
+ tvtosbt(prev_tlm_buf->tlb_tv));
+ db_printf("+%u.%03u ", (uint32_t)(delta_t / 1000),
+ (uint32_t)(delta_t % 1000));
+ }
+ switch (tlm_buf->tlb_eventid) {
+ case TCP_LOG_IN:
+ db_printf("< ");
+ db_print_tcphdr(tlm_buf);
+ break;
+ case TCP_LOG_OUT:
+ db_printf("> ");
+ db_print_tcphdr(tlm_buf);
+ break;
+ case TCP_LOG_RTO:
+ db_print_rto(tlm_buf);
+ break;
+ case TCP_LOG_PRU:
+ db_print_pru(tlm_buf);
+ break;
+ case TCP_LOG_USERSEND:
+ db_print_usersend(tlm_buf);
+ break;
+ default:
+ break;
+ }
+ db_printf("\n");
+ prev_tlm_buf = tlm_buf;
+ if (db_pager_quit)
+ break;
+ }
+}
+#endif
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -3083,7 +3083,7 @@
}
static void
-db_print_tcpcb(struct tcpcb *tp, const char *name, int indent)
+db_print_tcpcb(struct tcpcb *tp, const char *name, int indent, bool show_bblog)
{
db_print_indent(indent);
@@ -3208,35 +3208,42 @@
db_print_indent(indent);
db_printf("t_lognum: %d t_loglimit: %d t_logsn: %u\n",
tp->t_lognum, tp->t_loglimit, tp->t_logsn);
+
+ if (show_bblog) {
+ db_print_bblog_entries(&tp->t_logs, indent);
+ }
}
DB_SHOW_COMMAND(tcpcb, db_show_tcpcb)
{
struct tcpcb *tp;
+ bool show_bblog;
if (!have_addr) {
db_printf("usage: show tcpcb <addr>\n");
return;
}
+ show_bblog = strchr(modif, 'b') != NULL;
tp = (struct tcpcb *)addr;
- db_print_tcpcb(tp, "tcpcb", 0);
+ db_print_tcpcb(tp, "tcpcb", 0, show_bblog);
}
DB_SHOW_ALL_COMMAND(tcpcbs, db_show_all_tcpcbs)
{
VNET_ITERATOR_DECL(vnet_iter);
struct inpcb *inp;
- bool only_locked;
+ bool only_locked, show_bblog;
only_locked = strchr(modif, 'l') != NULL;
+ show_bblog = strchr(modif, 'b') != NULL;
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
CK_LIST_FOREACH(inp, &V_tcbinfo.ipi_listhead, inp_list) {
if (only_locked &&
inp->inp_lock.rw_lock == RW_UNLOCKED)
continue;
- db_print_tcpcb(intotcpcb(inp), "tcpcb", 0);
+ db_print_tcpcb(intotcpcb(inp), "tcpcb", 0, show_bblog);
if (db_pager_quit)
break;
}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 8, 2:11 AM (15 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41562343
Default Alt Text
D50629.1794103902.diff (11 KB)

Event Timeline