From d63baa6e189fa2f27cd259b59f5ee57dda022747 Mon Sep 17 00:00:00 2001 From: Anita Zhang Date: Sep 24 2021 17:18:38 +0000 Subject: 249.4-2.2: backport more networkd ethtools 'feature' support - Backport more feature support for systemd-networkd (#20450, #20541, #20729, #20828) --- diff --git a/SOURCES/20450.patch b/SOURCES/20450.patch new file mode 100644 index 0000000..e63c3d2 --- /dev/null +++ b/SOURCES/20450.patch @@ -0,0 +1,86 @@ +From 0db68800c756f298ef45584ac01915c2cb2ce359 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 16 Aug 2021 23:47:40 +0900 +Subject: [PATCH 1/2] ethtool: make the size of 'features' array static + +--- + src/shared/ethtool-util.c | 2 +- + src/shared/ethtool-util.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c +index f77f6943ca4f..699c7a97ab97 100644 +--- a/src/shared/ethtool-util.c ++++ b/src/shared/ethtool-util.c +@@ -501,7 +501,7 @@ static int set_features_bit( + return found ? 0 : -ENODATA; + } + +-int ethtool_set_features(int *ethtool_fd, const char *ifname, const int *features) { ++int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features[static _NET_DEV_FEAT_MAX]) { + _cleanup_free_ struct ethtool_gstrings *strings = NULL; + struct ethtool_sfeatures *sfeatures; + struct ifreq ifr = {}; +diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h +index 7d287666249a..f0fc40b0595f 100644 +--- a/src/shared/ethtool-util.h ++++ b/src/shared/ethtool-util.h +@@ -88,7 +88,7 @@ int ethtool_get_link_info(int *ethtool_fd, const char *ifname, + int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct ether_addr *ret); + int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts); + int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netdev_ring_param *ring); +-int ethtool_set_features(int *ethtool_fd, const char *ifname, const int *features); ++int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features[static _NET_DEV_FEAT_MAX]); + int ethtool_set_glinksettings(int *ethtool_fd, const char *ifname, + int autonegotiation, const uint32_t advertise[static N_ADVERTISE], + uint64_t speed, Duplex duplex, NetDevPort port); + +From c2f2250e5c52ec3745a462e3f55a94c133786df8 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 17 Aug 2021 00:44:00 +0900 +Subject: [PATCH 2/2] ethtool: make ethtool_set_features() return earlier when + nothing is requested + +--- + src/shared/ethtool-util.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c +index 699c7a97ab97..4ca90615f3c1 100644 +--- a/src/shared/ethtool-util.c ++++ b/src/shared/ethtool-util.c +@@ -505,12 +505,22 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features + _cleanup_free_ struct ethtool_gstrings *strings = NULL; + struct ethtool_sfeatures *sfeatures; + struct ifreq ifr = {}; +- int i, r; ++ bool have = false; ++ int r; + + assert(ethtool_fd); + assert(ifname); + assert(features); + ++ for (size_t i = 0; i < _NET_DEV_FEAT_MAX; i++) ++ if (features[i] >= 0) { ++ have = true; ++ break; ++ } ++ ++ if (!have) ++ return 0; ++ + r = ethtool_connect(ethtool_fd); + if (r < 0) + return r; +@@ -525,8 +535,8 @@ 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 (i = 0; i < _NET_DEV_FEAT_MAX; i++) +- if (features[i] != -1) { ++ for (size_t i = 0; i < _NET_DEV_FEAT_MAX; i++) ++ if (features[i] >= 0) { + r = set_features_bit(strings, netdev_feature_table[i], features[i], sfeatures); + if (r < 0) { + log_debug_errno(r, "ethtool: could not find feature, ignoring: %s", netdev_feature_table[i]); diff --git a/SOURCES/20541.patch b/SOURCES/20541.patch new file mode 100644 index 0000000..e41e3b1 --- /dev/null +++ b/SOURCES/20541.patch @@ -0,0 +1,306 @@ +From 72328a5977d240d33b78b24e7a6b65b1074000b9 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 26 Aug 2021 03:31:05 +0900 +Subject: [PATCH 1/2] ethtool: move function + +I'd like to locate all conf parsers at end of file. +--- + src/shared/ethtool-util.c | 250 +++++++++++++++++++------------------- + 1 file changed, 125 insertions(+), 125 deletions(-) + +diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c +index c47d819f0596..af3b917c75cb 100644 +--- a/src/shared/ethtool-util.c ++++ b/src/shared/ethtool-util.c +@@ -932,6 +932,131 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au + return 0; + } + ++int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce) { ++ struct ethtool_coalesce ecmd = { ++ .cmd = ETHTOOL_GCOALESCE, ++ }; ++ struct ifreq ifr = { ++ .ifr_data = (void*) &ecmd, ++ }; ++ bool need_update = false; ++ int r; ++ ++ assert(ethtool_fd); ++ assert(ifname); ++ assert(coalesce); ++ ++ if (coalesce->use_adaptive_rx_coalesce < 0 && ++ coalesce->use_adaptive_tx_coalesce < 0 && ++ !coalesce->rx_coalesce_usecs.set && ++ !coalesce->rx_max_coalesced_frames.set && ++ !coalesce->rx_coalesce_usecs_irq.set && ++ !coalesce->rx_max_coalesced_frames_irq.set && ++ !coalesce->tx_coalesce_usecs.set && ++ !coalesce->tx_max_coalesced_frames.set && ++ !coalesce->tx_coalesce_usecs_irq.set && ++ !coalesce->tx_max_coalesced_frames_irq.set && ++ !coalesce->stats_block_coalesce_usecs.set && ++ !coalesce->pkt_rate_low.set && ++ !coalesce->rx_coalesce_usecs_low.set && ++ !coalesce->rx_max_coalesced_frames_low.set && ++ !coalesce->tx_coalesce_usecs_low.set && ++ !coalesce->tx_max_coalesced_frames_low.set && ++ !coalesce->pkt_rate_high.set && ++ !coalesce->rx_coalesce_usecs_high.set && ++ !coalesce->rx_max_coalesced_frames_high.set && ++ !coalesce->tx_coalesce_usecs_high.set && ++ !coalesce->tx_max_coalesced_frames_high.set && ++ !coalesce->rate_sample_interval.set) ++ return 0; ++ ++ r = ethtool_connect(ethtool_fd); ++ if (r < 0) ++ return r; ++ ++ strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ ++ r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); ++ if (r < 0) ++ return -errno; ++ ++ if (coalesce->use_adaptive_rx_coalesce >= 0) ++ UPDATE(ecmd.use_adaptive_rx_coalesce, (uint32_t) coalesce->use_adaptive_rx_coalesce, need_update); ++ ++ if (coalesce->use_adaptive_tx_coalesce >= 0) ++ UPDATE(ecmd.use_adaptive_tx_coalesce, (uint32_t) coalesce->use_adaptive_tx_coalesce, need_update); ++ ++ if (coalesce->rx_coalesce_usecs.set) ++ UPDATE(ecmd.rx_coalesce_usecs, coalesce->rx_coalesce_usecs.value, need_update); ++ ++ if (coalesce->rx_max_coalesced_frames.set) ++ UPDATE(ecmd.rx_max_coalesced_frames, coalesce->rx_max_coalesced_frames.value, need_update); ++ ++ if (coalesce->rx_coalesce_usecs_irq.set) ++ UPDATE(ecmd.rx_coalesce_usecs_irq, coalesce->rx_coalesce_usecs_irq.value, need_update); ++ ++ if (coalesce->rx_max_coalesced_frames_irq.set) ++ UPDATE(ecmd.rx_max_coalesced_frames_irq, coalesce->rx_max_coalesced_frames_irq.value, need_update); ++ ++ if (coalesce->tx_coalesce_usecs.set) ++ UPDATE(ecmd.tx_coalesce_usecs, coalesce->tx_coalesce_usecs.value, need_update); ++ ++ if (coalesce->tx_max_coalesced_frames.set) ++ UPDATE(ecmd.tx_max_coalesced_frames, coalesce->tx_max_coalesced_frames.value, need_update); ++ ++ if (coalesce->tx_coalesce_usecs_irq.set) ++ UPDATE(ecmd.tx_coalesce_usecs_irq, coalesce->tx_coalesce_usecs_irq.value, need_update); ++ ++ if (coalesce->tx_max_coalesced_frames_irq.set) ++ UPDATE(ecmd.tx_max_coalesced_frames_irq, coalesce->tx_max_coalesced_frames_irq.value, need_update); ++ ++ if (coalesce->stats_block_coalesce_usecs.set) ++ UPDATE(ecmd.stats_block_coalesce_usecs, coalesce->stats_block_coalesce_usecs.value, need_update); ++ ++ if (coalesce->pkt_rate_low.set) ++ UPDATE(ecmd.pkt_rate_low, coalesce->pkt_rate_low.value, need_update); ++ ++ if (coalesce->rx_coalesce_usecs_low.set) ++ UPDATE(ecmd.rx_coalesce_usecs_low, coalesce->rx_coalesce_usecs_low.value, need_update); ++ ++ if (coalesce->rx_max_coalesced_frames_low.set) ++ UPDATE(ecmd.rx_max_coalesced_frames_low, coalesce->rx_max_coalesced_frames_low.value, need_update); ++ ++ if (coalesce->tx_coalesce_usecs_low.set) ++ UPDATE(ecmd.tx_coalesce_usecs_low, coalesce->tx_coalesce_usecs_low.value, need_update); ++ ++ if (coalesce->tx_max_coalesced_frames_low.set) ++ UPDATE(ecmd.tx_max_coalesced_frames_low, coalesce->tx_max_coalesced_frames_low.value, need_update); ++ ++ if (coalesce->pkt_rate_high.set) ++ UPDATE(ecmd.pkt_rate_high, coalesce->pkt_rate_high.value, need_update); ++ ++ if (coalesce->rx_coalesce_usecs_high.set) ++ UPDATE(ecmd.rx_coalesce_usecs_high, coalesce->rx_coalesce_usecs_high.value, need_update); ++ ++ if (coalesce->rx_max_coalesced_frames_high.set) ++ UPDATE(ecmd.rx_max_coalesced_frames_high, coalesce->rx_max_coalesced_frames_high.value, need_update); ++ ++ if (coalesce->tx_coalesce_usecs_high.set) ++ UPDATE(ecmd.tx_coalesce_usecs_high, coalesce->tx_coalesce_usecs_high.value, need_update); ++ ++ if (coalesce->tx_max_coalesced_frames_high.set) ++ UPDATE(ecmd.tx_max_coalesced_frames_high, coalesce->tx_max_coalesced_frames_high.value, need_update); ++ ++ if (coalesce->rate_sample_interval.set) ++ UPDATE(ecmd.rate_sample_interval, DIV_ROUND_UP(coalesce->rate_sample_interval.value, USEC_PER_SEC), need_update); ++ ++ if (!need_update) ++ return 0; ++ ++ ecmd.cmd = ETHTOOL_SCOALESCE; ++ r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); ++ if (r < 0) ++ return -errno; ++ ++ return 0; ++} ++ + int config_parse_advertise( + const char *unit, + const char *filename, +@@ -1182,128 +1307,3 @@ int config_parse_coalesce_sec( + + return 0; + } +- +-int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce) { +- struct ethtool_coalesce ecmd = { +- .cmd = ETHTOOL_GCOALESCE, +- }; +- struct ifreq ifr = { +- .ifr_data = (void*) &ecmd, +- }; +- bool need_update = false; +- int r; +- +- assert(ethtool_fd); +- assert(ifname); +- assert(coalesce); +- +- if (coalesce->use_adaptive_rx_coalesce < 0 && +- coalesce->use_adaptive_tx_coalesce < 0 && +- !coalesce->rx_coalesce_usecs.set && +- !coalesce->rx_max_coalesced_frames.set && +- !coalesce->rx_coalesce_usecs_irq.set && +- !coalesce->rx_max_coalesced_frames_irq.set && +- !coalesce->tx_coalesce_usecs.set && +- !coalesce->tx_max_coalesced_frames.set && +- !coalesce->tx_coalesce_usecs_irq.set && +- !coalesce->tx_max_coalesced_frames_irq.set && +- !coalesce->stats_block_coalesce_usecs.set && +- !coalesce->pkt_rate_low.set && +- !coalesce->rx_coalesce_usecs_low.set && +- !coalesce->rx_max_coalesced_frames_low.set && +- !coalesce->tx_coalesce_usecs_low.set && +- !coalesce->tx_max_coalesced_frames_low.set && +- !coalesce->pkt_rate_high.set && +- !coalesce->rx_coalesce_usecs_high.set && +- !coalesce->rx_max_coalesced_frames_high.set && +- !coalesce->tx_coalesce_usecs_high.set && +- !coalesce->tx_max_coalesced_frames_high.set && +- !coalesce->rate_sample_interval.set) +- return 0; +- +- r = ethtool_connect(ethtool_fd); +- if (r < 0) +- return r; +- +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); +- +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) +- return -errno; +- +- if (coalesce->use_adaptive_rx_coalesce >= 0) +- UPDATE(ecmd.use_adaptive_rx_coalesce, (uint32_t) coalesce->use_adaptive_rx_coalesce, need_update); +- +- if (coalesce->use_adaptive_tx_coalesce >= 0) +- UPDATE(ecmd.use_adaptive_tx_coalesce, (uint32_t) coalesce->use_adaptive_tx_coalesce, need_update); +- +- if (coalesce->rx_coalesce_usecs.set) +- UPDATE(ecmd.rx_coalesce_usecs, coalesce->rx_coalesce_usecs.value, need_update); +- +- if (coalesce->rx_max_coalesced_frames.set) +- UPDATE(ecmd.rx_max_coalesced_frames, coalesce->rx_max_coalesced_frames.value, need_update); +- +- if (coalesce->rx_coalesce_usecs_irq.set) +- UPDATE(ecmd.rx_coalesce_usecs_irq, coalesce->rx_coalesce_usecs_irq.value, need_update); +- +- if (coalesce->rx_max_coalesced_frames_irq.set) +- UPDATE(ecmd.rx_max_coalesced_frames_irq, coalesce->rx_max_coalesced_frames_irq.value, need_update); +- +- if (coalesce->tx_coalesce_usecs.set) +- UPDATE(ecmd.tx_coalesce_usecs, coalesce->tx_coalesce_usecs.value, need_update); +- +- if (coalesce->tx_max_coalesced_frames.set) +- UPDATE(ecmd.tx_max_coalesced_frames, coalesce->tx_max_coalesced_frames.value, need_update); +- +- if (coalesce->tx_coalesce_usecs_irq.set) +- UPDATE(ecmd.tx_coalesce_usecs_irq, coalesce->tx_coalesce_usecs_irq.value, need_update); +- +- if (coalesce->tx_max_coalesced_frames_irq.set) +- UPDATE(ecmd.tx_max_coalesced_frames_irq, coalesce->tx_max_coalesced_frames_irq.value, need_update); +- +- if (coalesce->stats_block_coalesce_usecs.set) +- UPDATE(ecmd.stats_block_coalesce_usecs, coalesce->stats_block_coalesce_usecs.value, need_update); +- +- if (coalesce->pkt_rate_low.set) +- UPDATE(ecmd.pkt_rate_low, coalesce->pkt_rate_low.value, need_update); +- +- if (coalesce->rx_coalesce_usecs_low.set) +- UPDATE(ecmd.rx_coalesce_usecs_low, coalesce->rx_coalesce_usecs_low.value, need_update); +- +- if (coalesce->rx_max_coalesced_frames_low.set) +- UPDATE(ecmd.rx_max_coalesced_frames_low, coalesce->rx_max_coalesced_frames_low.value, need_update); +- +- if (coalesce->tx_coalesce_usecs_low.set) +- UPDATE(ecmd.tx_coalesce_usecs_low, coalesce->tx_coalesce_usecs_low.value, need_update); +- +- if (coalesce->tx_max_coalesced_frames_low.set) +- UPDATE(ecmd.tx_max_coalesced_frames_low, coalesce->tx_max_coalesced_frames_low.value, need_update); +- +- if (coalesce->pkt_rate_high.set) +- UPDATE(ecmd.pkt_rate_high, coalesce->pkt_rate_high.value, need_update); +- +- if (coalesce->rx_coalesce_usecs_high.set) +- UPDATE(ecmd.rx_coalesce_usecs_high, coalesce->rx_coalesce_usecs_high.value, need_update); +- +- if (coalesce->rx_max_coalesced_frames_high.set) +- UPDATE(ecmd.rx_max_coalesced_frames_high, coalesce->rx_max_coalesced_frames_high.value, need_update); +- +- if (coalesce->tx_coalesce_usecs_high.set) +- UPDATE(ecmd.tx_coalesce_usecs_high, coalesce->tx_coalesce_usecs_high.value, need_update); +- +- if (coalesce->tx_max_coalesced_frames_high.set) +- UPDATE(ecmd.tx_max_coalesced_frames_high, coalesce->tx_max_coalesced_frames_high.value, need_update); +- +- if (coalesce->rate_sample_interval.set) +- UPDATE(ecmd.rate_sample_interval, DIV_ROUND_UP(coalesce->rate_sample_interval.value, USEC_PER_SEC), need_update); +- +- if (!need_update) +- return 0; +- +- ecmd.cmd = ETHTOOL_SCOALESCE; +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) +- return -errno; +- +- return 0; +-} + +From ee7512404b5de7c5ac36e09436379fada2ed84e7 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 26 Aug 2021 03:34:23 +0900 +Subject: [PATCH 2/2] udev/net: initialize coalesce tristate variables + +Otherwise, 99-default.link may introduce something like the +following warnings: +---- +Aug 26 03:23:59 systemd-udevd[519]: wlan0: Could not set coalesce settings, ignoring: Operation not supported +Aug 26 03:24:00 systemd-udevd[547]: wlp59s0: Could not set coalesce settings, ignoring: Operation not supported +---- + +Follow-up for 6c35ea5ef0231d519ff24d43a57a72cebab6a121. +--- + src/udev/net/link-config.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c +index 69f651435034..4963ba2fae81 100644 +--- a/src/udev/net/link-config.c ++++ b/src/udev/net/link-config.c +@@ -142,6 +142,8 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) { + .tx_flow_control = -1, + .autoneg_flow_control = -1, + .txqueuelen = UINT32_MAX, ++ .coalesce.use_adaptive_rx_coalesce = -1, ++ .coalesce.use_adaptive_tx_coalesce = -1, + }; + + for (i = 0; i < ELEMENTSOF(link->features); i++) diff --git a/SOURCES/20729.patch b/SOURCES/20729.patch new file mode 100644 index 0000000..82904e5 --- /dev/null +++ b/SOURCES/20729.patch @@ -0,0 +1,927 @@ +From 6d9a72f3b9b4d00ec80051503e5e3d4d7cd46c05 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 15 Sep 2021 01:28:29 +0900 +Subject: [PATCH 1/5] ethtool-util: use sizeof() + +--- + src/shared/ethtool-util.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c +index af3b917c75cb..d1f5eac63334 100644 +--- a/src/shared/ethtool-util.c ++++ b/src/shared/ethtool-util.c +@@ -214,7 +214,7 @@ int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) { + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); + if (r < 0) +@@ -254,7 +254,7 @@ int ethtool_get_link_info( + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); + if (r < 0) +@@ -303,7 +303,7 @@ int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct et + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); + if (r < 0) +@@ -362,7 +362,7 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) { + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); + if (r < 0) +@@ -405,7 +405,7 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); + if (r < 0) +@@ -538,7 +538,7 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = get_stringset(*ethtool_fd, &ifr, ETH_SS_FEATURES, &strings); + if (r < 0) +@@ -787,7 +787,7 @@ int ethtool_set_glinksettings( + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = get_glinksettings(*fd, &ifr, &u); + if (r < 0) { +@@ -857,7 +857,7 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) +@@ -906,7 +906,7 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = ioctl(*fd, SIOCETHTOOL, &ifr); + if (r < 0) +@@ -974,7 +974,7 @@ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, IFNAMSIZ, ifname); ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); + if (r < 0) + +From 4253dab576b3ff17887c3e0d97380aab2aa29d82 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 15 Sep 2021 01:41:15 +0900 +Subject: [PATCH 2/5] ethtool-util: shorten code a bit + +Also fixes a error code in debugging log. +--- + src/shared/ethtool-util.c | 70 ++++++++++++--------------------------- + 1 file changed, 22 insertions(+), 48 deletions(-) + +diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c +index d1f5eac63334..ac21ef0f61a8 100644 +--- a/src/shared/ethtool-util.c ++++ b/src/shared/ethtool-util.c +@@ -216,8 +216,7 @@ int ethtool_get_driver(int *ethtool_fd, const char *ifname, char **ret) { + + strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + if (isempty(ecmd.driver)) +@@ -256,8 +255,7 @@ int ethtool_get_link_info( + + strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + if (ret_autonegotiation) +@@ -305,8 +303,7 @@ int ethtool_get_permanent_macaddr(int *ethtool_fd, const char *ifname, struct et + + strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + if (epaddr.addr.size != 6) +@@ -364,8 +361,7 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) { + + strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + UPDATE(ecmd.wolopts, wolopts, need_update); +@@ -374,8 +370,7 @@ int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts) { + return 0; + + ecmd.cmd = ETHTOOL_SWOL; +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + return 0; +@@ -407,8 +402,7 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde + + strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + if (ring->rx.set) +@@ -427,8 +421,7 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde + return 0; + + ecmd.cmd = ETHTOOL_SRINGPARAM; +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + return 0; +@@ -446,7 +439,6 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st + }, + }; + unsigned len; +- int r; + + assert(ethtool_fd >= 0); + assert(ifr); +@@ -454,8 +446,7 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st + + ifr->ifr_data = (void *) &buffer.info; + +- r = ioctl(ethtool_fd, SIOCETHTOOL, ifr); +- if (r < 0) ++ if (ioctl(ethtool_fd, SIOCETHTOOL, ifr) < 0) + return -errno; + + if (!buffer.info.sset_mask) +@@ -478,8 +469,7 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st + + ifr->ifr_data = (void *) strings; + +- r = ioctl(ethtool_fd, SIOCETHTOOL, ifr); +- if (r < 0) ++ if (ioctl(ethtool_fd, SIOCETHTOOL, ifr) < 0) + return -errno; + + *ret = TAKE_PTR(strings); +@@ -559,9 +549,8 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features + + ifr.ifr_data = (void *) sfeatures; + +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) +- return log_debug_errno(r, "ethtool: could not set ethtool features for %s", ifname); ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) ++ return log_debug_errno(errno, "ethtool: could not set ethtool features for %s", ifname); + + return 0; + } +@@ -575,7 +564,6 @@ static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_uset + }; + struct ethtool_link_usettings *u; + unsigned offset; +- int r; + + assert(fd >= 0); + assert(ifr); +@@ -591,8 +579,7 @@ static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_uset + + ifr->ifr_data = (void *) &ecmd; + +- r = ioctl(fd, SIOCETHTOOL, ifr); +- if (r < 0) ++ if (ioctl(fd, SIOCETHTOOL, ifr) < 0) + return -errno; + + if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) +@@ -602,8 +589,7 @@ static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_uset + + ifr->ifr_data = (void *) &ecmd; + +- r = ioctl(fd, SIOCETHTOOL, ifr); +- if (r < 0) ++ if (ioctl(fd, SIOCETHTOOL, ifr) < 0) + return -errno; + + if (ecmd.req.link_mode_masks_nwords <= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) +@@ -636,7 +622,6 @@ static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **r + struct ethtool_cmd ecmd = { + .cmd = ETHTOOL_GSET, + }; +- int r; + + assert(fd >= 0); + assert(ifr); +@@ -644,8 +629,7 @@ static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **r + + ifr->ifr_data = (void *) &ecmd; + +- r = ioctl(fd, SIOCETHTOOL, ifr); +- if (r < 0) ++ if (ioctl(fd, SIOCETHTOOL, ifr) < 0) + return -errno; + + e = new(struct ethtool_link_usettings, 1); +@@ -678,7 +662,6 @@ static int set_slinksettings(int fd, struct ifreq *ifr, const struct ethtool_lin + __u32 link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; + } ecmd = {}; + unsigned offset; +- int r; + + assert(fd >= 0); + assert(ifr); +@@ -700,8 +683,7 @@ static int set_slinksettings(int fd, struct ifreq *ifr, const struct ethtool_lin + + ifr->ifr_data = (void *) &ecmd; + +- r = ioctl(fd, SIOCETHTOOL, ifr); +- if (r < 0) ++ if (ioctl(fd, SIOCETHTOOL, ifr) < 0) + return -errno; + + return 0; +@@ -711,7 +693,6 @@ static int set_sset(int fd, struct ifreq *ifr, const struct ethtool_link_usettin + struct ethtool_cmd ecmd = { + .cmd = ETHTOOL_SSET, + }; +- int r; + + assert(fd >= 0); + assert(ifr); +@@ -736,8 +717,7 @@ static int set_sset(int fd, struct ifreq *ifr, const struct ethtool_link_usettin + + ifr->ifr_data = (void *) &ecmd; + +- r = ioctl(fd, SIOCETHTOOL, ifr); +- if (r < 0) ++ if (ioctl(fd, SIOCETHTOOL, ifr) < 0) + return -errno; + + return 0; +@@ -859,8 +839,7 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha + + strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + +- r = ioctl(*fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + if (channels->rx.set) +@@ -879,8 +858,7 @@ int ethtool_set_channels(int *fd, const char *ifname, const netdev_channels *cha + return 0; + + ecmd.cmd = ETHTOOL_SCHANNELS; +- r = ioctl(*fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + return 0; +@@ -908,8 +886,7 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au + + strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + +- r = ioctl(*fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + if (rx >= 0) +@@ -925,8 +902,7 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au + return 0; + + ecmd.cmd = ETHTOOL_SPAUSEPARAM; +- r = ioctl(*fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + return 0; +@@ -976,8 +952,7 @@ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const + + strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + if (coalesce->use_adaptive_rx_coalesce >= 0) +@@ -1050,8 +1025,7 @@ int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const + return 0; + + ecmd.cmd = ETHTOOL_SCOALESCE; +- r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr); +- if (r < 0) ++ if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + return 0; + +From 008d3a370ccdea13290ab9277b32cc582b886b17 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 14 Sep 2021 17:42:52 +0900 +Subject: [PATCH 3/5] ethtool: do not set unavailable or never_changed bits + +--- + src/shared/ethtool-util.c | 138 ++++++++++++++++++++++++++------------ + 1 file changed, 96 insertions(+), 42 deletions(-) + +diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c +index ac21ef0f61a8..59b1bd86f085 100644 +--- a/src/shared/ethtool-util.c ++++ b/src/shared/ethtool-util.c +@@ -427,30 +427,31 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde + return 0; + } + +-static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, struct ethtool_gstrings **ret) { ++static int get_stringset(int ethtool_fd, const char *ifname, enum ethtool_stringset stringset_id, struct ethtool_gstrings **ret) { + _cleanup_free_ struct ethtool_gstrings *strings = NULL; + struct { + struct ethtool_sset_info info; + uint32_t space; + } buffer = { +- .info = { +- .cmd = ETHTOOL_GSSET_INFO, +- .sset_mask = UINT64_C(1) << stringset_id, +- }, ++ .info.cmd = ETHTOOL_GSSET_INFO, ++ .info.sset_mask = UINT64_C(1) << stringset_id, + }; +- unsigned len; ++ struct ifreq ifr = { ++ .ifr_data = (void*) &buffer, ++ }; ++ uint32_t len; + + assert(ethtool_fd >= 0); +- assert(ifr); ++ assert(ifname); + assert(ret); + +- ifr->ifr_data = (void *) &buffer.info; ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + +- if (ioctl(ethtool_fd, SIOCETHTOOL, ifr) < 0) ++ if (ioctl(ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + +- if (!buffer.info.sset_mask) +- return -EINVAL; ++ if (buffer.info.sset_mask == 0) ++ return -EOPNOTSUPP; + + #pragma GCC diagnostic push + #if HAVE_ZERO_LENGTH_BOUNDS +@@ -458,8 +459,10 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st + #endif + len = buffer.info.data[0]; + #pragma GCC diagnostic pop ++ if (len == 0) ++ return -EOPNOTSUPP; + +- strings = malloc0(sizeof(struct ethtool_gstrings) + len * ETH_GSTRING_LEN); ++ strings = malloc0(offsetof(struct ethtool_gstrings, data) + len * ETH_GSTRING_LEN); + if (!strings) + return -ENOMEM; + +@@ -467,47 +470,92 @@ static int get_stringset(int ethtool_fd, struct ifreq *ifr, int stringset_id, st + strings->string_set = stringset_id; + strings->len = len; + +- ifr->ifr_data = (void *) strings; ++ ifr.ifr_data = (void*) strings; + +- if (ioctl(ethtool_fd, SIOCETHTOOL, ifr) < 0) ++ if (ioctl(ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return -errno; + + *ret = TAKE_PTR(strings); ++ return 0; ++} ++ ++static int get_features(int ethtool_fd, const char *ifname, uint32_t n_features, struct ethtool_gfeatures **ret) { ++ _cleanup_free_ struct ethtool_gfeatures *gfeatures = NULL; ++ struct ifreq ifr; ++ ++ assert(ethtool_fd >= 0); ++ assert(ifname); ++ assert(ret); ++ assert(n_features > 0); ++ ++ gfeatures = malloc0(offsetof(struct ethtool_gfeatures, features) + ++ DIV_ROUND_UP(n_features, 32U) * sizeof(gfeatures->features[0])); ++ if (!gfeatures) ++ return -ENOMEM; ++ ++ gfeatures->cmd = ETHTOOL_GFEATURES; ++ gfeatures->size = DIV_ROUND_UP(n_features, 32U); ++ ++ ifr = (struct ifreq) { ++ .ifr_data = (void*) gfeatures, ++ }; ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); ++ ++ if (ioctl(ethtool_fd, SIOCETHTOOL, &ifr) < 0) ++ return -errno; + ++ *ret = TAKE_PTR(gfeatures); + return 0; + } + + static int set_features_bit( + const struct ethtool_gstrings *strings, ++ const struct ethtool_gfeatures *gfeatures, ++ struct ethtool_sfeatures *sfeatures, + const char *feature, +- bool flag, +- struct ethtool_sfeatures *sfeatures) { ++ int flag) { ++ + bool found = false; ++ int r = -ENODATA; + + assert(strings); +- assert(feature); ++ assert(gfeatures); + assert(sfeatures); ++ assert(feature); ++ ++ if (flag < 0) ++ return 0; ++ ++ for (uint32_t i = 0; i < strings->len; i++) { ++ uint32_t block, mask; + +- 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; ++ 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))) ++ continue; + +- block = i / 32; +- bit = i % 32; ++ block = i / 32; ++ mask = UINT32_C(1) << (i % 32); + +- sfeatures->features[block].valid |= 1 << bit; +- SET_FLAG(sfeatures->features[block].requested, 1 << bit, flag); +- found = true; ++ if (!FLAGS_SET(gfeatures->features[block].available, mask) || ++ FLAGS_SET(gfeatures->features[block].never_changed, mask)) { ++ r = -EOPNOTSUPP; ++ continue; + } + +- return found ? 0 : -ENODATA; ++ sfeatures->features[block].valid |= mask; ++ SET_FLAG(sfeatures->features[block].requested, mask, flag); ++ ++ found = true; ++ } ++ ++ return found ? 0 : r; + } + + int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features[static _NET_DEV_FEAT_MAX]) { + _cleanup_free_ struct ethtool_gstrings *strings = NULL; +- struct ethtool_sfeatures *sfeatures; +- struct ifreq ifr = {}; ++ _cleanup_free_ struct ethtool_gfeatures *gfeatures = NULL; ++ _cleanup_free_ struct ethtool_sfeatures *sfeatures = NULL; ++ struct ifreq ifr; + bool have = false; + int r; + +@@ -528,26 +576,32 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features + if (r < 0) + return r; + +- strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); ++ r = get_stringset(*ethtool_fd, ifname, ETH_SS_FEATURES, &strings); ++ if (r < 0) ++ return log_debug_errno(r, "ethtool: could not get ethtool feature strings: %m"); + +- r = get_stringset(*ethtool_fd, &ifr, ETH_SS_FEATURES, &strings); ++ r = get_features(*ethtool_fd, ifname, strings->len, &gfeatures); + if (r < 0) +- return log_debug_errno(r, "ethtool: could not get ethtool features for %s", ifname); ++ return log_debug_errno(r, "ethtool: could not get ethtool features for %s: %m", ifname); ++ ++ sfeatures = malloc0(offsetof(struct ethtool_sfeatures, features) + ++ DIV_ROUND_UP(strings->len, 32U) * sizeof(sfeatures->features[0])); ++ if (!sfeatures) ++ return log_oom_debug(); + +- sfeatures = alloca0(sizeof(struct ethtool_sfeatures) + DIV_ROUND_UP(strings->len, 32U) * sizeof(sfeatures->features[0])); + sfeatures->cmd = ETHTOOL_SFEATURES; + sfeatures->size = DIV_ROUND_UP(strings->len, 32U); + +- for (size_t i = 0; i < _NET_DEV_FEAT_MAX; i++) +- if (features[i] >= 0) { +- r = set_features_bit(strings, netdev_feature_table[i], features[i], sfeatures); +- if (r < 0) { +- log_debug_errno(r, "ethtool: could not find feature, ignoring: %s", netdev_feature_table[i]); +- continue; +- } +- } ++ for (size_t i = 0; i < _NET_DEV_FEAT_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); ++ } + +- ifr.ifr_data = (void *) sfeatures; ++ ifr = (struct ifreq) { ++ .ifr_data = (void*) sfeatures, ++ }; ++ strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); + + if (ioctl(*ethtool_fd, SIOCETHTOOL, &ifr) < 0) + return log_debug_errno(errno, "ethtool: could not set ethtool features for %s", ifname); + +From 7a4f203547c62cdc7611f38d97058b530570048f Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 15 Sep 2021 01:48:59 +0900 +Subject: [PATCH 4/5] 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. +--- + src/shared/ethtool-util.c | 55 ++++++++++++++++++++++++++++++++++++--- + src/shared/ethtool-util.h | 4 ++- + 2 files changed, 54 insertions(+), 5 deletions(-) + +diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c +index 59b1bd86f085..e95ce1a20917 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 6e180995055b..3f2252563304 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; + +From 77bf5c31de1d01edd49ac6aa25cdbe7734a11a25 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 14 Sep 2021 22:12:42 +0900 +Subject: [PATCH 5/5] ethtool-util: add more network device features + +Then, we can easily add new settings to configure features in .link +file. +--- + src/shared/ethtool-util.c | 73 ++++++++++++++++++++++++---- + src/shared/ethtool-util.h | 59 +++++++++++++++++++++- + src/udev/net/link-config-gperf.gperf | 4 +- + 3 files changed, 123 insertions(+), 13 deletions(-) + +diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c +index e95ce1a20917..00060abff40f 100644 +--- a/src/shared/ethtool-util.c ++++ b/src/shared/ethtool-util.c +@@ -70,15 +70,70 @@ 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_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-" */ ++ [NET_DEV_FEAT_SG] = "tx-scatter-gather", ++ [NET_DEV_FEAT_IP_CSUM] = "tx-checksum-ipv4", ++ [NET_DEV_FEAT_HW_CSUM] = "tx-checksum-ip-generic", ++ [NET_DEV_FEAT_IPV6_CSUM] = "tx-checksum-ipv6", ++ [NET_DEV_FEAT_HIGHDMA] = "highdma", ++ [NET_DEV_FEAT_FRAGLIST] = "tx-scatter-gather-fraglist", ++ [NET_DEV_FEAT_HW_VLAN_CTAG_TX] = "tx-vlan-hw-insert", ++ [NET_DEV_FEAT_HW_VLAN_CTAG_RX] = "rx-vlan-hw-parse", ++ [NET_DEV_FEAT_HW_VLAN_CTAG_FILTER] = "rx-vlan-filter", ++ [NET_DEV_FEAT_HW_VLAN_STAG_TX] = "tx-vlan-stag-hw-insert", ++ [NET_DEV_FEAT_HW_VLAN_STAG_RX] = "rx-vlan-stag-hw-parse", ++ [NET_DEV_FEAT_HW_VLAN_STAG_FILTER] = "rx-vlan-stag-filter", ++ [NET_DEV_FEAT_VLAN_CHALLENGED] = "vlan-challenged", ++ [NET_DEV_FEAT_GSO] = "tx-generic-segmentation", ++ [NET_DEV_FEAT_LLTX] = "tx-lockless", ++ [NET_DEV_FEAT_NETNS_LOCAL] = "netns-local", ++ [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_GSO_ROBUST] = "tx-gso-robust", ++ [NET_DEV_FEAT_TSO_ECN] = "tx-tcp-ecn-segmentation", ++ [NET_DEV_FEAT_TSO_MANGLEID] = "tx-tcp-mangleid-segmentation", ++ [NET_DEV_FEAT_TSO6] = "tx-tcp6-segmentation", ++ [NET_DEV_FEAT_FSO] = "tx-fcoe-segmentation", ++ [NET_DEV_FEAT_GSO_GRE] = "tx-gre-segmentation", ++ [NET_DEV_FEAT_GSO_GRE_CSUM] = "tx-gre-csum-segmentation", ++ [NET_DEV_FEAT_GSO_IPXIP4] = "tx-ipxip4-segmentation", ++ [NET_DEV_FEAT_GSO_IPXIP6] = "tx-ipxip6-segmentation", ++ [NET_DEV_FEAT_GSO_UDP_TUNNEL] = "tx-udp_tnl-segmentation", ++ [NET_DEV_FEAT_GSO_UDP_TUNNEL_CSUM] = "tx-udp_tnl-csum-segmentation", ++ [NET_DEV_FEAT_GSO_PARTIAL] = "tx-gso-partial", ++ [NET_DEV_FEAT_GSO_TUNNEL_REMCSUM] = "tx-tunnel-remcsum-segmentation", ++ [NET_DEV_FEAT_GSO_SCTP] = "tx-sctp-segmentation", ++ [NET_DEV_FEAT_GSO_ESP] = "tx-esp-segmentation", ++ [NET_DEV_FEAT_GSO_UDP_L4] = "tx-udp-segmentation", ++ [NET_DEV_FEAT_GSO_FRAGLIST] = "tx-gso-list", ++ [NET_DEV_FEAT_FCOE_CRC] = "tx-checksum-fcoe-crc", ++ [NET_DEV_FEAT_SCTP_CRC] = "tx-checksum-sctp", ++ [NET_DEV_FEAT_FCOE_MTU] = "fcoe-mtu", ++ [NET_DEV_FEAT_NTUPLE] = "rx-ntuple-filter", ++ [NET_DEV_FEAT_RXHASH] = "rx-hashing", ++ [NET_DEV_FEAT_RXCSUM] = "rx-checksum", ++ [NET_DEV_FEAT_NOCACHE_COPY] = "tx-nocache-copy", ++ [NET_DEV_FEAT_LOOPBACK] = "loopback", ++ [NET_DEV_FEAT_RXFCS] = "rx-fcs", ++ [NET_DEV_FEAT_RXALL] = "rx-all", ++ [NET_DEV_FEAT_HW_L2FW_DOFFLOAD] = "l2-fwd-offload", ++ [NET_DEV_FEAT_HW_TC] = "hw-tc-offload", ++ [NET_DEV_FEAT_HW_ESP] = "esp-hw-offload", ++ [NET_DEV_FEAT_HW_ESP_TX_CSUM] = "esp-tx-csum-hw-offload", ++ [NET_DEV_FEAT_RX_UDP_TUNNEL_PORT] = "rx-udp_tunnel-port-offload", ++ [NET_DEV_FEAT_HW_TLS_RECORD] = "tls-hw-record", ++ [NET_DEV_FEAT_HW_TLS_TX] = "tls-hw-tx-offload", ++ [NET_DEV_FEAT_HW_TLS_RX] = "tls-hw-rx-offload", ++ [NET_DEV_FEAT_GRO_FRAGLIST] = "rx-gro-list", ++ [NET_DEV_FEAT_HW_MACSEC] = "macsec-hw-offload", ++ [NET_DEV_FEAT_GRO_UDP_FWD] = "rx-udp-gro-forwarding", ++ [NET_DEV_FEAT_HW_HSR_TAG_INS] = "hsr-tag-ins-offload", ++ [NET_DEV_FEAT_HW_HSR_TAG_RM] = "hsr-tag-rm-offload", ++ [NET_DEV_FEAT_HW_HSR_FWD] = "hsr-fwd-offload", ++ [NET_DEV_FEAT_HW_HSR_DUP] = "hsr-dup-offload", ++ ++ [NET_DEV_FEAT_TXCSUM] = "tx-checksum-", /* The suffix "-" means any feature beginning with "tx-checksum-" */ + }; + + static const char* const ethtool_link_mode_bit_table[] = { +diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h +index 3f2252563304..cc0655893175 100644 +--- a/src/shared/ethtool-util.h ++++ b/src/shared/ethtool-util.h +@@ -19,16 +19,71 @@ typedef enum Duplex { + } Duplex; + + typedef enum NetDevFeature { +- NET_DEV_FEAT_RX, ++ NET_DEV_FEAT_SG, ++ NET_DEV_FEAT_IP_CSUM, ++ NET_DEV_FEAT_HW_CSUM, ++ NET_DEV_FEAT_IPV6_CSUM, ++ NET_DEV_FEAT_HIGHDMA, ++ NET_DEV_FEAT_FRAGLIST, ++ NET_DEV_FEAT_HW_VLAN_CTAG_TX, ++ NET_DEV_FEAT_HW_VLAN_CTAG_RX, ++ NET_DEV_FEAT_HW_VLAN_CTAG_FILTER, ++ NET_DEV_FEAT_HW_VLAN_STAG_TX, ++ NET_DEV_FEAT_HW_VLAN_STAG_RX, ++ NET_DEV_FEAT_HW_VLAN_STAG_FILTER, ++ NET_DEV_FEAT_VLAN_CHALLENGED, + NET_DEV_FEAT_GSO, ++ NET_DEV_FEAT_LLTX, ++ NET_DEV_FEAT_NETNS_LOCAL, + NET_DEV_FEAT_GRO, + NET_DEV_FEAT_GRO_HW, + NET_DEV_FEAT_LRO, + NET_DEV_FEAT_TSO, ++ NET_DEV_FEAT_GSO_ROBUST, ++ NET_DEV_FEAT_TSO_ECN, ++ NET_DEV_FEAT_TSO_MANGLEID, + NET_DEV_FEAT_TSO6, ++ NET_DEV_FEAT_FSO, ++ NET_DEV_FEAT_GSO_GRE, ++ NET_DEV_FEAT_GSO_GRE_CSUM, ++ NET_DEV_FEAT_GSO_IPXIP4, ++ NET_DEV_FEAT_GSO_IPXIP6, ++ NET_DEV_FEAT_GSO_UDP_TUNNEL, ++ NET_DEV_FEAT_GSO_UDP_TUNNEL_CSUM, ++ NET_DEV_FEAT_GSO_PARTIAL, ++ NET_DEV_FEAT_GSO_TUNNEL_REMCSUM, ++ NET_DEV_FEAT_GSO_SCTP, ++ NET_DEV_FEAT_GSO_ESP, ++ NET_DEV_FEAT_GSO_UDP_L4, ++ NET_DEV_FEAT_GSO_FRAGLIST, ++ NET_DEV_FEAT_FCOE_CRC, ++ NET_DEV_FEAT_SCTP_CRC, ++ NET_DEV_FEAT_FCOE_MTU, ++ NET_DEV_FEAT_NTUPLE, ++ NET_DEV_FEAT_RXHASH, ++ NET_DEV_FEAT_RXCSUM, ++ NET_DEV_FEAT_NOCACHE_COPY, ++ NET_DEV_FEAT_LOOPBACK, ++ NET_DEV_FEAT_RXFCS, ++ NET_DEV_FEAT_RXALL, ++ NET_DEV_FEAT_HW_L2FW_DOFFLOAD, ++ NET_DEV_FEAT_HW_TC, ++ NET_DEV_FEAT_HW_ESP, ++ NET_DEV_FEAT_HW_ESP_TX_CSUM, ++ NET_DEV_FEAT_RX_UDP_TUNNEL_PORT, ++ NET_DEV_FEAT_HW_TLS_RECORD, ++ NET_DEV_FEAT_HW_TLS_TX, ++ NET_DEV_FEAT_HW_TLS_RX, ++ NET_DEV_FEAT_GRO_FRAGLIST, ++ NET_DEV_FEAT_HW_MACSEC, ++ NET_DEV_FEAT_GRO_UDP_FWD, ++ NET_DEV_FEAT_HW_HSR_TAG_INS, ++ NET_DEV_FEAT_HW_HSR_TAG_RM, ++ NET_DEV_FEAT_HW_HSR_FWD, ++ NET_DEV_FEAT_HW_HSR_DUP, + _NET_DEV_FEAT_SIMPLE_MAX, + +- NET_DEV_FEAT_TX = _NET_DEV_FEAT_SIMPLE_MAX, ++ NET_DEV_FEAT_TXCSUM = _NET_DEV_FEAT_SIMPLE_MAX, + _NET_DEV_FEAT_MAX, + _NET_DEV_FEAT_INVALID = -EINVAL, + } NetDevFeature; +diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf +index 44b46cb17c0b..e3cdaaee0509 100644 +--- a/src/udev/net/link-config-gperf.gperf ++++ b/src/udev/net/link-config-gperf.gperf +@@ -50,8 +50,8 @@ Link.Duplex, config_parse_duplex, + Link.AutoNegotiation, config_parse_tristate, 0, offsetof(LinkConfig, autonegotiation) + Link.WakeOnLan, config_parse_wol, 0, offsetof(LinkConfig, wol) + Link.Port, config_parse_port, 0, offsetof(LinkConfig, port) +-Link.ReceiveChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_RX]) +-Link.TransmitChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TX]) ++Link.ReceiveChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_RXCSUM]) ++Link.TransmitChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TXCSUM]) + Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_GSO]) + Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TSO]) + Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6]) diff --git a/SOURCES/20828.patch b/SOURCES/20828.patch new file mode 100644 index 0000000..2b55bd4 --- /dev/null +++ b/SOURCES/20828.patch @@ -0,0 +1,240 @@ +From 88eca13f57194765d184ca227320df83f48020e2 Mon Sep 17 00:00:00 2001 +From: Anita Zhang +Date: Fri, 24 Sep 2021 01:19:00 -0700 +Subject: [PATCH] link: connect 5 more properties to ethtool features + +Sets up the follow properties and their corresponding ethtool feature: +- ReceiveVLANCTAGHardwareAcceleration == rx-vlan-hw-parse (or rxvlan) +- TransmitVLANCTAGHardwareAcceleration == tx-vlan-hw-insert (or txvlan) +- ReceiveVLANCTAGFilter == rx-vlan-filter +- TransmitVLANSTAGHardwareAcceleration == tx-vlan-stag-hw-insert +- NTupleFilter == rx-ntuple-filter (or ntuple) +--- + man/systemd.link.xml | 35 +++++ + src/udev/net/link-config-gperf.gperf | 153 +++++++++++---------- + test/fuzz/fuzz-link-parser/directives.link | 5 + + 3 files changed, 119 insertions(+), 74 deletions(-) + +diff --git a/man/systemd.link.xml b/man/systemd.link.xml +index 638a1522cd38..c8d3c5137459 100644 +--- a/man/systemd.link.xml ++++ b/man/systemd.link.xml +@@ -715,6 +715,41 @@ + When unset, the kernel's default will be used. + + ++ ++ ReceiveVLANCTAGHardwareAcceleration= ++ ++ Takes a boolean. If set to true, receive VLAN CTAG hardware acceleration is enabled. ++ When unset, the kernel's default will be used. ++ ++ ++ ++ TransmitVLANCTAGHardwareAcceleration= ++ ++ Takes a boolean. If set to true, transmit VLAN CTAG hardware acceleration is enabled. ++ When unset, the kernel's default will be used. ++ ++ ++ ++ ReceiveVLANCTAGFilter= ++ ++ Takes a boolean. If set to true, receive filtering on VLAN CTAGs is enabled. ++ When unset, the kernel's default will be used. ++ ++ ++ ++ TransmitVLANSTAGHardwareAcceleration= ++ ++ Takes a boolean. If set to true, transmit VLAN STAG HW acceleration is enabled. ++ When unset, the kernel's default will be used. ++ ++ ++ ++ NTupleFilter= ++ ++ Takes a boolean. If set to true, receive N-tuple filters and actions are enabled. ++ When unset, the kernel's default will be used. ++ ++ + + RxChannels= + TxChannels= +diff --git a/src/udev/net/link-config-gperf.gperf b/src/udev/net/link-config-gperf.gperf +index e3cdaaee0509..04c255ce514c 100644 +--- a/src/udev/net/link-config-gperf.gperf ++++ b/src/udev/net/link-config-gperf.gperf +@@ -21,77 +21,82 @@ struct ConfigPerfItem; + %struct-type + %includes + %% +-Match.MACAddress, config_parse_hwaddrs, 0, offsetof(LinkConfig, match.mac) +-Match.PermanentMACAddress, config_parse_hwaddrs, 0, offsetof(LinkConfig, match.permanent_mac) +-Match.OriginalName, config_parse_match_ifnames, 0, offsetof(LinkConfig, match.ifname) +-Match.Path, config_parse_match_strv, 0, offsetof(LinkConfig, match.path) +-Match.Driver, config_parse_match_strv, 0, offsetof(LinkConfig, match.driver) +-Match.Type, config_parse_match_strv, 0, offsetof(LinkConfig, match.iftype) +-Match.Property, config_parse_match_property, 0, offsetof(LinkConfig, match.property) +-Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(LinkConfig, conditions) +-Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(LinkConfig, conditions) +-Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(LinkConfig, conditions) +-Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(LinkConfig, conditions) +-Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(LinkConfig, conditions) +-Link.Description, config_parse_string, 0, offsetof(LinkConfig, description) +-Link.MACAddressPolicy, config_parse_mac_address_policy, 0, offsetof(LinkConfig, mac_address_policy) +-Link.MACAddress, config_parse_hwaddr, 0, offsetof(LinkConfig, mac) +-Link.NamePolicy, config_parse_name_policy, 0, offsetof(LinkConfig, name_policy) +-Link.Name, config_parse_ifname, 0, offsetof(LinkConfig, name) +-Link.AlternativeName, config_parse_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(LinkConfig, alternative_names) +-Link.AlternativeNamesPolicy, config_parse_alternative_names_policy, 0, offsetof(LinkConfig, alternative_names_policy) +-Link.Alias, config_parse_ifalias, 0, offsetof(LinkConfig, alias) +-Link.TransmitQueues, config_parse_rx_tx_queues, 0, offsetof(LinkConfig, txqueues) +-Link.ReceiveQueues, config_parse_rx_tx_queues, 0, offsetof(LinkConfig, rxqueues) +-Link.TransmitQueueLength, config_parse_txqueuelen, 0, offsetof(LinkConfig, txqueuelen) +-Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(LinkConfig, mtu) +-Link.BitsPerSecond, config_parse_si_uint64, 0, offsetof(LinkConfig, speed) +-Link.Duplex, config_parse_duplex, 0, offsetof(LinkConfig, duplex) +-Link.AutoNegotiation, config_parse_tristate, 0, offsetof(LinkConfig, autonegotiation) +-Link.WakeOnLan, config_parse_wol, 0, offsetof(LinkConfig, wol) +-Link.Port, config_parse_port, 0, offsetof(LinkConfig, port) +-Link.ReceiveChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_RXCSUM]) +-Link.TransmitChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TXCSUM]) +-Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_GSO]) +-Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TSO]) +-Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6]) +-Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0 +-Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_GRO]) +-Link.GenericReceiveOffloadHardware, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_GRO_HW]) +-Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_LRO]) +-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_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) +-Link.GenericSegmentOffloadMaxBytes, config_parse_iec_size, 0, offsetof(LinkConfig, gso_max_size) +-Link.GenericSegmentOffloadMaxSegments, config_parse_uint32, 0, offsetof(LinkConfig, gso_max_segments) +-Link.RxCoalesceSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs) +-Link.RxMaxCoalescedFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_max_coalesced_frames) +-Link.RxCoalesceIrqSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs_irq) +-Link.RxMaxCoalescedIrqFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_irq) +-Link.TxCoalesceSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs) +-Link.TxMaxCoalescedFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames) +-Link.TxCoalesceIrqSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_irq) +-Link.TxMaxCoalescedIrqFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_irq) +-Link.StatisticsBlockCoalesceSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.stats_block_coalesce_usecs) +-Link.UseAdaptiveRxCoalesce, config_parse_tristate, 0, offsetof(LinkConfig, coalesce.use_adaptive_rx_coalesce) +-Link.UseAdaptiveTxCoalesce, config_parse_tristate, 0, offsetof(LinkConfig, coalesce.use_adaptive_tx_coalesce) +-Link.CoalescePacketRateLow, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.pkt_rate_low) +-Link.RxCoalesceLowSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs_low) +-Link.RxMaxCoalescedLowFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_low) +-Link.TxCoalesceLowSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_low) +-Link.TxMaxCoalescedLowFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_low) +-Link.CoalescePacketRateHigh, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.pkt_rate_high) +-Link.RxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs_high) +-Link.RxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_high) +-Link.TxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high) +-Link.TxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high) +-Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rate_sample_interval) ++Match.MACAddress, config_parse_hwaddrs, 0, offsetof(LinkConfig, match.mac) ++Match.PermanentMACAddress, config_parse_hwaddrs, 0, offsetof(LinkConfig, match.permanent_mac) ++Match.OriginalName, config_parse_match_ifnames, 0, offsetof(LinkConfig, match.ifname) ++Match.Path, config_parse_match_strv, 0, offsetof(LinkConfig, match.path) ++Match.Driver, config_parse_match_strv, 0, offsetof(LinkConfig, match.driver) ++Match.Type, config_parse_match_strv, 0, offsetof(LinkConfig, match.iftype) ++Match.Property, config_parse_match_property, 0, offsetof(LinkConfig, match.property) ++Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(LinkConfig, conditions) ++Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(LinkConfig, conditions) ++Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(LinkConfig, conditions) ++Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(LinkConfig, conditions) ++Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(LinkConfig, conditions) ++Link.Description, config_parse_string, 0, offsetof(LinkConfig, description) ++Link.MACAddressPolicy, config_parse_mac_address_policy, 0, offsetof(LinkConfig, mac_address_policy) ++Link.MACAddress, config_parse_hwaddr, 0, offsetof(LinkConfig, mac) ++Link.NamePolicy, config_parse_name_policy, 0, offsetof(LinkConfig, name_policy) ++Link.Name, config_parse_ifname, 0, offsetof(LinkConfig, name) ++Link.AlternativeName, config_parse_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(LinkConfig, alternative_names) ++Link.AlternativeNamesPolicy, config_parse_alternative_names_policy, 0, offsetof(LinkConfig, alternative_names_policy) ++Link.Alias, config_parse_ifalias, 0, offsetof(LinkConfig, alias) ++Link.TransmitQueues, config_parse_rx_tx_queues, 0, offsetof(LinkConfig, txqueues) ++Link.ReceiveQueues, config_parse_rx_tx_queues, 0, offsetof(LinkConfig, rxqueues) ++Link.TransmitQueueLength, config_parse_txqueuelen, 0, offsetof(LinkConfig, txqueuelen) ++Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(LinkConfig, mtu) ++Link.BitsPerSecond, config_parse_si_uint64, 0, offsetof(LinkConfig, speed) ++Link.Duplex, config_parse_duplex, 0, offsetof(LinkConfig, duplex) ++Link.AutoNegotiation, config_parse_tristate, 0, offsetof(LinkConfig, autonegotiation) ++Link.WakeOnLan, config_parse_wol, 0, offsetof(LinkConfig, wol) ++Link.Port, config_parse_port, 0, offsetof(LinkConfig, port) ++Link.ReceiveChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_RXCSUM]) ++Link.TransmitChecksumOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TXCSUM]) ++Link.GenericSegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_GSO]) ++Link.TCPSegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TSO]) ++Link.TCP6SegmentationOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_TSO6]) ++Link.UDPSegmentationOffload, config_parse_warn_compat, DISABLED_LEGACY, 0 ++Link.GenericReceiveOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_GRO]) ++Link.GenericReceiveOffloadHardware, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_GRO_HW]) ++Link.LargeReceiveOffload, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_LRO]) ++Link.ReceiveVLANCTAGHardwareAcceleration, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_HW_VLAN_CTAG_RX]) ++Link.TransmitVLANCTAGHardwareAcceleration, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_HW_VLAN_CTAG_TX]) ++Link.ReceiveVLANCTAGFilter, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_HW_VLAN_CTAG_FILTER]) ++Link.TransmitVLANSTAGHardwareAcceleration, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_HW_VLAN_STAG_TX]) ++Link.NTupleFilter, config_parse_tristate, 0, offsetof(LinkConfig, features[NET_DEV_FEAT_NTUPLE]) ++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_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) ++Link.GenericSegmentOffloadMaxBytes, config_parse_iec_size, 0, offsetof(LinkConfig, gso_max_size) ++Link.GenericSegmentOffloadMaxSegments, config_parse_uint32, 0, offsetof(LinkConfig, gso_max_segments) ++Link.RxCoalesceSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs) ++Link.RxMaxCoalescedFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_max_coalesced_frames) ++Link.RxCoalesceIrqSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs_irq) ++Link.RxMaxCoalescedIrqFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_irq) ++Link.TxCoalesceSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs) ++Link.TxMaxCoalescedFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames) ++Link.TxCoalesceIrqSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_irq) ++Link.TxMaxCoalescedIrqFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_irq) ++Link.StatisticsBlockCoalesceSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.stats_block_coalesce_usecs) ++Link.UseAdaptiveRxCoalesce, config_parse_tristate, 0, offsetof(LinkConfig, coalesce.use_adaptive_rx_coalesce) ++Link.UseAdaptiveTxCoalesce, config_parse_tristate, 0, offsetof(LinkConfig, coalesce.use_adaptive_tx_coalesce) ++Link.CoalescePacketRateLow, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.pkt_rate_low) ++Link.RxCoalesceLowSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs_low) ++Link.RxMaxCoalescedLowFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_low) ++Link.TxCoalesceLowSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_low) ++Link.TxMaxCoalescedLowFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_low) ++Link.CoalescePacketRateHigh, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.pkt_rate_high) ++Link.RxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rx_coalesce_usecs_high) ++Link.RxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.rx_max_coalesced_frames_high) ++Link.TxCoalesceHighSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.tx_coalesce_usecs_high) ++Link.TxMaxCoalescedHighFrames, config_parse_coalesce_u32, 0, offsetof(LinkConfig, coalesce.tx_max_coalesced_frames_high) ++Link.CoalescePacketRateSampleIntervalSec, config_parse_coalesce_sec, 0, offsetof(LinkConfig, coalesce.rate_sample_interval) +diff --git a/test/fuzz/fuzz-link-parser/directives.link b/test/fuzz/fuzz-link-parser/directives.link +index b5cffb1a271f..8be2434665a7 100644 +--- a/test/fuzz/fuzz-link-parser/directives.link ++++ b/test/fuzz/fuzz-link-parser/directives.link +@@ -38,6 +38,11 @@ UDPSegmentationOffload= + GenericReceiveOffload= + GenericReceiveOffloadHardware= + LargeReceiveOffload= ++ReceiveVLANCTAGHardwareAcceleration= ++TransmitVLANCTAGHardwareAcceleration= ++ReceiveVLANCTAGFilter= ++TransmitVLANSTAGHardwareAcceleration= ++NTupleFilter= + RxChannels= + TxChannels= + OtherChannels= diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index e3aa251..da8cf7c 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -40,7 +40,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd %if %{without inplace} Version: 249.4 -Release: 2.1%{?dist} +Release: 2.2%{?dist} %else # determine the build information from local checkout Version: %(tools/meson-vcs-tag.sh . error | sed -r 's/-([0-9])/.^\1/; s/-g/_g/') @@ -121,6 +121,10 @@ Patch0009: https://github.com/systemd/systemd/pull/20472.patch Patch0010: https://github.com/systemd/systemd/pull/20477.patch Patch0011: https://github.com/systemd/systemd/pull/20484.patch Patch0012: https://github.com/systemd/systemd/pull/20489.patch +Patch0013: https://github.com/systemd/systemd/pull/20450.patch +Patch0014: https://github.com/systemd/systemd/pull/20541.patch +Patch0015: https://github.com/systemd/systemd/pull/20729.patch +Patch0016: https://github.com/systemd/systemd/pull/20828.patch # Downstream-only patches (0500–9999) @@ -1067,6 +1071,10 @@ fi %endif %changelog +* Fri Sep 24 2021 Anita Zhang - 249.4-2.2 +- Backport more feature support for systemd-networkd + (#20450, #20541, #20729, #20828) + * Wed Sep 22 2021 Anita Zhang - 249.4-2.1 - Sync changes from Fedora - Backport one more feature for systemd-networkd (#20489)