summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS7
-rw-r--r--man/systemd.network.xml14
-rw-r--r--src/libsystemd-network/dhcp-internal.h4
-rw-r--r--src/libsystemd-network/dhcp-network.c18
-rw-r--r--src/libsystemd-network/fuzz-dhcp-client.c5
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c18
-rw-r--r--src/libsystemd-network/test-dhcp-client.c5
-rw-r--r--src/network/networkd-dhcp4.c42
-rw-r--r--src/network/networkd-dhcp4.h1
-rw-r--r--src/network/networkd-network-gperf.gperf1
-rw-r--r--src/network/networkd-network.h2
-rw-r--r--src/systemd/sd-dhcp-client.h3
12 files changed, 111 insertions, 9 deletions
diff --git a/NEWS b/NEWS
index 7e1e536060..4358d0c48e 100644
--- a/NEWS
+++ b/NEWS
@@ -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);