BPF_SOCK_OPS_RETRANS_CB_FLAG    = (1<<1),
        BPF_SOCK_OPS_STATE_CB_FLAG      = (1<<2),
        BPF_SOCK_OPS_RTT_CB_FLAG        = (1<<3),
+       BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG  = (1<<4),
+       BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG = (1<<5),
 /* Mask of all currently supported cb flags */
-       BPF_SOCK_OPS_ALL_CB_FLAGS       = 0xF,
+       BPF_SOCK_OPS_ALL_CB_FLAGS       = 0x3F,
 };
 
 /* List of known BPF sock_ops operators.
 
 #endif
 
 #ifdef CONFIG_CGROUP_BPF
+static void bpf_skops_parse_hdr(struct sock *sk, struct sk_buff *skb)
+{
+       bool unknown_opt = tcp_sk(sk)->rx_opt.saw_unknown &&
+               BPF_SOCK_OPS_TEST_FLAG(tcp_sk(sk),
+                                      BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG);
+       bool parse_all_opt = BPF_SOCK_OPS_TEST_FLAG(tcp_sk(sk),
+                                                   BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG);
+
+       if (likely(!unknown_opt && !parse_all_opt))
+               return;
+
+       /* The skb will be handled in the
+        * bpf_skops_established() or
+        * bpf_skops_write_hdr_opt().
+        */
+       switch (sk->sk_state) {
+       case TCP_SYN_RECV:
+       case TCP_SYN_SENT:
+       case TCP_LISTEN:
+               return;
+       }
+
+       /* BPF prog will have access to the sk and skb.
+        *
+        * The bpf running context preparation and the actual bpf prog
+        * calling will be implemented in a later PATCH together with
+        * other bpf pieces.
+        */
+}
+
 static void bpf_skops_established(struct sock *sk, int bpf_op,
                                  struct sk_buff *skb)
 {
        BPF_CGROUP_RUN_PROG_SOCK_OPS(&sock_ops);
 }
 #else
+static void bpf_skops_parse_hdr(struct sock *sk, struct sk_buff *skb)
+{
+}
+
 static void bpf_skops_established(struct sock *sk, int bpf_op,
                                  struct sk_buff *skb)
 {
                goto discard;
        }
 
+       bpf_skops_parse_hdr(sk, skb);
+
        return true;
 
 discard:
 
        BPF_SOCK_OPS_RETRANS_CB_FLAG    = (1<<1),
        BPF_SOCK_OPS_STATE_CB_FLAG      = (1<<2),
        BPF_SOCK_OPS_RTT_CB_FLAG        = (1<<3),
+       BPF_SOCK_OPS_PARSE_ALL_HDR_OPT_CB_FLAG  = (1<<4),
+       BPF_SOCK_OPS_PARSE_UNKNOWN_HDR_OPT_CB_FLAG = (1<<5),
 /* Mask of all currently supported cb flags */
-       BPF_SOCK_OPS_ALL_CB_FLAGS       = 0xF,
+       BPF_SOCK_OPS_ALL_CB_FLAGS       = 0x3F,
 };
 
 /* List of known BPF sock_ops operators.