From: Yu Watanabe Date: Sat, 2 May 2026 13:31:03 +0000 (+0900) Subject: socket-util: introduce tos_to_priority() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fa9b3b26c7421ebf39004094ecee0ca9bcea2bd9;p=thirdparty%2Fsystemd.git socket-util: introduce tos_to_priority() This maps from TOS, which can be used for setsockopt(IPPROTO_IP, IP_TOS), to socket priority, which can be used for setsockopt(SOL_SOCKET, SO_PRIORITY). With this, we can set priority like the following: ``` uint8_t tos = IPTOS_CLASS_CS6; setsockopt_int(fd, IPPROTO_IP, IP_TOS, tos); setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, tos_to_priority(tos)); ``` Co-authored with Google Gemini. --- diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 698aa69a4b0..2e0ee684ff9 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -1873,3 +1874,29 @@ void cmsg_close_all(struct msghdr *mh) { } } } + +int tos_to_priority(uint8_t tos) { + /* Map the IP Precedence (top 3 bits of the TOS field) to Linux internal packet priorities + * (TC_PRIO_*). This exactly mirrors the standard Linux kernel IP precedence-to-priority mapping + * (rt_tos2priority) to ensure consistent behavior when explicitly setting SO_PRIORITY. */ + switch (IPTOS_PREC(tos)) { + case IPTOS_PREC_NETCONTROL: /* 0xc0 (CS7) - Network Control. Used for infrastructure control (e.g., STP, keepalives). */ + case IPTOS_PREC_INTERNETCONTROL: /* 0xe0 (CS6) - Internetwork Control. Used for routing protocols (e.g., OSPF, BGP) and DHCP. */ + return TC_PRIO_CONTROL; + + case IPTOS_PREC_CRITIC_ECP: /* 0xa0 (CS5) - Critical. Used for delay-sensitive traffic like Voice over IP (VoIP). */ + case IPTOS_PREC_FLASHOVERRIDE: /* 0x80 (CS4) - Flash Override. Used for interactive video and multimedia. */ + return TC_PRIO_INTERACTIVE; + + case IPTOS_PREC_FLASH: /* 0x60 (CS3) - Flash. Used for broadcast video and call signaling (e.g., SIP). */ + case IPTOS_PREC_IMMEDIATE: /* 0x40 (CS2) - Immediate. Used for OAM (Operations, Administration, and Management) and transactional data. */ + return TC_PRIO_INTERACTIVE_BULK; + + case IPTOS_PREC_PRIORITY: /* 0x20 (CS1) - Priority. Used for background traffic and bulk data transfers. */ + return TC_PRIO_BULK; + + case IPTOS_PREC_ROUTINE: /* 0x00 (CS0) - Routine. Best effort traffic. */ + default: + return TC_PRIO_BESTEFFORT; + } +} diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 78b948ad461..208eb7ac077 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -270,3 +270,5 @@ int netlink_socket_get_multicast_groups(int fd, size_t *ret_len, uint32_t **ret_ int socket_get_cookie(int fd, uint64_t *ret); void cmsg_close_all(struct msghdr *mh); + +int tos_to_priority(uint8_t tos); diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index 090839ac068..713844b09b7 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include "alloc-util.h" @@ -530,4 +532,22 @@ TEST(getpeerpidref) { ASSERT_TRUE(!pidref_equal(&pidref0, &pidref_pid1)); } +TEST(tos_to_priority) { + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS7), TC_PRIO_CONTROL); + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS6), TC_PRIO_CONTROL); + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS5), TC_PRIO_INTERACTIVE); + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS4), TC_PRIO_INTERACTIVE); + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS3), TC_PRIO_INTERACTIVE_BULK); + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS2), TC_PRIO_INTERACTIVE_BULK); + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS1), TC_PRIO_BULK); + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS0), TC_PRIO_BESTEFFORT); + + /* check if lower bits are correctly filtered. */ + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS7 | IPTOS_LOWDELAY), TC_PRIO_CONTROL); + ASSERT_EQ(tos_to_priority(IPTOS_CLASS_CS1 | IPTOS_LOWCOST), TC_PRIO_BULK); + + ASSERT_EQ(tos_to_priority(0x00), TC_PRIO_BESTEFFORT); + ASSERT_EQ(tos_to_priority(0xff), TC_PRIO_CONTROL); +} + DEFINE_TEST_MAIN(LOG_DEBUG);