[DTrace-devel] [PATCH v2 1/2] udp: new provider

Eugene Loh eugene.loh at oracle.com
Fri Aug 29 17:58:04 UTC 2025


Reviewed-by: Eugene Loh <eugene.loh at oracle.com>
(I didn't scrutinize every detail, but looks about right.)

On 8/29/25 04:24, Alan Maguire wrote:
> Support UDP send and receive, using raw fbt probes; since
> udp.d changes sync dlibs also.  Update test.x provider check
> for udp, and add udp to expected providers.
>
> Signed-off-by: Alan Maguire <alan.maguire at oracle.com>
> ---
>   dlibs/aarch64/5.11/udp.d                    |  11 +-
>   dlibs/aarch64/5.12/udp.d                    |  11 +-
>   dlibs/aarch64/5.14/udp.d                    |  11 +-
>   dlibs/aarch64/5.16/udp.d                    |  11 +-
>   dlibs/aarch64/5.2/udp.d                     |  11 +-
>   dlibs/aarch64/5.6/udp.d                     |  11 +-
>   dlibs/aarch64/6.1/udp.d                     |  11 +-
>   dlibs/aarch64/6.10/udp.d                    |  11 +-
>   dlibs/x86_64/5.11/udp.d                     |  11 +-
>   dlibs/x86_64/5.12/udp.d                     |  11 +-
>   dlibs/x86_64/5.14/udp.d                     |  11 +-
>   dlibs/x86_64/5.16/udp.d                     |  11 +-
>   dlibs/x86_64/5.2/udp.d                      |  11 +-
>   dlibs/x86_64/5.6/udp.d                      |  11 +-
>   dlibs/x86_64/6.1/udp.d                      |  11 +-
>   dlibs/x86_64/6.10/udp.d                     |  11 +-
>   libdtrace/Build                             |   2 +
>   libdtrace/dt_prov_udp.c                     | 170 ++++++++++++++++++++
>   libdtrace/dt_provider.c                     |   1 +
>   libdtrace/dt_provider.h                     |   1 +
>   libdtrace/udp.d                             |  11 +-
>   test/unittest/dtrace-util/tst.ListProbes.r  |   1 +
>   test/unittest/dtrace-util/tst.ListProbes.sh |   1 +
>   test/unittest/udp/test.x                    |   6 +-
>   24 files changed, 279 insertions(+), 90 deletions(-)
>   create mode 100644 libdtrace/dt_prov_udp.c
>
> diff --git a/dlibs/aarch64/5.11/udp.d b/dlibs/aarch64/5.11/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/aarch64/5.11/udp.d
> +++ b/dlibs/aarch64/5.11/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/aarch64/5.12/udp.d b/dlibs/aarch64/5.12/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/aarch64/5.12/udp.d
> +++ b/dlibs/aarch64/5.12/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/aarch64/5.14/udp.d b/dlibs/aarch64/5.14/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/aarch64/5.14/udp.d
> +++ b/dlibs/aarch64/5.14/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/aarch64/5.16/udp.d b/dlibs/aarch64/5.16/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/aarch64/5.16/udp.d
> +++ b/dlibs/aarch64/5.16/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/aarch64/5.2/udp.d b/dlibs/aarch64/5.2/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/aarch64/5.2/udp.d
> +++ b/dlibs/aarch64/5.2/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/aarch64/5.6/udp.d b/dlibs/aarch64/5.6/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/aarch64/5.6/udp.d
> +++ b/dlibs/aarch64/5.6/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/aarch64/6.1/udp.d b/dlibs/aarch64/6.1/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/aarch64/6.1/udp.d
> +++ b/dlibs/aarch64/6.1/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/aarch64/6.10/udp.d b/dlibs/aarch64/6.10/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/aarch64/6.10/udp.d
> +++ b/dlibs/aarch64/6.10/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/x86_64/5.11/udp.d b/dlibs/x86_64/5.11/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/x86_64/5.11/udp.d
> +++ b/dlibs/x86_64/5.11/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/x86_64/5.12/udp.d b/dlibs/x86_64/5.12/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/x86_64/5.12/udp.d
> +++ b/dlibs/x86_64/5.12/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/x86_64/5.14/udp.d b/dlibs/x86_64/5.14/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/x86_64/5.14/udp.d
> +++ b/dlibs/x86_64/5.14/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/x86_64/5.16/udp.d b/dlibs/x86_64/5.16/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/x86_64/5.16/udp.d
> +++ b/dlibs/x86_64/5.16/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/x86_64/5.2/udp.d b/dlibs/x86_64/5.2/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/x86_64/5.2/udp.d
> +++ b/dlibs/x86_64/5.2/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/x86_64/5.6/udp.d b/dlibs/x86_64/5.6/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/x86_64/5.6/udp.d
> +++ b/dlibs/x86_64/5.6/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/x86_64/6.1/udp.d b/dlibs/x86_64/6.1/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/x86_64/6.1/udp.d
> +++ b/dlibs/x86_64/6.1/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/dlibs/x86_64/6.10/udp.d b/dlibs/x86_64/6.10/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/dlibs/x86_64/6.10/udp.d
> +++ b/dlibs/x86_64/6.10/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/libdtrace/Build b/libdtrace/Build
> index 3540d1c1..722f787d 100644
> --- a/libdtrace/Build
> +++ b/libdtrace/Build
> @@ -59,6 +59,7 @@ libdtrace-build_SOURCES = dt_aggregate.c \
>   			  dt_prov_sdt.c \
>   			  dt_prov_syscall.c \
>   			  dt_prov_tcp.c \
> +			  dt_prov_udp.c \
>   			  dt_prov_uprobe.c \
>   			  dt_provider.c \
>   			  dt_provider_sdt.c \
> @@ -120,6 +121,7 @@ dt_prov_sched.c_CFLAGS := -Wno-pedantic
>   dt_prov_sdt.c_CFLAGS := -Wno-pedantic
>   dt_prov_syscall.c_CFLAGS := -Wno-pedantic
>   dt_prov_tcp.c_CFLAGS := -Wno-pedantic
> +dt_prov_udp.c_CFLAGS := -Wno-pedantic
>   dt_prov_uprobe.c_CFLAGS := -Wno-pedantic
>   dt_debug.c_CFLAGS := -Wno-prio-ctor-dtor
>   
> diff --git a/libdtrace/dt_prov_udp.c b/libdtrace/dt_prov_udp.c
> new file mode 100644
> index 00000000..33a975a5
> --- /dev/null
> +++ b/libdtrace/dt_prov_udp.c
> @@ -0,0 +1,170 @@
> +/*
> + * Oracle Linux DTrace.
> + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
> + * Licensed under the Universal Permissive License v 1.0 as shown at
> + * http://oss.oracle.com/licenses/upl.
> + *
> + * The 'udp' SDT provider for DTrace-specific probes.
> + */
> +#include <assert.h>
> +#include <errno.h>
> +#include <netinet/in.h>
> +
> +#include "dt_dctx.h"
> +#include "dt_cg.h"
> +#include "dt_provider_sdt.h"
> +#include "dt_probe.h"
> +
> +static const char		prvname[] = "udp";
> +static const char		modname[] = "vmlinux";
> +
> +enum {
> +	NET_PROBE_OUTBOUND = 0,
> +	NET_PROBE_INBOUND,
> +};
> +
> +static probe_dep_t	probes[] = {
> +	{ "receive",
> +	  DTRACE_PROBESPEC_NAME,	"rawfbt::udp_queue_rcv_skb:entry" },
> +	{ "receive",
> +	  DTRACE_PROBESPEC_NAME,	"rawfbt::udpv6_queue_rcv_skb:entry" },
> +	{ "send",
> +	  DTRACE_PROBESPEC_NAME,	"rawfbt::ip_send_skb:entry" },
> +	{ "send",
> +	  DTRACE_PROBESPEC_NAME,	"rawfbt::ip6_send_skb:entry" },
> +	{ NULL, }
> +};
> +
> +static probe_arg_t probe_args[] = {
> +
> +	{ "receive", 0, { 0, 0, "struct sk_buff *", "pktinfo_t *" } },
> +	{ "receive", 1, { 1, 0, "struct sock *", "csinfo_t *" } },
> +	{ "receive", 2, { 2, 0, "void_ip_t *", "ipinfo_t *" } },
> +	{ "receive", 3, { 3, 0, "struct udp_sock *", "udpsinfo_t *" } },
> +	{ "receive", 4, { 4, 0, "struct udphdr *", "udpinfo_t *" } },
> +
> +	{ "send", 0, { 0, 0, "struct sk_buff *", "pktinfo_t *" } },
> +	{ "send", 1, { 1, 0, "struct sock *", "csinfo_t *" } },
> +	{ "send", 2, { 2, 0, "void_ip_t *", "ipinfo_t *" } },
> +	{ "send", 3, { 3, 0, "struct udp_sock *", "udpsinfo_t *" } },
> +	{ "send", 4, { 4, 0, "struct udphdr *", "udpinfo_t *" } },
> +
> +	{ NULL, }
> +};
> +
> +static const dtrace_pattr_t	pattr = {
> +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
> +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
> +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
> +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
> +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
> +};
> +
> +/*
> + * Provide all the "udp" SDT probes.
> + */
> +static int populate(dtrace_hdl_t *dtp)
> +{
> +	return dt_sdt_populate(dtp, prvname, modname, &dt_udp, &pattr,
> +			       probe_args, probes);
> +}
> +
> +/*
> + * Generate a BPF trampoline for a SDT probe.
> + *
> + * The trampoline function is called when a SDT probe triggers, and it must
> + * satisfy the following prototype:
> + *
> + *	int dt_udp(void *data)
> + *
> + * The trampoline will populate a dt_dctx_t struct and then call the function
> + * that implements the compiled D clause.  It returns the value that it gets
> + * back from that function.
> + */
> +static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
> +{
> +	dt_irlist_t	*dlp = &pcb->pcb_ir;
> +	dt_probe_t	*prp = pcb->pcb_probe;
> +	dt_probe_t	*uprp = pcb->pcb_parent_probe;
> +	int		skbarg = 1;
> +	int		direction;
> +
> +	/*
> +	 * We construct the udp::: probe arguments as follows:
> +	 *      arg0 = skb
> +	 *      arg1 = sk
> +	 *      arg2 = ip_hdr(skb) [if available]
> +	 *      arg3 = sk [struct udp_sock *]
> +	 *      arg4 = udp_hdr(skb)
> +	 *      arg5 = NET_PROBE_INBOUND (0x1) | NET_PROBE_OUTBOUND (0x0)
> +	 * arg5 never makes it into supported args[], it is simply set to
> +	 * help inform translators about whether it is an inbound/outbound probe
> +	 */
> +
> +	if (strcmp(prp->desc->prb, "receive") == 0) {
> +		direction = NET_PROBE_INBOUND;
> +		/* get sk from arg0, store in arg3 */
> +		emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_6, BPF_REG_7, DMST_ARG(0)));
> +		emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_6, 0, exitlbl));
> +		emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(3), BPF_REG_6));
> +	} else {
> +		if (strcmp(uprp->desc->fun, "ip6_send_skb") == 0)
> +			skbarg = 0;
> +		direction = NET_PROBE_OUTBOUND;
> +		emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_6, BPF_REG_7, DMST_ARG(skbarg)));
> +		/* get sk from skb->sk, store in arg3 */
> +		dt_cg_tramp_get_member(pcb, "struct sk_buff", BPF_REG_6, "sk");
> +		emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_0, 0, exitlbl));
> +		emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(3), BPF_REG_0));
> +	}
> +
> +	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_6, BPF_REG_7, DMST_ARG(skbarg)));
> +	emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(0), BPF_REG_6));
> +
> +	/* Now get sk from arg3, store it in arg1 and ensure it is UDP */
> +	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_6, BPF_REG_7, DMST_ARG(3)));
> +	emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(1), BPF_REG_0));
> +	dt_cg_tramp_get_member(pcb, "struct sock", BPF_REG_6,
> +			       "sk_protocol");
> +	emit(dlp, BPF_BRANCH_IMM(BPF_JNE, BPF_REG_0, IPPROTO_UDP, exitlbl));
> +
> +	/*
> +	 * ip_hdr(skb) =
> +	 *	skb_network_header(skb)	=	(include/linux/ip.h)
> +	 *	skb->head + skb->network_header	(include/linux/skbuff.h)
> +	 */
> +	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_6, BPF_REG_7, DMST_ARG(0)));
> +	dt_cg_tramp_get_member(pcb, "struct sk_buff", BPF_REG_6, "head");
> +	emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(2), BPF_REG_0));
> +
> +	dt_cg_tramp_get_member(pcb, "struct sk_buff", BPF_REG_6,
> +			       "network_header");
> +	emit(dlp, BPF_XADD_REG(BPF_DW, BPF_REG_7, DMST_ARG(2), BPF_REG_0));
> +
> +	/*
> +	 * udp_hdr(skb) =
> +	 *	skb_transport_header(skb) =		(include/linux/ip.h)
> +	 *	skb->head + skb->transport_header	(include/linux/skbuff.h)
> +	 */
> +	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_6, BPF_REG_7, DMST_ARG(0)));
> +	dt_cg_tramp_get_member(pcb, "struct sk_buff", BPF_REG_6, "head");
> +	emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(4), BPF_REG_0));
> +	dt_cg_tramp_get_member(pcb, "struct sk_buff", BPF_REG_6,
> +			       "transport_header");
> +	emit(dlp, BPF_XADD_REG(BPF_DW, BPF_REG_7, DMST_ARG(4), BPF_REG_0));
> +
> +	emit(dlp, BPF_STORE_IMM(BPF_DW, BPF_REG_7, DMST_ARG(5), direction));
> +
> +	return 0;
> +}
> +
> +dt_provimpl_t	dt_udp = {
> +	.name		= prvname,
> +	.prog_type	= BPF_PROG_TYPE_UNSPEC,
> +	.populate	= &populate,
> +	.enable		= &dt_sdt_enable,
> +	.load_prog	= &dt_bpf_prog_load,
> +	.trampoline	= &trampoline,
> +	.probe_info	= &dt_sdt_probe_info,
> +	.destroy	= &dt_sdt_destroy,
> +};
> diff --git a/libdtrace/dt_provider.c b/libdtrace/dt_provider.c
> index b9a7196b..848fdc13 100644
> --- a/libdtrace/dt_provider.c
> +++ b/libdtrace/dt_provider.c
> @@ -41,6 +41,7 @@ const dt_provimpl_t *dt_providers[] = {
>   	&dt_sdt,
>   	&dt_syscall,
>   	&dt_tcp,
> +	&dt_udp,
>   	&dt_uprobe,
>   	&dt_usdt,
>   	NULL
> diff --git a/libdtrace/dt_provider.h b/libdtrace/dt_provider.h
> index 9d60e5ec..dc126671 100644
> --- a/libdtrace/dt_provider.h
> +++ b/libdtrace/dt_provider.h
> @@ -89,6 +89,7 @@ extern dt_provimpl_t dt_sched;
>   extern dt_provimpl_t dt_sdt;
>   extern dt_provimpl_t dt_syscall;
>   extern dt_provimpl_t dt_tcp;
> +extern dt_provimpl_t dt_udp;
>   extern dt_provimpl_t dt_uprobe;
>   extern dt_provimpl_t dt_usdt;
>   
> diff --git a/libdtrace/udp.d b/libdtrace/udp.d
> index 0e44ed64..e5a0fc9b 100644
> --- a/libdtrace/udp.d
> +++ b/libdtrace/udp.d
> @@ -7,6 +7,7 @@
>   
>   #pragma D depends_on module vmlinux
>   #pragma D depends_on library net.d
> +#pragma D depends_on library ip.d
>   #pragma D depends_on provider udp
>   
>   /*
> @@ -48,24 +49,24 @@ translator udpsinfo_t < struct udp_sock *S > {
>   	 */
>   	udps_addr = (uintptr_t)S;
>   	udps_lport = arg4 ?
> -	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->source) :
> +	    (arg5 == NET_PROBE_OUTBOUND ? ntohs(((struct udphdr *)arg4)->source) :
>   	    ntohs(((struct udphdr *)arg4)->dest)) : 0;
>   	udps_rport = arg4 ?
>   	    (probename == "send" ? ntohs(((struct udphdr *)arg4)->dest) :
>   	    ntohs(((struct udphdr *)arg4)->source)) : 0;
>   	udps_laddr = arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->saddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->saddr :
>   	    &((struct iphdr *)arg2)->daddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->saddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->saddr :
>   	    &((struct ipv6hdr *)arg2)->daddr) :
>   	    "<unknown>";
>   	udps_raddr =
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 4 ?
> -            inet_ntoa(probename == "send" ? &((struct iphdr *)arg2)->daddr :
> +            inet_ntoa(arg5 == NET_PROBE_OUTBOUND ? &((struct iphdr *)arg2)->daddr :
>   	    &((struct iphdr *)arg2)->saddr) :
>   	    arg2 && *(uint8_t *)arg2 >> 4 == 6 ?
> -	    inet_ntoa6(probename == "send" ? &((struct ipv6hdr *)arg2)->daddr :
> +	    inet_ntoa6(arg5 == NET_PROBE_OUTBOUND ? &((struct ipv6hdr *)arg2)->daddr :
>   	    &((struct ipv6hdr *)arg2)->saddr) :
>   	    "<unknown>";
>   };
> diff --git a/test/unittest/dtrace-util/tst.ListProbes.r b/test/unittest/dtrace-util/tst.ListProbes.r
> index ad557253..a1e185d4 100644
> --- a/test/unittest/dtrace-util/tst.ListProbes.r
> +++ b/test/unittest/dtrace-util/tst.ListProbes.r
> @@ -12,3 +12,4 @@ sched
>   sdt
>   syscall
>   tcp
> +udp
> diff --git a/test/unittest/dtrace-util/tst.ListProbes.sh b/test/unittest/dtrace-util/tst.ListProbes.sh
> index a747a045..744bb8ad 100755
> --- a/test/unittest/dtrace-util/tst.ListProbes.sh
> +++ b/test/unittest/dtrace-util/tst.ListProbes.sh
> @@ -70,6 +70,7 @@ $dtrace $dt_flags -l \
>       $2 == "sdt"      { mycheck($2, $1,   600,   6000); next }
>       $2 == "syscall"  { mycheck($2, $1,   300,   3000); next }
>       $2 == "tcp"      { mycheck($2, $1,     8,      8); next }
> +    $2 == "udp"      { mycheck($2, $1,     2,      2); next }	
>       # nothing for usdt
>   
>       # Unrecognized line.
> diff --git a/test/unittest/udp/test.x b/test/unittest/udp/test.x
> index d3d7a598..2ff8d675 100755
> --- a/test/unittest/udp/test.x
> +++ b/test/unittest/udp/test.x
> @@ -1,14 +1,10 @@
>   #!/bin/bash
>   #
>   # Oracle Linux DTrace.
> -# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
> +# Copyright (c) 2017, 2025 Oracle and/or its affiliates. All rights reserved.
>   # Licensed under the Universal Permissive License v 1.0 as shown at
>   # http://oss.oracle.com/licenses/upl.
>   
> -if ! check_provider udp; then
> -        echo "Could not load udp provider"
> -        exit 1
> -fi
>   if ! perl -MIO::Socket::IP -e 'exit(0);' 2>/dev/null; then
>   	exit 1
>   fi



More information about the DTrace-devel mailing list