1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

udev: make RxChannels= or friends also accept "max"

Follow-up for 406041b7de.

Also, this makes
- the settings accept an empty string,
- if the specified value is too large, also use the advertised maximum
  value.
- mention the range of the value in the man page.
This commit is contained in:
Yu Watanabe 2021-08-18 16:41:11 +09:00 committed by Lennart Poettering
parent bdbb61f69f
commit 0d341eccef
4 changed files with 90 additions and 181 deletions

View File

@ -710,58 +710,27 @@
</varlistentry>
<varlistentry>
<term><varname>RxChannels=</varname></term>
<listitem>
<para>Sets the number of receive channels (a number between 1 and 4294967295) .</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>TxChannels=</varname></term>
<listitem>
<para>Sets the number of transmit channels (a number between 1 and 4294967295).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>OtherChannels=</varname></term>
<listitem>
<para>Sets the number of other channels (a number between 1 and 4294967295).</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>CombinedChannels=</varname></term>
<listitem>
<para>Sets the number of combined set channels (a number between 1 and 4294967295).</para>
<para>Specifies the number of receive, transmit, other, or combined channels, respectively.
Takes an unsigned integer in the range 1…4294967295 or <literal>max</literal>. If set to
<literal>max</literal>, the advertised maximum value of the hardware will be used. When
unset, the number will not be changed. Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RxBufferSize=</varname></term>
<listitem>
<para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets
in the NIC receive buffer. When unset, the kernel's default will be used. If set to
<literal>max</literal>, the hardware's advertised maximum size will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RxMiniBufferSize=</varname></term>
<listitem>
<para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets
in the NIC mini receive buffer. When unset, the kernel's default will be used. If set to
<literal>max</literal>, the hardware's advertised maximum size will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>RxJumboBufferSize=</varname></term>
<listitem>
<para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets
in the NIC jumbo receive buffer. When unset, the kernel's default will be used. If set to
<literal>max</literal>, the hardware's advertised maximum size will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>TxBufferSize=</varname></term>
<listitem>
<para>Takes an integer or <literal>max</literal>. Specifies the maximum number of pending packets
in the NIC transmit buffer. When unset, the kernel's default will be used. If set to
<literal>max</literal>, the hardware's advertised maximum size will be used.</para>
<para>Specifies the maximum number of pending packets in the NIC receive buffer, mini receive
buffer, jumbo receive buffer, or transmit buffer, respectively. Takes an unsigned integer in
the range 1…4294967295 or <literal>max</literal>. If set to <literal>max</literal>, the
advertised maximum value of the hardware will be used. When unset, the number will not be
changed. Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -329,6 +329,17 @@ int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct et
dest = _v; \
} while(false)
#define UPDATE_WITH_MAX(dest, max, val, updated) \
do { \
typeof(dest) _v = (val); \
typeof(dest) _max = (max); \
if (_v == 0 || _v > _max) \
_v = _max; \
if (dest != _v) \
updated = true; \
dest = _v; \
} while(false)
int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) {
struct ethtool_wolinfo ecmd = {
.cmd = ETHTOOL_GWOL,
@ -382,10 +393,10 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde
assert(ifname);
assert(ring);
if (!ring->rx_pending_set &&
!ring->rx_mini_pending_set &&
!ring->rx_jumbo_pending_set &&
!ring->tx_pending_set)
if (!ring->rx.set &&
!ring->rx_mini.set &&
!ring->rx_jumbo.set &&
!ring->tx.set)
return 0;
r = ethtool_connect(ethtool_fd);
@ -398,25 +409,17 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde
if (r < 0)
return -errno;
if (ring->rx_pending_set)
UPDATE(ecmd.rx_pending,
ring->rx_pending == 0 ? ecmd.rx_max_pending : ring->rx_pending,
need_update);
if (ring->rx.set)
UPDATE_WITH_MAX(ecmd.rx_pending, ecmd.rx_max_pending, ring->rx.value, need_update);
if (ring->rx_mini_pending_set)
UPDATE(ecmd.rx_mini_pending,
ring->rx_mini_pending == 0 ? ecmd.rx_mini_max_pending : ring->rx_mini_pending,
need_update);
if (ring->rx_mini.set)
UPDATE_WITH_MAX(ecmd.rx_mini_pending, ecmd.rx_mini_max_pending, ring->rx_mini.value, need_update);
if (ring->rx_jumbo_pending_set)
UPDATE(ecmd.rx_jumbo_pending,
ring->rx_jumbo_pending == 0 ? ecmd.rx_jumbo_max_pending : ring->rx_jumbo_pending,
need_update);
if (ring->rx_jumbo.set)
UPDATE_WITH_MAX(ecmd.rx_jumbo_pending, ecmd.rx_jumbo_max_pending, ring->rx_jumbo.value, need_update);
if (ring->tx_pending_set)
UPDATE(ecmd.tx_pending,
ring->tx_pending == 0 ? ecmd.tx_max_pending : ring->tx_pending,
need_update);
if (ring->tx.set)
UPDATE_WITH_MAX(ecmd.tx_pending, ecmd.tx_max_pending, ring->tx.value, need_update);
if (!need_update)
return 0;
@ -842,10 +845,10 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha
assert(ifname);
assert(channels);
if (!channels->rx_count_set &&
!channels->tx_count_set &&
!channels->other_count_set &&
!channels->combined_count_set)
if (!channels->rx.set &&
!channels->tx.set &&
!channels->other.set &&
!channels->combined.set)
return 0;
r = ethtool_connect(fd);
@ -858,17 +861,17 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha
if (r < 0)
return -errno;
if (channels->rx_count_set)
UPDATE(ecmd.rx_count, channels->rx_count, need_update);
if (channels->rx.set)
UPDATE_WITH_MAX(ecmd.rx_count, ecmd.max_rx, channels->rx.value, need_update);
if (channels->tx_count_set)
UPDATE(ecmd.tx_count, channels->tx_count, need_update);
if (channels->tx.set)
UPDATE_WITH_MAX(ecmd.tx_count, ecmd.max_tx, channels->tx.value, need_update);
if (channels->other_count_set)
UPDATE(ecmd.other_count, channels->other_count, need_update);
if (channels->other.set)
UPDATE_WITH_MAX(ecmd.other_count, ecmd.max_other, channels->other.value, need_update);
if (channels->combined_count_set)
UPDATE(ecmd.combined_count, channels->combined_count, need_update);
if (channels->combined.set)
UPDATE_WITH_MAX(ecmd.combined_count, ecmd.max_combined, channels->combined.value, need_update);
if (!need_update)
return 0;
@ -927,57 +930,6 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au
return 0;
}
int config_parse_channel(
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) {
netdev_channels *channels = data;
uint32_t k;
int r;
assert(filename);
assert(section);
assert(lvalue);
assert(rvalue);
assert(data);
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse channel value for %s=, ignoring: %s", lvalue, rvalue);
return 0;
}
if (k < 1) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s= value, ignoring: %s", lvalue, rvalue);
return 0;
}
if (streq(lvalue, "RxChannels")) {
channels->rx_count = k;
channels->rx_count_set = true;
} else if (streq(lvalue, "TxChannels")) {
channels->tx_count = k;
channels->tx_count_set = true;
} else if (streq(lvalue, "OtherChannels")) {
channels->other_count = k;
channels->other_count_set = true;
} else if (streq(lvalue, "CombinedChannels")) {
channels->combined_count = k;
channels->combined_count_set = true;
}
return 0;
}
int config_parse_advertise(
const char *unit,
const char *filename,
@ -1033,7 +985,7 @@ int config_parse_advertise(
}
}
int config_parse_nic_buffer_size(
int config_parse_ring_buffer_or_channel(
const char *unit,
const char *filename,
unsigned line,
@ -1045,7 +997,7 @@ int config_parse_nic_buffer_size(
void *data,
void *userdata) {
netdev_ring_param *ring = data;
u32_opt *dst = data;
uint32_t k;
int r;
@ -1055,36 +1007,32 @@ int config_parse_nic_buffer_size(
assert(rvalue);
assert(data);
if (streq(rvalue, "max"))
k = 0;
else {
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse interface buffer value, ignoring: %s", rvalue);
return 0;
}
if (k < 1) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s= value, ignoring: %s", lvalue, rvalue);
return 0;
}
if (isempty(rvalue)) {
dst->value = 0;
dst->set = false;
return 0;
}
if (streq(lvalue, "RxBufferSize")) {
ring->rx_pending = k;
ring->rx_pending_set = true;
} else if (streq(lvalue, "RxMiniBufferSize")) {
ring->rx_mini_pending = k;
ring->rx_mini_pending_set = true;
} else if (streq(lvalue, "RxJumboBufferSize")) {
ring->rx_jumbo_pending = k;
ring->rx_jumbo_pending_set = true;
} else if (streq(lvalue, "TxBufferSize")) {
ring->tx_pending = k;
ring->tx_pending_set = true;
if (streq(rvalue, "max")) {
dst->value = 0;
dst->set = true;
return 0;
}
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse %s=, ignoring: %s", lvalue, rvalue);
return 0;
}
if (k < 1) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Invalid %s= value, ignoring: %s", lvalue, rvalue);
return 0;
}
dst->value = k;
dst->set = true;
return 0;
}

View File

@ -57,30 +57,23 @@ struct ethtool_link_usettings {
} link_modes;
};
typedef struct netdev_channels {
uint32_t rx_count;
uint32_t tx_count;
uint32_t other_count;
uint32_t combined_count;
typedef struct u32_opt {
uint32_t value; /* a value of 0 indicates the hardware advertised maximum should be used.*/
bool set;
} u32_opt;
bool rx_count_set;
bool tx_count_set;
bool other_count_set;
bool combined_count_set;
typedef struct netdev_channels {
u32_opt rx;
u32_opt tx;
u32_opt other;
u32_opt combined;
} netdev_channels;
typedef struct netdev_ring_param {
/* For any of the 4 following settings, a value of 0 indicates the hardware advertised maximum should
* be used. */
uint32_t rx_pending;
uint32_t rx_mini_pending;
uint32_t rx_jumbo_pending;
uint32_t tx_pending;
bool rx_pending_set;
bool rx_mini_pending_set;
bool rx_jumbo_pending_set;
bool tx_pending_set;
u32_opt rx;
u32_opt rx_mini;
u32_opt rx_jumbo;
u32_opt tx;
} netdev_ring_param;
int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret);
@ -111,6 +104,5 @@ enum ethtool_link_mode_bit_indices ethtool_link_mode_bit_from_string(const char
CONFIG_PARSER_PROTOTYPE(config_parse_duplex);
CONFIG_PARSER_PROTOTYPE(config_parse_wol);
CONFIG_PARSER_PROTOTYPE(config_parse_port);
CONFIG_PARSER_PROTOTYPE(config_parse_channel);
CONFIG_PARSER_PROTOTYPE(config_parse_advertise);
CONFIG_PARSER_PROTOTYPE(config_parse_nic_buffer_size);
CONFIG_PARSER_PROTOTYPE(config_parse_ring_buffer_or_channel);

View File

@ -58,15 +58,15 @@ Link.TCP6SegmentationOffload, config_parse_tristate, 0,
Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0
Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_GRO])
Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_LRO])
Link.RxChannels, config_parse_channel, 0, offsetof(LinkConfig, channels)
Link.TxChannels, config_parse_channel, 0, offsetof(LinkConfig, channels)
Link.OtherChannels, config_parse_channel, 0, offsetof(LinkConfig, channels)
Link.CombinedChannels, config_parse_channel, 0, offsetof(LinkConfig, channels)
Link.RxChannels, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, channels.rx)
Link.TxChannels, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, channels.tx)
Link.OtherChannels, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, channels.other)
Link.CombinedChannels, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, channels.combined)
Link.Advertise, config_parse_advertise, 0, offsetof(LinkConfig, advertise)
Link.RxBufferSize, config_parse_nic_buffer_size, 0, offsetof(LinkConfig, ring)
Link.RxMiniBufferSize, config_parse_nic_buffer_size, 0, offsetof(LinkConfig, ring)
Link.RxJumboBufferSize, config_parse_nic_buffer_size, 0, offsetof(LinkConfig, ring)
Link.TxBufferSize, config_parse_nic_buffer_size, 0, offsetof(LinkConfig, ring)
Link.RxBufferSize, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, ring.rx)
Link.RxMiniBufferSize, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, ring.rx_mini)
Link.RxJumboBufferSize, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, ring.rx_jumbo)
Link.TxBufferSize, config_parse_ring_buffer_or_channel, 0, offsetof(LinkConfig, ring.tx)
Link.RxFlowControl, config_parse_tristate, 0, offsetof(LinkConfig, rx_flow_control)
Link.TxFlowControl, config_parse_tristate, 0, offsetof(LinkConfig, tx_flow_control)
Link.AutoNegotiationFlowControl, config_parse_tristate, 0, offsetof(LinkConfig, autoneg_flow_control)