add tcpsynbl
diff --git a/README.md b/README.md
index 66bac4e..f926224 100644
--- a/README.md
+++ b/README.md
@@ -158,6 +158,7 @@
 - tools/[tcpretrans](tools/tcpretrans.py): Trace TCP retransmits and TLPs. [Examples](tools/tcpretrans_example.txt).
 - tools/[tcpstates](tools/tcpstates.py): Trace TCP session state changes with durations. [Examples](tools/tcpstates_example.txt).
 - tools/[tcpsubnet](tools/tcpsubnet.py): Summarize and aggregate TCP send by subnet. [Examples](tools/tcpsubnet_example.txt).
+- tools/[tcpsynbl](tools/tcpsynbl.py): Show TCP SYN backlog. [Examples](tools/tcpsynbl_example.txt).
 - tools/[tcptop](tools/tcptop.py): Summarize TCP send/recv throughput by host. Top for TCP. [Examples](tools/tcptop_example.txt).
 - tools/[tcptracer](tools/tcptracer.py): Trace TCP established connections (connect(), accept(), close()). [Examples](tools/tcptracer_example.txt).
 - tools/[threadsnoop](tools/threadsnoop.py): List new thread creation. [Examples](tools/threadsnoop_example.txt).
diff --git a/man/man8/tcpsynbl.8 b/man/man8/tcpsynbl.8
new file mode 100644
index 0000000..4dd38c8
--- /dev/null
+++ b/man/man8/tcpsynbl.8
@@ -0,0 +1,59 @@
+.TH tcpsynbl 8  "2019-07-03" "USER COMMANDS"
+.SH NAME
+tcpsynbl \- Show the TCP SYN backlog as a histogram. Uses BCC/eBPF.
+.SH SYNOPSIS
+.B tcpsynbl
+.SH DESCRIPTION
+This tool shows the TCP SYN backlog size during SYN arrival as a histogram.
+This lets you see how close your applications are to hitting the backlog limit
+and dropping SYNs (causing performance issues with SYN retransmits), and is a
+measure of workload saturation. The histogram shown is measured at the time of
+SYN received, and a separate histogram is shown for each backlog limit.
+
+This works by tracing the tcp_v4_syn_recv_sock() and tcp_v6_syn_recv_sock()
+kernel functions using dynamic instrumentation. Since these functions may
+change in future kernels, this tool may need maintenance to keep working.
+
+Since this uses BPF, only the root user can use this tool.
+.SH REQUIREMENTS
+CONFIG_BPF and BCC.
+.SH EXAMPLES
+.TP
+Show the TCP SYN backlog as a histogram.
+#
+.B tcpsynbl
+.SH FIELDS
+.TP
+backlog
+The backlog size when a SYN was received.
+.TP
+count
+The number of times this backlog size was encountered.
+.TP
+distribution
+An ASCII visualization of the count column.
+.SH OVERHEAD
+Inbound SYNs should be relatively low compared to packets and other events,
+so the overhead of this tool is expected to be negligible.
+.SH SOURCE
+This originated as a bpftrace tool from the book "BPF Performance Tools",
+published by Addison Wesley (2019):
+.IP
+http://www.brendangregg.com/bpf-performance-tools-book.html
+.PP
+See the book for more documentation on this tool.
+.PP
+This version is in the BCC repository:
+.IP
+https://github.com/iovisor/bcc
+.PP
+Also look in the bcc distribution for a companion _examples.txt file
+containing example usage, output, and commentary for this tool.
+.SH OS
+Linux
+.SH STABILITY
+Unstable - in development.
+.SH AUTHOR
+Brendan Gregg
+.SH SEE ALSO
+tcptop(8)
diff --git a/tools/tcpsynbl.py b/tools/tcpsynbl.py
new file mode 100755
index 0000000..c24eb96
--- /dev/null
+++ b/tools/tcpsynbl.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+# @lint-avoid-python-3-compatibility-imports
+#
+# tcpsynbl      Show TCP SYN backlog.
+#               For Linux, uses BCC, eBPF. Embedded C.
+#
+# Copyright (c) 2019 Brendan Gregg.
+# Licensed under the Apache License, Version 2.0 (the "License").
+# This was originally created for the BPF Performance Tools book
+# published by Addison Wesley. ISBN-13: 9780136554820
+# When copying or porting, include this comment.
+#
+# 03-Jul-2019   Brendan Gregg   Ported from bpftrace to BCC.
+
+from __future__ import print_function
+from bcc import BPF
+from time import sleep
+
+# load BPF program
+b = BPF(text="""
+#include <net/sock.h>
+
+typedef struct backlog_key {
+    u32 backlog;
+    u64 slot;
+} backlog_key_t;
+
+BPF_HISTOGRAM(dist, backlog_key_t);
+
+int do_entry(struct pt_regs *ctx) {
+    struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx);
+
+    backlog_key_t key = {};
+    key.backlog = sk->sk_max_ack_backlog;
+    key.slot = bpf_log2l(sk->sk_ack_backlog);
+    dist.increment(key);
+
+    return 0;
+};
+""")
+b.attach_kprobe(event="tcp_v4_syn_recv_sock", fn_name="do_entry")
+b.attach_kprobe(event="tcp_v6_syn_recv_sock", fn_name="do_entry")
+
+print("Tracing SYN backlog size. Ctrl-C to end.");
+
+try:
+    sleep(99999999)
+except KeyboardInterrupt:
+    print()
+
+dist = b.get_table("dist")
+dist.print_log2_hist("backlog", "backlog_max")
diff --git a/tools/tcpsynbl_example.txt b/tools/tcpsynbl_example.txt
new file mode 100644
index 0000000..1ac167d
--- /dev/null
+++ b/tools/tcpsynbl_example.txt
@@ -0,0 +1,20 @@
+Demonstrations of tcpsynbl, the Linux BCC/eBPF version.
+
+
+This tool shows the TCP SYN backlog size during SYN arrival as a histogram.
+This lets you see how close your applications are to hitting the backlog limit
+and dropping SYNs (causing performance issues with SYN retransmits). For
+example:
+
+# ./tcpsynbl.py 
+Tracing SYN backlog size. Ctrl-C to end.
+^C
+
+backlog_max = 500L
+     backlog             : count     distribution
+         0 -> 1          : 961      |****************************************|
+         2 -> 3          : 1        |                                        |
+
+This output shows that for the backlog limit of 500, there were 961 SYN
+arrival where the backlog was zero or one, and one accept where the backlog was
+two or three. This indicates that we are nowhere near this limit.