1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Cloudflare Ltd https://cloudflare.com */
4 #include <linux/skmsg.h>
14 static struct proto
*udpv6_prot_saved __read_mostly
;
15 static DEFINE_SPINLOCK(udpv6_prot_lock
);
16 static struct proto udp_bpf_prots
[UDP_BPF_NUM_PROTS
];
18 static void udp_bpf_rebuild_protos(struct proto
*prot
, const struct proto
*base
)
21 prot
->unhash
= sock_map_unhash
;
22 prot
->close
= sock_map_close
;
25 static void udp_bpf_check_v6_needs_rebuild(struct proto
*ops
)
27 if (unlikely(ops
!= smp_load_acquire(&udpv6_prot_saved
))) {
28 spin_lock_bh(&udpv6_prot_lock
);
29 if (likely(ops
!= udpv6_prot_saved
)) {
30 udp_bpf_rebuild_protos(&udp_bpf_prots
[UDP_BPF_IPV6
], ops
);
31 smp_store_release(&udpv6_prot_saved
, ops
);
33 spin_unlock_bh(&udpv6_prot_lock
);
37 static int __init
udp_bpf_v4_build_proto(void)
39 udp_bpf_rebuild_protos(&udp_bpf_prots
[UDP_BPF_IPV4
], &udp_prot
);
42 core_initcall(udp_bpf_v4_build_proto
);
44 struct proto
*udp_bpf_get_proto(struct sock
*sk
, struct sk_psock
*psock
)
46 int family
= sk
->sk_family
== AF_INET
? UDP_BPF_IPV4
: UDP_BPF_IPV6
;
48 if (sk
->sk_family
== AF_INET6
)
49 udp_bpf_check_v6_needs_rebuild(psock
->sk_proto
);
51 return &udp_bpf_prots
[family
];