udev: add {Receive,Transmit}ChecksumOffload= settings

Closes #14661.
This commit is contained in:
Yu Watanabe 2020-01-27 19:49:25 +09:00
parent 53e1ba280f
commit bf2334c054
5 changed files with 50 additions and 25 deletions

View File

@ -612,6 +612,20 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>ReceiveChecksumOffload=</varname></term>
<listitem>
<para>Takes a boolean. If set to true, the hardware offload for checksumming of ingress
network packets is enabled. When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>TransmitChecksumOffload=</varname></term>
<listitem>
<para>Takes a boolean. If set to true, the hardware offload for checksumming of egress
network packets is enabled. When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>TCPSegmentationOffload=</varname></term>
<listitem>
@ -633,7 +647,7 @@
When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><varname>GenericReceiveOffload=</varname></term>
<listitem>
<para>Takes a boolean. If set to true, the Generic Receive Offload (GRO) is enabled.

View File

@ -50,6 +50,8 @@ DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort);
DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse Port setting");
static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {
[NET_DEV_FEAT_RX] = "rx-checksum",
[NET_DEV_FEAT_TX] = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */
[NET_DEV_FEAT_GSO] = "tx-generic-segmentation",
[NET_DEV_FEAT_GRO] = "rx-gro",
[NET_DEV_FEAT_LRO] = "rx-lro",
@ -498,22 +500,38 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st
return 0;
}
static int find_feature_index(struct ethtool_gstrings *strings, const char *feature) {
unsigned i;
static int set_features_bit(
const struct ethtool_gstrings *strings,
const char *feature,
bool flag,
struct ethtool_sfeatures *sfeatures) {
bool found = false;
for (i = 0; i < strings->len; i++) {
if (streq((char *) &strings->data[i * ETH_GSTRING_LEN], feature))
return i;
}
assert(strings);
assert(feature);
assert(sfeatures);
return -ENODATA;
for (size_t i = 0; i < strings->len; i++)
if (streq((char *) &strings->data[i * ETH_GSTRING_LEN], feature) ||
(endswith(feature, "-") && startswith((char *) &strings->data[i * ETH_GSTRING_LEN], feature))) {
size_t block, bit;
block = i / 32;
bit = i % 32;
sfeatures->features[block].valid |= 1 << bit;
SET_FLAG(sfeatures->features[block].requested, 1 << bit, flag);
found = true;
}
return found ? 0 : -ENODATA;
}
int ethtool_set_features(int *ethtool_fd, const char *ifname, int *features) {
_cleanup_free_ struct ethtool_gstrings *strings = NULL;
struct ethtool_sfeatures *sfeatures;
int block, bit, i, r;
struct ifreq ifr = {};
int i, r;
if (*ethtool_fd < 0) {
r = ethtool_connect_or_warn(ethtool_fd, true);
@ -531,27 +549,14 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, int *features) {
sfeatures->cmd = ETHTOOL_SFEATURES;
sfeatures->size = DIV_ROUND_UP(strings->len, 32U);
for (i = 0; i < _NET_DEV_FEAT_MAX; i++) {
for (i = 0; i < _NET_DEV_FEAT_MAX; i++)
if (features[i] != -1) {
r = find_feature_index(strings, netdev_feature_table[i]);
r = set_features_bit(strings, netdev_feature_table[i], features[i], sfeatures);
if (r < 0) {
log_warning_errno(r, "ethtool: could not find feature: %s", netdev_feature_table[i]);
log_warning_errno(r, "ethtool: could not find feature, ignoring: %s", netdev_feature_table[i]);
continue;
}
block = r / 32;
bit = r % 32;
sfeatures->features[block].valid |= 1 << bit;
if (features[i])
sfeatures->features[block].requested |= 1 << bit;
else
sfeatures->features[block].requested &= ~(1 << bit);
}
}
ifr.ifr_data = (void *) sfeatures;

View File

@ -32,6 +32,8 @@ typedef enum WakeOnLan {
} WakeOnLan;
typedef enum NetDevFeature {
NET_DEV_FEAT_RX,
NET_DEV_FEAT_TX,
NET_DEV_FEAT_GSO,
NET_DEV_FEAT_GRO,
NET_DEV_FEAT_LRO,

View File

@ -45,6 +45,8 @@ Link.Duplex, config_parse_duplex, 0,
Link.AutoNegotiation, config_parse_tristate, 0, offsetof(link_config, autonegotiation)
Link.WakeOnLan, config_parse_wol, 0, offsetof(link_config, wol)
Link.Port, config_parse_port, 0, offsetof(link_config, port)
Link.ReceiveChecksumOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_RX])
Link.TransmitChecksumOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TX])
Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_GSO])
Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO])
Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(link_config, features[NET_DEV_FEAT_TSO6])

View File

@ -26,6 +26,8 @@ Duplex=
AutoNegotiation=
WakeOnLan=
Port=
ReceiveChecksumOffload=
TransmitChecksumOffload=
GenericSegmentationOffload=
TCPSegmentationOffload=
TCP6SegmentationOffload=