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:
parent
008d3a370c
commit
7a4f203547
@ -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,
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user