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

udev/net: support to set MDI-X mode

Closes #22386.
This commit is contained in:
Yu Watanabe 2022-02-04 13:06:27 +09:00 committed by Luca Boccassi
parent 74694002e6
commit 18f84f8aba
7 changed files with 100 additions and 7 deletions

View File

@ -946,6 +946,21 @@
</listitem>
</varlistentry>
<varlistentry>
<term><varname>MDI=</varname></term>
<listitem>
<para>Specifies the medium dependent interface (MDI) mode for the interface. A MDI describes
the interface from a physical layer implementation to the physical medium used to carry the
transmission. Takes one of the following words: <literal>straight</literal> (or equivalently:
<literal>mdi</literal>), <literal>crossover</literal> (or equivalently:
<literal>mdi-x</literal>, <literal>mdix</literal>), and <literal>auto</literal>. When
<literal>straight</literal>, the MDI straight through mode will be used. When
<literal>crossover</literal>, the MDI crossover (MDI-X) mode will be used. When
<literal>auto</literal>, the MDI status is automatically detected. Defaults to unset, and the
kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>SR-IOVVirtualFunctions=</varname></term>
<listitem>

View File

@ -74,6 +74,15 @@ static const char* const port_table[] = {
DEFINE_STRING_TABLE_LOOKUP(port, NetDevPort);
DEFINE_CONFIG_PARSE_ENUM(config_parse_port, port, NetDevPort, "Failed to parse Port setting");
static const char* const mdi_table[] = {
[ETH_TP_MDI_INVALID] = "unknown",
[ETH_TP_MDI] = "mdi",
[ETH_TP_MDI_X] = "mdi-x",
[ETH_TP_MDI_AUTO] = "auto",
};
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(mdi, int);
static const char* const netdev_feature_table[_NET_DEV_FEAT_MAX] = {
[NET_DEV_FEAT_SG] = "tx-scatter-gather",
[NET_DEV_FEAT_IP_CSUM] = "tx-checksum-ipv4",
@ -835,6 +844,8 @@ static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **r
.base.phy_address = ecmd.phy_address,
.base.autoneg = ecmd.autoneg,
.base.mdio_support = ecmd.mdio_support,
.base.eth_tp_mdix = ecmd.eth_tp_mdix,
.base.eth_tp_mdix_ctrl = ecmd.eth_tp_mdix_ctrl,
.link_modes.supported[0] = ecmd.supported,
.link_modes.advertising[0] = ecmd.advertising,
@ -914,7 +925,8 @@ int ethtool_set_glinksettings(
const uint32_t advertise[static N_ADVERTISE],
uint64_t speed,
Duplex duplex,
NetDevPort port) {
NetDevPort port,
uint8_t mdi) {
_cleanup_free_ struct ethtool_link_usettings *u = NULL;
struct ifreq ifr = {};
@ -926,7 +938,7 @@ int ethtool_set_glinksettings(
assert(advertise);
if (autonegotiation < 0 && memeqzero(advertise, sizeof(uint32_t) * N_ADVERTISE) &&
speed == 0 && duplex < 0 && port < 0)
speed == 0 && duplex < 0 && port < 0 && mdi == ETH_TP_MDI_INVALID)
return 0;
/* If autonegotiation is disabled, the speed and duplex represent the fixed link mode and are
@ -957,7 +969,7 @@ int ethtool_set_glinksettings(
if (r < 0) {
r = get_gset(*fd, &ifr, &u);
if (r < 0)
return log_debug_errno(r, "ethtool: Cannot get device settings for %s : %m", ifname);
return log_debug_errno(r, "ethtool: Cannot get device settings for %s: %m", ifname);
}
if (speed > 0)
@ -984,6 +996,13 @@ int ethtool_set_glinksettings(
ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES - sizeof(uint32_t) * N_ADVERTISE);
}
if (mdi != ETH_TP_MDI_INVALID) {
if (u->base.eth_tp_mdix_ctrl == ETH_TP_MDI_INVALID)
log_debug("ethtool: setting MDI not supported for %s, ignoring.", ifname);
else
UPDATE(u->base.eth_tp_mdix_ctrl, mdi, changed);
}
if (!changed)
return 0;
@ -1261,6 +1280,48 @@ int config_parse_advertise(
}
}
int config_parse_mdi(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
uint8_t *mdi = ASSERT_PTR(data);
assert(filename);
assert(rvalue);
if (isempty(rvalue)) {
*mdi = ETH_TP_MDI_INVALID;
return 0;
}
if (STR_IN_SET(rvalue, "mdi", "straight")) {
*mdi = ETH_TP_MDI;
return 0;
}
if (STR_IN_SET(rvalue, "mdi-x", "mdix", "crossover")) {
*mdi = ETH_TP_MDI_X;
return 0;
}
if (streq(rvalue, "auto")) {
*mdi = ETH_TP_MDI_AUTO;
return 0;
}
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to parse %s= setting, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
int config_parse_ring_buffer_or_channel(
const char *unit,
const char *filename,

View File

@ -168,9 +168,15 @@ int ethtool_get_permanent_hw_addr(int *ethtool_fd, const char *ifname, struct hw
int ethtool_set_wol(int *ethtool_fd, const char *ifname, uint32_t wolopts, const uint8_t password[SOPASS_MAX]);
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[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);
int ethtool_set_glinksettings(
int *fd,
const char *ifname,
int autonegotiation,
const uint32_t advertise[static N_ADVERTISE],
uint64_t speed,
Duplex duplex,
NetDevPort port,
uint8_t mdi);
int ethtool_set_channels(int *ethtool_fd, const char *ifname, const netdev_channels *channels);
int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int autoneg);
int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce);
@ -183,12 +189,15 @@ int wol_options_to_string_alloc(uint32_t opts, char **ret);
const char *port_to_string(NetDevPort port) _const_;
NetDevPort port_from_string(const char *port) _pure_;
const char *mdi_to_string(int mdi) _const_;
const char *ethtool_link_mode_bit_to_string(enum ethtool_link_mode_bit_indices val) _const_;
enum ethtool_link_mode_bit_indices ethtool_link_mode_bit_from_string(const char *str) _pure_;
CONFIG_PARSER_PROTOTYPE(config_parse_duplex);
CONFIG_PARSER_PROTOTYPE(config_parse_wol);
CONFIG_PARSER_PROTOTYPE(config_parse_port);
CONFIG_PARSER_PROTOTYPE(config_parse_mdi);
CONFIG_PARSER_PROTOTYPE(config_parse_advertise);
CONFIG_PARSER_PROTOTYPE(config_parse_ring_buffer_or_channel);
CONFIG_PARSER_PROTOTYPE(config_parse_coalesce_u32);

View File

@ -102,6 +102,7 @@ Link.RxMaxCoalescedHighFrames, config_parse_coalesce_u32,
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)
Link.MDI, config_parse_mdi, 0, offsetof(LinkConfig, mdi)
Link.SR-IOVVirtualFunctions, config_parse_sr_iov_num_vfs, 0, offsetof(LinkConfig, sr_iov_num_vfs)
SR-IOV.VirtualFunction, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)
SR-IOV.VLANId, config_parse_sr_iov_uint32, 0, offsetof(LinkConfig, sr_iov_by_section)

View File

@ -250,6 +250,7 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
.txqueuelen = UINT32_MAX,
.coalesce.use_adaptive_rx_coalesce = -1,
.coalesce.use_adaptive_tx_coalesce = -1,
.mdi = ETH_TP_MDI_INVALID,
.sr_iov_num_vfs = UINT32_MAX,
};
@ -475,7 +476,7 @@ static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
r = ethtool_set_glinksettings(ethtool_fd, name,
config->autonegotiation, config->advertise,
config->speed, config->duplex, config->port);
config->speed, config->duplex, config->port, config->mdi);
if (r < 0) {
if (config->autonegotiation >= 0)
log_link_warning_errno(link, r, "Could not %s auto negotiation, ignoring: %m",
@ -495,6 +496,10 @@ static int link_apply_ethtool_settings(Link *link, int *ethtool_fd) {
if (config->port >= 0)
log_link_warning_errno(link, r, "Could not set port to '%s', ignoring: %m",
port_to_string(config->port));
if (config->mdi != ETH_TP_MDI_INVALID)
log_link_warning_errno(link, r, "Could not set MDI-X to '%s', ignoring: %m",
mdi_to_string(config->mdi));
}
r = ethtool_set_wol(ethtool_fd, name, config->wol, config->wol_password);

View File

@ -76,6 +76,7 @@ struct LinkConfig {
int tx_flow_control;
int autoneg_flow_control;
netdev_coalesce_param coalesce;
uint8_t mdi;
uint32_t sr_iov_num_vfs;
OrderedHashmap *sr_iov_by_section;

View File

@ -80,6 +80,7 @@ RxMaxCoalescedHighFrames=
TxCoalesceHighSec=
TxMaxCoalescedHighFrames=
CoalescePacketRateSampleIntervalSec=
MDI=
SR-IOVVirtualFunctions=
[SR-IOV]
VirtualFunction=