diff options
-rw-r--r-- | src/core/dbus-socket.c | 6 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 1 | ||||
-rw-r--r-- | src/core/load-fragment.c | 1 | ||||
-rw-r--r-- | src/core/load-fragment.h | 1 | ||||
-rw-r--r-- | src/core/socket.c | 46 | ||||
-rw-r--r-- | src/core/socket.h | 13 | ||||
-rw-r--r-- | src/shared/bus-unit-util.c | 3 |
7 files changed, 70 insertions, 1 deletions
diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c index 07d030adb3..a5d15d80cd 100644 --- a/src/core/dbus-socket.c +++ b/src/core/dbus-socket.c @@ -20,6 +20,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only); static BUS_DEFINE_PROPERTY_GET(property_get_fdname, "s", Socket, socket_fdname); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_timestamping, socket_timestamping, SocketTimestamping); static int property_get_listen( sd_bus *bus, @@ -106,6 +107,7 @@ const sd_bus_vtable bus_socket_vtable[] = { SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PassPacketInfo", "b", bus_property_get_bool, offsetof(Socket, pass_pktinfo), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Timestamping", "s", property_get_timestamping, offsetof(Socket, timestamping), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemoveOnStop", "b", bus_property_get_bool, offsetof(Socket, remove_on_stop), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Symlinks", "as", NULL, offsetof(Socket, symlinks), SD_BUS_VTABLE_PROPERTY_CONST), @@ -159,6 +161,7 @@ static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(fdname, fdname_is_valid); static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(ifname, ifname_valid); static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(ip_tos, "i", int32_t, int, "%" PRIi32, ip_tos_to_string_alloc); static BUS_DEFINE_SET_TRANSIENT_TO_STRING(socket_protocol, "i", int32_t, int, "%" PRIi32, socket_protocol_to_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(socket_timestamping, SocketTimestamping, socket_timestamping_from_string_harder); static int bus_socket_set_transient_property( Socket *s, @@ -210,6 +213,9 @@ static int bus_socket_set_transient_property( if (streq(name, "PassPacketInfo")) return bus_set_transient_bool(u, name, &s->pass_pktinfo, message, flags, error); + if (streq(name, "Timestamping")) + return bus_set_transient_socket_timestamping(u, name, &s->timestamping, message, flags, error); + if (streq(name, "ReusePort")) return bus_set_transient_bool(u, name, &s->reuse_port, message, flags, error); diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index b5ccf62ae0..063d8ba6b6 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -419,6 +419,7 @@ Socket.Broadcast, config_parse_bool, Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred) Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec) Socket.PassPacketInfo, config_parse_bool, 0, offsetof(Socket, pass_pktinfo) +Socket.Timestamping, config_parse_socket_timestamping, 0, offsetof(Socket, timestamping) Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion) Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port) Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 60c9a5f03a..0ab64e1708 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -140,6 +140,7 @@ DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares, cg_cpu_shares_parse, uint64_t, DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flags_from_string, unsigned long, "Failed to parse mount flag"); DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_numa_policy, mpol, int, -1, "Invalid NUMA policy type"); DEFINE_CONFIG_PARSE_ENUM(config_parse_status_unit_format, status_unit_format, StatusUnitFormat, "Failed to parse status unit format"); +DEFINE_CONFIG_PARSE_ENUM_FULL(config_parse_socket_timestamping, socket_timestamping_from_string_harder, SocketTimestamping, "Failed to parse timestamping precision"); int config_parse_unit_deps( const char *unit, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index fa4c1fb1a0..47036145c8 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -136,6 +136,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_crash_chvt); CONFIG_PARSER_PROTOTYPE(config_parse_timeout_abort); CONFIG_PARSER_PROTOTYPE(config_parse_swap_priority); CONFIG_PARSER_PROTOTYPE(config_parse_mount_images); +CONFIG_PARSER_PROTOTYPE(config_parse_socket_timestamping); /* gperf prototypes */ const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length); diff --git a/src/core/socket.c b/src/core/socket.c index f71fa34300..f045eed5b5 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -629,6 +629,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) { prefix, socket_fdname(s), prefix, yes_no(s->selinux_context_from_net)); + if (s->timestamping != SOCKET_TIMESTAMPING_OFF) + fprintf(f, + "%sTimestamping: %s\n", + prefix, socket_timestamping_to_string(s->timestamping)); + if (s->control_pid > 0) fprintf(f, "%sControl PID: "PID_FMT"\n", @@ -1051,6 +1056,14 @@ static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) { log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m"); } + if (s->timestamping != SOCKET_TIMESTAMPING_OFF) { + r = setsockopt_int(fd, SOL_SOCKET, + s->timestamping == SOCKET_TIMESTAMPING_NS ? SO_TIMESTAMPNS : SO_TIMESTAMP, + true); + if (r < 0) + log_unit_warning_errno(UNIT(s), r, "Failed to enable timestamping socket option, ignoring: %m"); + } + if (s->priority >= 0) { r = setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, s->priority); if (r < 0) @@ -3409,6 +3422,39 @@ static const char* const socket_result_table[_SOCKET_RESULT_MAX] = { DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult); +static const char* const socket_timestamping_table[_SOCKET_TIMESTAMPING_MAX] = { + [SOCKET_TIMESTAMPING_OFF] = "off", + [SOCKET_TIMESTAMPING_US] = "us", + [SOCKET_TIMESTAMPING_NS] = "ns", +}; + +DEFINE_STRING_TABLE_LOOKUP(socket_timestamping, SocketTimestamping); + +SocketTimestamping socket_timestamping_from_string_harder(const char *p) { + SocketTimestamping t; + int r; + + if (!p) + return _SOCKET_TIMESTAMPING_INVALID; + + t = socket_timestamping_from_string(p); + if (t >= 0) + return t; + + /* Let's alternatively support the various other aliases parse_time() accepts for ns and µs here, + * too. */ + if (streq(p, "nsec")) + return SOCKET_TIMESTAMPING_NS; + if (STR_IN_SET(p, "usec", "µs")) + return SOCKET_TIMESTAMPING_US; + + r = parse_boolean(p); + if (r < 0) + return _SOCKET_TIMESTAMPING_INVALID; + + return r ? SOCKET_TIMESTAMPING_NS : SOCKET_TIMESTAMPING_OFF; /* If boolean yes, default to ns accuracy */ +} + const UnitVTable socket_vtable = { .object_size = sizeof(Socket), .exec_context_offset = offsetof(Socket, exec_context), diff --git a/src/core/socket.h b/src/core/socket.h index cf475e2638..90839de9fa 100644 --- a/src/core/socket.h +++ b/src/core/socket.h @@ -58,6 +58,14 @@ typedef struct SocketPort { LIST_FIELDS(struct SocketPort, port); } SocketPort; +typedef enum SocketTimestamping { + SOCKET_TIMESTAMPING_OFF, + SOCKET_TIMESTAMPING_US, /* SO_TIMESTAMP */ + SOCKET_TIMESTAMPING_NS, /* SO_TIMESTAMPNS */ + _SOCKET_TIMESTAMPING_MAX, + _SOCKET_TIMESTAMPING_INVALID = -1, +} SocketTimestamping; + struct Socket { Unit meta; @@ -123,6 +131,7 @@ struct Socket { bool pass_cred; bool pass_sec; bool pass_pktinfo; + SocketTimestamping timestamping; /* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */ SocketAddressBindIPv6Only bind_ipv6_only; @@ -182,4 +191,8 @@ SocketResult socket_result_from_string(const char *s) _pure_; const char* socket_port_type_to_string(SocketPort *p) _pure_; SocketType socket_port_type_from_string(const char *p) _pure_; +const char* socket_timestamping_to_string(SocketTimestamping p) _const_; +SocketTimestamping socket_timestamping_from_string(const char *p) _pure_; +SocketTimestamping socket_timestamping_from_string_harder(const char *p) _pure_; + DEFINE_CAST(SOCKET, Socket); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 89e0c5bb95..79c2e0cf19 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -2037,7 +2037,8 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons "BindIPv6Only", "FileDescriptorName", "SocketUser", - "SocketGroup")) + "SocketGroup", + "Timestamping")) return bus_append_string(m, field, eq); if (streq(field, "Symlinks")) |