__u32 local_ip6[4];     /* Stored in network byte order */
        __u32 remote_port;      /* Stored in network byte order */
        __u32 local_port;       /* stored in host byte order */
+       __u32 is_fullsock;      /* Some TCP fields are only valid if
+                                * there is a full socket. If not, the
+                                * fields read as zero.
+                                */
+       __u32 snd_cwnd;
+       __u32 srtt_us;          /* Averaged RTT << 3 in usecs */
 };
 
 /* List of known BPF sock_ops operators.
 
                *insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
                                      offsetof(struct sock_common, skc_num));
                break;
+
+       case offsetof(struct bpf_sock_ops, is_fullsock):
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+                                               struct bpf_sock_ops_kern,
+                                               is_fullsock),
+                                     si->dst_reg, si->src_reg,
+                                     offsetof(struct bpf_sock_ops_kern,
+                                              is_fullsock));
+               break;
+
+/* Helper macro for adding read access to tcp_sock fields. */
+#define SOCK_OPS_GET_TCP32(FIELD_NAME)                                       \
+       do {                                                                  \
+               BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, FIELD_NAME) != 4); \
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(                       \
+                                               struct bpf_sock_ops_kern,     \
+                                               is_fullsock),                 \
+                                     si->dst_reg, si->src_reg,               \
+                                     offsetof(struct bpf_sock_ops_kern,      \
+                                              is_fullsock));                 \
+               *insn++ = BPF_JMP_IMM(BPF_JEQ, si->dst_reg, 0, 2);            \
+               *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(                       \
+                                               struct bpf_sock_ops_kern, sk),\
+                                     si->dst_reg, si->src_reg,               \
+                                     offsetof(struct bpf_sock_ops_kern, sk));\
+               *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,        \
+                                     offsetof(struct tcp_sock, FIELD_NAME)); \
+       } while (0)
+
+       case offsetof(struct bpf_sock_ops, snd_cwnd):
+               SOCK_OPS_GET_TCP32(snd_cwnd);
+               break;
+
+       case offsetof(struct bpf_sock_ops, srtt_us):
+               SOCK_OPS_GET_TCP32(srtt_us);
+               break;
        }
        return insn - insn_buf;
 }