SK_PACING_FQ            = 2,
 };
 
-/* Pointer stored in sk_user_data might not be suitable for copying
- * when cloning the socket. For instance, it can point to a reference
- * counted object. sk_user_data bottom bit is set if pointer must not
- * be copied.
+/* flag bits in sk_user_data
+ *
+ * - SK_USER_DATA_NOCOPY:      Pointer stored in sk_user_data might
+ *   not be suitable for copying when cloning the socket. For instance,
+ *   it can point to a reference counted object. sk_user_data bottom
+ *   bit is set if pointer must not be copied.
+ *
+ * - SK_USER_DATA_BPF:         Mark whether sk_user_data field is
+ *   managed/owned by a BPF reuseport array. This bit should be set
+ *   when sk_user_data's sk is added to the bpf's reuseport_array.
+ *
+ * - SK_USER_DATA_PSOCK:       Mark whether pointer stored in
+ *   sk_user_data points to psock type. This bit should be set
+ *   when sk_user_data is assigned to a psock object.
  */
 #define SK_USER_DATA_NOCOPY    1UL
-#define SK_USER_DATA_BPF       2UL     /* Managed by BPF */
-#define SK_USER_DATA_PTRMASK   ~(SK_USER_DATA_NOCOPY | SK_USER_DATA_BPF)
+#define SK_USER_DATA_BPF       2UL
+#define SK_USER_DATA_PSOCK     4UL
+#define SK_USER_DATA_PTRMASK   ~(SK_USER_DATA_NOCOPY | SK_USER_DATA_BPF |\
+                                 SK_USER_DATA_PSOCK)
 
 /**
  * sk_user_data_is_nocopy - Test if sk_user_data pointer must not be copied
 
 #define __sk_user_data(sk) ((*((void __rcu **)&(sk)->sk_user_data)))
 
+/**
+ * __rcu_dereference_sk_user_data_with_flags - return the pointer
+ * only if argument flags all has been set in sk_user_data. Otherwise
+ * return NULL
+ *
+ * @sk: socket
+ * @flags: flag bits
+ */
+static inline void *
+__rcu_dereference_sk_user_data_with_flags(const struct sock *sk,
+                                         uintptr_t flags)
+{
+       uintptr_t sk_user_data = (uintptr_t)rcu_dereference(__sk_user_data(sk));
+
+       WARN_ON_ONCE(flags & SK_USER_DATA_PTRMASK);
+
+       if ((sk_user_data & flags) == flags)
+               return (void *)(sk_user_data & SK_USER_DATA_PTRMASK);
+       return NULL;
+}
+
 #define rcu_dereference_sk_user_data(sk)                               \
+       __rcu_dereference_sk_user_data_with_flags(sk, 0)
+#define __rcu_assign_sk_user_data_with_flags(sk, ptr, flags)           \
 ({                                                                     \
-       void *__tmp = rcu_dereference(__sk_user_data((sk)));            \
-       (void *)((uintptr_t)__tmp & SK_USER_DATA_PTRMASK);              \
-})
-#define rcu_assign_sk_user_data(sk, ptr)                               \
-({                                                                     \
-       uintptr_t __tmp = (uintptr_t)(ptr);                             \
-       WARN_ON_ONCE(__tmp & ~SK_USER_DATA_PTRMASK);                    \
-       rcu_assign_pointer(__sk_user_data((sk)), __tmp);                \
-})
-#define rcu_assign_sk_user_data_nocopy(sk, ptr)                                \
-({                                                                     \
-       uintptr_t __tmp = (uintptr_t)(ptr);                             \
-       WARN_ON_ONCE(__tmp & ~SK_USER_DATA_PTRMASK);                    \
+       uintptr_t __tmp1 = (uintptr_t)(ptr),                            \
+                 __tmp2 = (uintptr_t)(flags);                          \
+       WARN_ON_ONCE(__tmp1 & ~SK_USER_DATA_PTRMASK);                   \
+       WARN_ON_ONCE(__tmp2 & SK_USER_DATA_PTRMASK);                    \
        rcu_assign_pointer(__sk_user_data((sk)),                        \
-                          __tmp | SK_USER_DATA_NOCOPY);                \
+                          __tmp1 | __tmp2);                            \
 })
+#define rcu_assign_sk_user_data(sk, ptr)                               \
+       __rcu_assign_sk_user_data_with_flags(sk, ptr, 0)
 
 static inline
 struct net *sock_net(const struct sock *sk)