mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
parent
53e1ba280f
commit
bf2334c054
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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])
|
||||
|
@ -26,6 +26,8 @@ Duplex=
|
||||
AutoNegotiation=
|
||||
WakeOnLan=
|
||||
Port=
|
||||
ReceiveChecksumOffload=
|
||||
TransmitChecksumOffload=
|
||||
GenericSegmentationOffload=
|
||||
TCPSegmentationOffload=
|
||||
TCP6SegmentationOffload=
|
||||
|
Loading…
Reference in New Issue
Block a user