diff options
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | man/systemd.network.xml | 14 | ||||
-rw-r--r-- | src/libsystemd-network/dhcp-internal.h | 4 | ||||
-rw-r--r-- | src/libsystemd-network/dhcp-network.c | 18 | ||||
-rw-r--r-- | src/libsystemd-network/fuzz-dhcp-client.c | 5 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp-client.c | 18 | ||||
-rw-r--r-- | src/libsystemd-network/test-dhcp-client.c | 5 | ||||
-rw-r--r-- | src/network/networkd-dhcp4.c | 42 | ||||
-rw-r--r-- | src/network/networkd-dhcp4.h | 1 | ||||
-rw-r--r-- | src/network/networkd-network-gperf.gperf | 1 | ||||
-rw-r--r-- | src/network/networkd-network.h | 2 | ||||
-rw-r--r-- | src/systemd/sd-dhcp-client.h | 3 |
12 files changed, 111 insertions, 9 deletions
@@ -48,6 +48,13 @@ CHANGES WITH 253 in spe: * systemd-fstab-generator now supports x-systemd.makefs option for /sysroot (in the initrd). + * The [DHCPv4] section in .network file gained new SocketPriority= + setting that assigns the Linux socket priority used by the DHCPv4 + raw socket. Can be used in conjuntion with the EgressQOSMaps=setting in + [VLAN] section of .netdev file to send the desired ethernet 802.1Q frame + priority for DHCPv4 initial packets. This cannot be achieved with + netfilter mangle tables because of the raw socket bypass. + Changes in udev: * The new net naming scheme "v253" has been introduced. In the new diff --git a/man/systemd.network.xml b/man/systemd.network.xml index ccdbc49b1d..daa2c2e167 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1890,6 +1890,20 @@ allow my_server_t localnet_peer_t:peer recv;</programlisting> </listitem> </varlistentry> + <varlistentry> + <term><varname>SocketPriority=</varname></term> + <listitem> + <para>The Linux socket option <constant>SO_PRIORITY</constant> applied to the raw IP socket used for + initial DHCPv4 messages. Unset by default. Usual values range from 0 to 6. + More details about <constant>SO_PRIORITY</constant> socket option in + <citerefentry project='man-pages'><refentrytitle>socket</refentrytitle><manvolnum>7</manvolnum></citerefentry>. + Can be used in conjunction with [VLAN] section <varname>EgressQOSMaps=</varname> setting of .netdev + file to set the 802.1Q VLAN ethernet tagged header priority, see + <citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>. + </para> + </listitem> + </varlistentry> + <!-- How to use the DHCP lease --> <varlistentry> diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h index a311d1d5b9..5a7308c5ac 100644 --- a/src/libsystemd-network/dhcp-internal.h +++ b/src/libsystemd-network/dhcp-internal.h @@ -40,7 +40,9 @@ int dhcp_network_bind_raw_socket( const struct hw_addr_data *hw_addr, const struct hw_addr_data *bcast_addr, uint16_t arp_type, - uint16_t port); + uint16_t port, + bool so_priority_set, + int so_priority); int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type); int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len); diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c index 4e4b1ccb75..9137efa3ee 100644 --- a/src/libsystemd-network/dhcp-network.c +++ b/src/libsystemd-network/dhcp-network.c @@ -25,7 +25,9 @@ static int _bind_raw_socket( const struct hw_addr_data *hw_addr, const struct hw_addr_data *bcast_addr, uint16_t arp_type, - uint16_t port) { + uint16_t port, + bool so_priority_set, + int so_priority) { assert(ifindex > 0); assert(link); @@ -113,6 +115,12 @@ static int _bind_raw_socket( if (r < 0) return -errno; + if (so_priority_set) { + r = setsockopt_int(s, SOL_SOCKET, SO_PRIORITY, so_priority); + if (r < 0) + return r; + } + link->ll = (struct sockaddr_ll) { .sll_family = AF_PACKET, .sll_protocol = htobe16(ETH_P_IP), @@ -137,7 +145,9 @@ int dhcp_network_bind_raw_socket( const struct hw_addr_data *hw_addr, const struct hw_addr_data *bcast_addr, uint16_t arp_type, - uint16_t port) { + uint16_t port, + bool so_priority_set, + int so_priority) { static struct hw_addr_data default_eth_bcast = { .length = ETH_ALEN, @@ -160,13 +170,13 @@ int dhcp_network_bind_raw_socket( return _bind_raw_socket(ifindex, link, xid, hw_addr, (bcast_addr && !hw_addr_is_null(bcast_addr)) ? bcast_addr : &default_eth_bcast, - arp_type, port); + arp_type, port, so_priority_set, so_priority); case ARPHRD_INFINIBAND: return _bind_raw_socket(ifindex, link, xid, &HW_ADDR_NULL, (bcast_addr && !hw_addr_is_null(bcast_addr)) ? bcast_addr : &default_ib_bcast, - arp_type, port); + arp_type, port, so_priority_set, so_priority); default: return -EINVAL; } diff --git a/src/libsystemd-network/fuzz-dhcp-client.c b/src/libsystemd-network/fuzz-dhcp-client.c index a9cfba90e3..d2bbf660b0 100644 --- a/src/libsystemd-network/fuzz-dhcp-client.c +++ b/src/libsystemd-network/fuzz-dhcp-client.c @@ -16,7 +16,10 @@ int dhcp_network_bind_raw_socket( uint32_t id, const struct hw_addr_data *hw_addr, const struct hw_addr_data *bcast_addr, - uint16_t arp_type, uint16_t port) { + uint16_t arp_type, + uint16_t port, + bool so_priority_set, + int so_priority) { int fd; fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 48174e7c4b..f5abb1bf86 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -121,6 +121,8 @@ struct sd_dhcp_client { sd_dhcp_lease *lease; usec_t start_delay; int ip_service_type; + int socket_priority; + bool socket_priority_set; /* Ignore machine-ID when generating DUID. See dhcp_identifier_set_duid_en(). */ bool test_mode; @@ -647,6 +649,16 @@ int sd_dhcp_client_set_service_type(sd_dhcp_client *client, int type) { return 0; } +int sd_dhcp_client_set_socket_priority(sd_dhcp_client *client, int socket_priority) { + assert_return(client, -EINVAL); + assert_return(!sd_dhcp_client_is_running(client), -EBUSY); + + client->socket_priority_set = true; + client->socket_priority = socket_priority; + + return 0; +} + int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client *client, uint32_t fallback_lease_lifetime) { assert_return(client, -EINVAL); assert_return(!sd_dhcp_client_is_running(client), -EBUSY); @@ -1381,7 +1393,8 @@ static int client_start_delayed(sd_dhcp_client *client) { r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid, &client->hw_addr, &client->bcast_addr, - client->arp_type, client->port); + client->arp_type, client->port, + client->socket_priority_set, client->socket_priority); if (r < 0) { client_stop(client, r); return r; @@ -1429,7 +1442,8 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid, &client->hw_addr, &client->bcast_addr, - client->arp_type, client->port); + client->arp_type, client->port, + client->socket_priority_set, client->socket_priority); if (r < 0) { client_stop(client, r); return 0; diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c index 92b9b5b9bc..863649f6df 100644 --- a/src/libsystemd-network/test-dhcp-client.c +++ b/src/libsystemd-network/test-dhcp-client.c @@ -235,7 +235,10 @@ int dhcp_network_bind_raw_socket( uint32_t id, const struct hw_addr_data *_hw_addr, const struct hw_addr_data *_bcast_addr, - uint16_t arp_type, uint16_t port) { + uint16_t arp_type, + uint16_t port, + bool so_priority_set, + int so_priority) { if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0) return -errno; diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index e4005719d0..43850e1e95 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1499,6 +1499,12 @@ static int dhcp4_configure(Link *link) { return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set IP service type: %m"); } + if (link->network->dhcp_socket_priority_set) { + r = sd_dhcp_client_set_socket_priority(link->dhcp_client, link->network->dhcp_socket_priority); + if (r < 0) + return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set socket priority: %m"); + } + if (link->network->dhcp_fallback_lease_lifetime > 0) { r = sd_dhcp_client_set_fallback_lease_lifetime(link->dhcp_client, link->network->dhcp_fallback_lease_lifetime); if (r < 0) @@ -1701,6 +1707,42 @@ int config_parse_dhcp_ip_service_type( return 0; } +int config_parse_dhcp_socket_priority( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = ASSERT_PTR(data); + int a, r; + + assert(lvalue); + assert(rvalue); + + if (isempty(rvalue)) { + network->dhcp_socket_priority_set = false; + return 0; + } + + r = safe_atoi(rvalue, &a); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to parse socket priority, ignoring: %s", rvalue); + return 0; + } + + network->dhcp_socket_priority_set = true; + network->dhcp_socket_priority = a; + + return 0; +} + int config_parse_dhcp_fallback_lease_lifetime( const char *unit, const char *filename, diff --git a/src/network/networkd-dhcp4.h b/src/network/networkd-dhcp4.h index 1d30cd15df..0f14e07943 100644 --- a/src/network/networkd-dhcp4.h +++ b/src/network/networkd-dhcp4.h @@ -29,6 +29,7 @@ int link_request_dhcp4_client(Link *link); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_client_identifier); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_max_attempts); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_ip_service_type); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_socket_priority); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_mud_url); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_fallback_lease_lifetime); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_label); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 762eef5b91..c205e56c62 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -243,6 +243,7 @@ DHCPv4.SendDecline, config_parse_bool, DHCPv4.DenyList, config_parse_in_addr_prefixes, AF_INET, offsetof(Network, dhcp_deny_listed_ip) DHCPv4.AllowList, config_parse_in_addr_prefixes, AF_INET, offsetof(Network, dhcp_allow_listed_ip) DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, dhcp_ip_service_type) +DHCPv4.SocketPriority, config_parse_dhcp_socket_priority, 0, 0 DHCPv4.SendOption, config_parse_dhcp_send_option, AF_INET, offsetof(Network, dhcp_client_send_options) DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options) DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu) diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 79e8ceb06b..09f0e9beea 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -130,6 +130,8 @@ struct Network { uint16_t dhcp_client_port; int dhcp_critical; int dhcp_ip_service_type; + int dhcp_socket_priority; + bool dhcp_socket_priority_set; bool dhcp_anonymize; bool dhcp_send_hostname; int dhcp_broadcast; diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index b200f17cbd..2b3f995769 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -309,6 +309,9 @@ int sd_dhcp_client_get_lease( int sd_dhcp_client_set_service_type( sd_dhcp_client *client, int type); +int sd_dhcp_client_set_socket_priority( + sd_dhcp_client *client, + int so_priority); int sd_dhcp_client_set_fallback_lease_lifetime( sd_dhcp_client *client, uint32_t fallback_lease_lifetime); |