Commit 4671f8510cc for php.net
commit 4671f8510cc2d975241799d77c766673e8a1660f
Author: David Carlier <devnexen@gmail.com>
Date: Mon Mar 31 22:38:42 2025 +0100
ext/sockets: UDP_SEGMENT support.
UDP segmentation offload is an optimisation attempt by sending multiple
large enough datagrams over UDP which reduces syscalls as by default,
they have to be broke down in small UDP packets, it is better if the
hardware supports it, other handed down to the software implementation.
close GH-18213
diff --git a/NEWS b/NEWS
index d0a1d30fc9e..be2005a98f0 100644
--- a/NEWS
+++ b/NEWS
@@ -208,6 +208,8 @@ PHP NEWS
(David Carlier)
. Added IP_BINDANY for a socket to bind to any address. (David Carlier)
. Added SO_BUSY_POOL to reduce packets poll latency. (David Carlier)
+ - Added UDP_SEGMENT support to optimise multiple large datagrams over UDP
+ if the kernel and hardware supports it. (David Carlier)
- Sodium:
. Fix overall theorical overflows on zend_string buffer allocations.
diff --git a/UPGRADING b/UPGRADING
index 67b6dcb8e75..400187a40f2 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -440,6 +440,7 @@ PHP 8.5 UPGRADE NOTES
. AF_PACKET (Linux only).
. IP_BINDANY (FreeBSD/NetBSD/OpenBSD only).
. SO_BUSY_POLL (Linux only).
+ . UDP_SEGMENT (Linux only).
========================================
11. Changes to INI File Handling
diff --git a/ext/sockets/config.m4 b/ext/sockets/config.m4
index 37f927a7818..f637c32b3b6 100644
--- a/ext/sockets/config.m4
+++ b/ext/sockets/config.m4
@@ -5,7 +5,7 @@ PHP_ARG_ENABLE([sockets],
if test "$PHP_SOCKETS" != "no"; then
AC_CHECK_FUNCS([hstrerror if_nametoindex if_indextoname sockatmark])
- AC_CHECK_HEADERS([sys/sockio.h linux/filter.h linux/if_packet.h linux/if_ether.h])
+ AC_CHECK_HEADERS([sys/sockio.h linux/filter.h linux/if_packet.h linux/if_ether.h linux/udp.h])
AC_DEFINE([HAVE_SOCKETS], [1],
[Define to 1 if the PHP extension 'sockets' is available.])
diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c
index 2d8b55c6b97..e3d5dc6c296 100644
--- a/ext/sockets/sockets.c
+++ b/ext/sockets/sockets.c
@@ -70,6 +70,9 @@
# if defined(HAVE_LINUX_IF_ETHER_H)
# include <linux/if_ether.h>
# endif
+# if defined(HAVE_LINUX_UDP_H)
+# include <linux/udp.h>
+# endif
#endif
#include <stddef.h>
@@ -2301,6 +2304,22 @@ PHP_FUNCTION(socket_set_option)
}
#endif
+#if defined(UDP_SEGMENT)
+ case UDP_SEGMENT: {
+ ov = zval_get_long(arg4);
+
+ // UDP segmentation offload maximum size or 0 to disable it
+ if (ov < 0 || ov > USHRT_MAX) {
+ zend_argument_value_error(4, "must be of between 0 and %u", USHRT_MAX);
+ RETURN_FALSE;
+ }
+
+ optlen = sizeof(ov);
+ opt_ptr = &ov;
+ break;
+ }
+#endif
+
default:
default_case:
ov = zval_get_long(arg4);
diff --git a/ext/sockets/sockets.stub.php b/ext/sockets/sockets.stub.php
index d647f46b80d..d94352e3628 100644
--- a/ext/sockets/sockets.stub.php
+++ b/ext/sockets/sockets.stub.php
@@ -2022,6 +2022,14 @@
const ETH_P_ALL = UNKNOWN;
#endif
+#ifdef UDP_SEGMENT
+/**
+ * @var int
+ * @cvalue UDP_SEGMENT
+ */
+const UDP_SEGMENT = UNKNOWN;
+#endif
+
/**
* @strict-properties
* @not-serializable
diff --git a/ext/sockets/sockets_arginfo.h b/ext/sockets/sockets_arginfo.h
index 45714fb2851..78f2212a518 100644
Binary files a/ext/sockets/sockets_arginfo.h and b/ext/sockets/sockets_arginfo.h differ
diff --git a/ext/sockets/tests/socket_cmsg_udp_segment.phpt b/ext/sockets/tests/socket_cmsg_udp_segment.phpt
new file mode 100644
index 00000000000..679b246ea9d
--- /dev/null
+++ b/ext/sockets/tests/socket_cmsg_udp_segment.phpt
@@ -0,0 +1,26 @@
+--TEST--
+UDP_SEGMENT setsockopt(), can't really test is as the kernel support might not be enabled.
+--EXTENSIONS--
+sockets
+--SKIPIF--
+<?php
+if (!defined('UDP_SEGMENT')) { die('skip UDP_SEGMENT is not defined'); }
+?>
+--FILE--
+<?php
+$src = socket_create(AF_UNIX, SOCK_DGRAM, 0);
+
+try {
+ socket_setopt($src, SOL_UDP, UDP_SEGMENT, -1);
+} catch (\ValueError $e) {
+ echo $e->getMessage(), PHP_EOL;
+}
+try {
+ socket_setopt($src, SOL_UDP, UDP_SEGMENT, 65536);
+} catch (\ValueError $e) {
+ echo $e->getMessage(), PHP_EOL;
+}
+?>
+--EXPECT--
+socket_setopt(): Argument #4 ($value) must be of between 0 and 65535
+socket_setopt(): Argument #4 ($value) must be of between 0 and 65535