Added IPv4/IPv6 filter support for tcp trace tools (#3565)

* Added IPv4/IPv6 filter support for tcp trace tools

* Fixed a typo

* Added usage for TCP syn backlog

* Fixed a typo

* Fixed a typo

* Added man support for IPv4/IPv6 family filters
diff --git a/tools/tcpstates.py b/tools/tcpstates.py
index ec5bb7b..cb38c59 100755
--- a/tools/tcpstates.py
+++ b/tools/tcpstates.py
@@ -5,7 +5,7 @@
 # tcpstates   Trace the TCP session state changes with durations.
 #             For Linux, uses BCC, BPF. Embedded C.
 #
-# USAGE: tcpstates [-h] [-C] [-S] [interval [count]]
+# USAGE: tcpstates [-h] [-C] [-S] [interval [count]] [-4 | -6]
 #
 # This uses the sock:inet_sock_set_state tracepoint, added to Linux 4.16.
 # Linux 4.16 also adds more state transitions so that they can be traced.
@@ -34,6 +34,8 @@
     ./tcpstates -L 80     # only trace local port 80
     ./tcpstates -L 80,81  # only trace local ports 80 and 81
     ./tcpstates -D 80     # only trace remote port 80
+    ./tcpstates -4        # trace IPv4 family only
+    ./tcpstates -6        # trace IPv6 family only
 """
 parser = argparse.ArgumentParser(
     description="Trace TCP session state changes and durations",
@@ -55,6 +57,11 @@
     help=argparse.SUPPRESS)
 parser.add_argument("-Y", "--journal", action="store_true",
     help="log session state changes to the systemd journal")
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-4", "--ipv4", action="store_true",
+    help="trace IPv4 family only")
+group.add_argument("-6", "--ipv6", action="store_true",
+    help="trace IPv6 family only")
 args = parser.parse_args()
 debug = 0
 
@@ -126,7 +133,9 @@
         delta_us = 0;
     else
         delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
-
+    u16 family = args->family;
+    FILTER_FAMILY
+    
     if (args->family == AF_INET) {
         struct ipv4_data_t data4 = {
             .span_us = delta_us,
@@ -194,7 +203,8 @@
         delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
 
     u16 family = sk->__sk_common.skc_family;
-
+    FILTER_FAMILY
+    
     if (family == AF_INET) {
         struct ipv4_data_t data4 = {
             .span_us = delta_us,
@@ -258,6 +268,13 @@
     lports_if = ' && '.join(['lport != %d' % lport for lport in lports])
     bpf_text = bpf_text.replace('FILTER_LPORT',
         'if (%s) { last.delete(&sk); return 0; }' % lports_if)
+if args.ipv4:
+    bpf_text = bpf_text.replace('FILTER_FAMILY',
+        'if (family != AF_INET) { return 0; }')
+elif args.ipv6:
+    bpf_text = bpf_text.replace('FILTER_FAMILY',
+        'if (family != AF_INET6) { return 0; }')
+bpf_text = bpf_text.replace('FILTER_FAMILY', '')
 bpf_text = bpf_text.replace('FILTER_DPORT', '')
 bpf_text = bpf_text.replace('FILTER_LPORT', '')