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

ethtool-util: apply tx-checksum-* features at last

NET_DEV_FEAT_TX matches multiple features. In the next commit, all
features whose strings start with "tx-checksum-" will be added.
To make them take precedence over NET_DEV_FEAT_TX, it will be applied
only when each explicit feature is not applied.
This commit is contained in:
Yu Watanabe 2021-09-15 01:48:59 +09:00
parent 008d3a370c
commit 7a4f203547
2 changed files with 54 additions and 5 deletions

View File

@ -71,13 +71,14 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse P
static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = { static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {
[NET_DEV_FEAT_RX] = "rx-checksum", [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_GSO] = "tx-generic-segmentation",
[NET_DEV_FEAT_GRO] = "rx-gro", [NET_DEV_FEAT_GRO] = "rx-gro",
[NET_DEV_FEAT_GRO_HW] = "rx-gro-hw", [NET_DEV_FEAT_GRO_HW] = "rx-gro-hw",
[NET_DEV_FEAT_LRO] = "rx-lro", [NET_DEV_FEAT_LRO] = "rx-lro",
[NET_DEV_FEAT_TSO] = "tx-tcp-segmentation", [NET_DEV_FEAT_TSO] = "tx-tcp-segmentation",
[NET_DEV_FEAT_TSO6] = "tx-tcp6-segmentation", [NET_DEV_FEAT_TSO6] = "tx-tcp6-segmentation",
[NET_DEV_FEAT_TX] = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */
}; };
static const char* const ethtool_link_mode_bit_table[] = { static const char* const ethtool_link_mode_bit_table[] = {
@ -515,6 +516,43 @@ static int set_features_bit(
const char *feature, const char *feature,
int flag) { int flag) {
assert(strings);
assert(gfeatures);
assert(sfeatures);
assert(feature);
if (flag < 0)
return 0;
for (uint32_t i = 0; i < strings->len; i++) {
uint32_t block, mask;
if (!strneq((const char*) &strings->data[i * ETH_GSTRING_LEN], feature, ETH_GSTRING_LEN))
continue;
block = i / 32;
mask = UINT32_C(1) << (i % 32);
if (!FLAGS_SET(gfeatures->features[block].available, mask) ||
FLAGS_SET(gfeatures->features[block].never_changed, mask))
return -EOPNOTSUPP;
sfeatures->features[block].valid |= mask;
SET_FLAG(sfeatures->features[block].requested, mask, flag);
return 0;
}
return -ENODATA;
}
static int set_features_multiple_bit(
const struct ethtool_gstrings *strings,
const struct ethtool_gfeatures *gfeatures,
struct ethtool_sfeatures *sfeatures,
const char *feature,
int flag) {
bool found = false; bool found = false;
int r = -ENODATA; int r = -ENODATA;
@ -529,8 +567,7 @@ static int set_features_bit(
for (uint32_t i = 0; i < strings->len; i++) { for (uint32_t i = 0; i < strings->len; i++) {
uint32_t block, mask; uint32_t block, mask;
if (!strneq((const char*) &strings->data[i * ETH_GSTRING_LEN], feature, ETH_GSTRING_LEN) && if (!startswith((const char*) &strings->data[i * ETH_GSTRING_LEN], feature))
!(endswith(feature, "-") && startswith((const char*) &strings->data[i * ETH_GSTRING_LEN], feature)))
continue; continue;
block = i / 32; block = i / 32;
@ -542,6 +579,10 @@ static int set_features_bit(
continue; continue;
} }
/* The flags is explicitly set by set_features_bit() */
if (FLAGS_SET(sfeatures->features[block].valid, mask))
continue;
sfeatures->features[block].valid |= mask; sfeatures->features[block].valid |= mask;
SET_FLAG(sfeatures->features[block].requested, mask, flag); SET_FLAG(sfeatures->features[block].requested, mask, flag);
@ -592,12 +633,18 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features
sfeatures->cmd = ETHTOOL_SFEATURES; sfeatures->cmd = ETHTOOL_SFEATURES;
sfeatures->size = DIV_ROUND_UP(strings->len, 32U); sfeatures->size = DIV_ROUND_UP(strings->len, 32U);
for (size_t i = 0; i < _NET_DEV_FEAT_MAX; i++) { for (size_t i = 0; i < _NET_DEV_FEAT_SIMPLE_MAX; i++) {
r = set_features_bit(strings, gfeatures, sfeatures, netdev_feature_table[i], features[i]); r = set_features_bit(strings, gfeatures, sfeatures, netdev_feature_table[i], features[i]);
if (r < 0) if (r < 0)
log_debug_errno(r, "ethtool: could not set feature %s for %s, ignoring: %m", netdev_feature_table[i], ifname); log_debug_errno(r, "ethtool: could not set feature %s for %s, ignoring: %m", netdev_feature_table[i], ifname);
} }
for (size_t i = _NET_DEV_FEAT_SIMPLE_MAX; i < _NET_DEV_FEAT_MAX; i++) {
r = set_features_multiple_bit(strings, gfeatures, sfeatures, netdev_feature_table[i], features[i]);
if (r < 0)
log_debug_errno(r, "ethtool: could not set feature %s for %s, ignoring: %m", netdev_feature_table[i], ifname);
}
ifr = (struct ifreq) { ifr = (struct ifreq) {
.ifr_data = (void*) sfeatures, .ifr_data = (void*) sfeatures,
}; };

View File

@ -20,13 +20,15 @@ typedef enum Duplex {
typedef enum NetDevFeature { typedef enum NetDevFeature {
NET_DEV_FEAT_RX, NET_DEV_FEAT_RX,
NET_DEV_FEAT_TX,
NET_DEV_FEAT_GSO, NET_DEV_FEAT_GSO,
NET_DEV_FEAT_GRO, NET_DEV_FEAT_GRO,
NET_DEV_FEAT_GRO_HW, NET_DEV_FEAT_GRO_HW,
NET_DEV_FEAT_LRO, NET_DEV_FEAT_LRO,
NET_DEV_FEAT_TSO, NET_DEV_FEAT_TSO,
NET_DEV_FEAT_TSO6, NET_DEV_FEAT_TSO6,
_NET_DEV_FEAT_SIMPLE_MAX,
NET_DEV_FEAT_TX = _NET_DEV_FEAT_SIMPLE_MAX,
_NET_DEV_FEAT_MAX, _NET_DEV_FEAT_MAX,
_NET_DEV_FEAT_INVALID = -EINVAL, _NET_DEV_FEAT_INVALID = -EINVAL,
} NetDevFeature; } NetDevFeature;