From: Yu Watanabe Date: Tue, 14 Sep 2021 16:48:59 +0000 (+0900) Subject: ethtool-util: apply tx-checksum-* features at last X-Git-Tag: v250-rc1~673^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7a4f203547c62cdc7611f38d97058b530570048f;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c index 59b1bd86f08..e95ce1a2091 100644 --- a/src/shared/ethtool-util.c +++ b/src/shared/ethtool-util.c @@ -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] = { [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_GRO_HW] = "rx-gro-hw", [NET_DEV_FEAT_LRO] = "rx-lro", [NET_DEV_FEAT_TSO] = "tx-tcp-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[] = { @@ -515,6 +516,43 @@ static int set_features_bit( const char *feature, 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; int r = -ENODATA; @@ -529,8 +567,7 @@ static int set_features_bit( 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) && - !(endswith(feature, "-") && startswith((const char*) &strings->data[i * ETH_GSTRING_LEN], feature))) + if (!startswith((const char*) &strings->data[i * ETH_GSTRING_LEN], feature)) continue; block = i / 32; @@ -542,6 +579,10 @@ static int set_features_bit( continue; } + /* The flags is explicitly set by set_features_bit() */ + if (FLAGS_SET(sfeatures->features[block].valid, mask)) + continue; + sfeatures->features[block].valid |= mask; 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->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]); if (r < 0) 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_data = (void*) sfeatures, }; diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h index 6e180995055..3f225256330 100644 --- a/src/shared/ethtool-util.h +++ b/src/shared/ethtool-util.h @@ -20,13 +20,15 @@ typedef enum Duplex { typedef enum NetDevFeature { NET_DEV_FEAT_RX, - NET_DEV_FEAT_TX, NET_DEV_FEAT_GSO, NET_DEV_FEAT_GRO, NET_DEV_FEAT_GRO_HW, NET_DEV_FEAT_LRO, NET_DEV_FEAT_TSO, 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_INVALID = -EINVAL, } NetDevFeature;