mirror of
https://github.com/systemd/systemd.git
synced 2025-03-25 18:50:18 +03:00
Merge pull request #8776 from poettering/mtu-cleanup
networkd/udev: clean up parsing and handling of MTU values
This commit is contained in:
commit
cd81a8fc82
@ -1057,6 +1057,10 @@ struct input_mask {
|
||||
#define IPV6_MIN_MTU 1280
|
||||
#endif
|
||||
|
||||
#ifndef IPV4_MIN_MTU
|
||||
#define IPV4_MIN_MTU 68
|
||||
#endif
|
||||
|
||||
#ifndef IFF_MULTI_QUEUE
|
||||
#define IFF_MULTI_QUEUE 0x100
|
||||
#endif
|
||||
|
@ -11,12 +11,14 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "errno-list.h"
|
||||
#include "extract-word.h"
|
||||
#include "locale-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
@ -93,6 +95,30 @@ int parse_ifindex(const char *s, int *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_mtu(int family, const char *s, uint32_t *ret) {
|
||||
uint64_t u;
|
||||
size_t m;
|
||||
int r;
|
||||
|
||||
r = parse_size(s, 1024, &u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (u > UINT32_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
if (family == AF_INET6)
|
||||
m = IPV6_MIN_MTU; /* This is 1280 */
|
||||
else
|
||||
m = IPV4_MIN_MTU; /* For all other protocols, including 'unspecified' we assume the IPv4 minimal MTU */
|
||||
|
||||
if (u < m)
|
||||
return -ERANGE;
|
||||
|
||||
*ret = (uint32_t) u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_size(const char *t, uint64_t base, uint64_t *size) {
|
||||
|
||||
/* Soo, sometimes we want to parse IEC binary suffixes, and
|
||||
|
@ -22,6 +22,7 @@ int parse_dev(const char *s, dev_t *ret);
|
||||
int parse_pid(const char *s, pid_t* ret_pid);
|
||||
int parse_mode(const char *s, mode_t *ret);
|
||||
int parse_ifindex(const char *s, int *ret);
|
||||
int parse_mtu(int family, const char *s, uint32_t *ret);
|
||||
|
||||
int parse_size(const char *t, uint64_t base, uint64_t *size);
|
||||
int parse_range(const char *t, unsigned *lower, unsigned *upper);
|
||||
|
@ -40,7 +40,7 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
|
||||
}
|
||||
|
||||
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
|
||||
const struct ether_addr *mac, unsigned mtu) {
|
||||
const struct ether_addr *mac, uint32_t mtu) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
|
||||
int r;
|
||||
|
||||
@ -72,7 +72,7 @@ int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
|
||||
return r;
|
||||
}
|
||||
|
||||
if (mtu > 0) {
|
||||
if (mtu != 0) {
|
||||
r = sd_netlink_message_append_u32(message, IFLA_MTU, mtu);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -40,7 +40,7 @@ static inline bool rtnl_message_type_is_routing_policy_rule(uint16_t type) {
|
||||
}
|
||||
|
||||
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
|
||||
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, unsigned mtu);
|
||||
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu);
|
||||
|
||||
int rtnl_log_parse_error(int r);
|
||||
int rtnl_log_create_error(int r);
|
||||
|
@ -40,7 +40,7 @@ static void test_link_configure(sd_netlink *rtnl, int ifindex) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
|
||||
const char *mac = "98:fe:94:3f:c6:18", *name = "test";
|
||||
char buffer[ETHER_ADDR_TO_STRING_MAX];
|
||||
unsigned int mtu = 1450, mtu_out;
|
||||
uint32_t mtu = 1450, mtu_out;
|
||||
const char *name_out;
|
||||
struct ether_addr mac_out;
|
||||
|
||||
@ -66,7 +66,7 @@ static void test_link_configure(sd_netlink *rtnl, int ifindex) {
|
||||
static void test_link_get(sd_netlink *rtnl, int ifindex) {
|
||||
sd_netlink_message *m;
|
||||
sd_netlink_message *r;
|
||||
unsigned int mtu = 1500;
|
||||
uint32_t mtu = 1500;
|
||||
const char *str_data;
|
||||
uint8_t u8_data;
|
||||
uint32_t u32_data;
|
||||
|
@ -66,7 +66,7 @@ static int netdev_geneve_create(NetDev *netdev) {
|
||||
return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m");
|
||||
}
|
||||
|
||||
if (netdev->mtu) {
|
||||
if (netdev->mtu != 0) {
|
||||
r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m");
|
||||
|
@ -40,7 +40,7 @@ Match.Architecture, config_parse_net_condition, CONDITI
|
||||
NetDev.Description, config_parse_string, 0, offsetof(NetDev, description)
|
||||
NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname)
|
||||
NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind)
|
||||
NetDev.MTUBytes, config_parse_iec_size, 0, offsetof(NetDev, mtu)
|
||||
NetDev.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(NetDev, mtu)
|
||||
NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac)
|
||||
VLAN.Id, config_parse_vlanid, 0, offsetof(VLan, id)
|
||||
VLAN.GVRP, config_parse_tristate, 0, offsetof(VLan, gvrp)
|
||||
@ -50,7 +50,7 @@ VLAN.ReorderHeader, config_parse_tristate, 0,
|
||||
MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
|
||||
MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
|
||||
IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)
|
||||
IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags)
|
||||
IPVLAN.Flags, config_parse_ipvlan_flags, 0, offsetof(IPVlan, flags)
|
||||
Tunnel.Local, config_parse_tunnel_address, 0, offsetof(Tunnel, local)
|
||||
Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(Tunnel, remote)
|
||||
Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos)
|
||||
|
@ -91,7 +91,7 @@ typedef struct NetDev {
|
||||
char *description;
|
||||
char *ifname;
|
||||
struct ether_addr *mac;
|
||||
size_t mtu;
|
||||
uint32_t mtu;
|
||||
int ifindex;
|
||||
|
||||
LIST_HEAD(netdev_join_callback, callbacks);
|
||||
|
@ -144,7 +144,7 @@ static void tuntap_done(NetDev *netdev) {
|
||||
static int tuntap_verify(NetDev *netdev, const char *filename) {
|
||||
assert(netdev);
|
||||
|
||||
if (netdev->mtu)
|
||||
if (netdev->mtu != 0)
|
||||
log_netdev_warning(netdev, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev->kind));
|
||||
|
||||
if (netdev->mac)
|
||||
|
@ -821,7 +821,7 @@ static int link_status_one(
|
||||
}
|
||||
|
||||
if (info->has_mtu)
|
||||
printf(" MTU: %u\n", info->mtu);
|
||||
printf(" MTU: %" PRIu32 "\n", info->mtu);
|
||||
|
||||
(void) dump_addresses(rtnl, " Address: ", info->ifindex);
|
||||
(void) dump_gateways(rtnl, hwdb, " Gateway: ", info->ifindex);
|
||||
|
@ -1757,7 +1757,7 @@ int link_up(Link *link) {
|
||||
for this interface, or if it is a bridge slave, then disable IPv6 else enable it. */
|
||||
(void) link_enable_ipv6(link);
|
||||
|
||||
if (link->network->mtu) {
|
||||
if (link->network->mtu != 0) {
|
||||
/* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes
|
||||
on the interface. Bump up MTU bytes to IPV6_MTU_MIN. */
|
||||
if (link_ipv6_enabled(link) && link->network->mtu < IPV6_MIN_MTU) {
|
||||
@ -2486,7 +2486,7 @@ static int link_set_ipv6_mtu(Link *link) {
|
||||
|
||||
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/mtu");
|
||||
|
||||
xsprintf(buf, "%u", link->network->ipv6_mtu);
|
||||
xsprintf(buf, "%" PRIu32, link->network->ipv6_mtu);
|
||||
|
||||
r = write_string_file(p, buf, 0);
|
||||
if (r < 0)
|
||||
@ -3229,7 +3229,7 @@ int link_update(Link *link, sd_netlink_message *m) {
|
||||
r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
|
||||
if (r >= 0 && mtu > 0) {
|
||||
link->mtu = mtu;
|
||||
if (!link->original_mtu) {
|
||||
if (link->original_mtu == 0) {
|
||||
link->original_mtu = mtu;
|
||||
log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ typedef struct Link {
|
||||
sd_dhcp_client *dhcp_client;
|
||||
sd_dhcp_lease *dhcp_lease;
|
||||
char *lease_file;
|
||||
uint16_t original_mtu;
|
||||
uint32_t original_mtu;
|
||||
unsigned dhcp4_messages;
|
||||
bool dhcp4_configured;
|
||||
bool dhcp6_configured;
|
||||
|
@ -31,7 +31,7 @@ Match.KernelCommandLine, config_parse_net_condition,
|
||||
Match.KernelVersion, config_parse_net_condition, CONDITION_KERNEL_VERSION, offsetof(Network, match_kernel_version)
|
||||
Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch)
|
||||
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
|
||||
Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu)
|
||||
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(Network, mtu)
|
||||
Link.ARP, config_parse_tristate, 0, offsetof(Network, arp)
|
||||
Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged)
|
||||
Link.RequiredForOnline, config_parse_bool, 0, offsetof(Network, required_for_online)
|
||||
@ -69,7 +69,7 @@ Network.IPv6AcceptRouterAdvertisements, config_parse_tristate,
|
||||
Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits)
|
||||
Network.IPv6HopLimit, config_parse_int, 0, offsetof(Network, ipv6_hop_limit)
|
||||
Network.IPv6ProxyNDP, config_parse_tristate, 0, offsetof(Network, ipv6_proxy_ndp)
|
||||
Network.IPv6MTUBytes, config_parse_ipv6_mtu, 0, 0
|
||||
Network.IPv6MTUBytes, config_parse_mtu, AF_INET6, 0
|
||||
Network.ActiveSlave, config_parse_bool, 0, offsetof(Network, active_slave)
|
||||
Network.PrimarySlave, config_parse_bool, 0, offsetof(Network, primary_slave)
|
||||
Network.IPv4ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp)
|
||||
|
@ -1417,42 +1417,6 @@ int config_parse_dhcp_route_table(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_ipv6_mtu(
|
||||
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) {
|
||||
|
||||
Network *network = data;
|
||||
uint32_t mtu;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
r = safe_atou32(rvalue, &mtu);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 MTU, ignoring assignment: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mtu < IPV6_MIN_MTU) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 MTU for interface. Allowed minimum MTU is 1280 bytes, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
network->ipv6_mtu = mtu;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting");
|
||||
|
||||
static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
|
||||
|
@ -33,8 +33,6 @@
|
||||
#define BRIDGE_VLAN_BITMAP_MAX 4096
|
||||
#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32)
|
||||
|
||||
#define IPV6_MIN_MTU 1280
|
||||
|
||||
typedef enum DHCPClientIdentifier {
|
||||
DHCP_CLIENT_ID_MAC,
|
||||
DHCP_CLIENT_ID_DUID,
|
||||
@ -200,7 +198,7 @@ struct Network {
|
||||
int ipv6_hop_limit;
|
||||
int ipv6_proxy_ndp;
|
||||
int proxy_arp;
|
||||
unsigned ipv6_mtu;
|
||||
uint32_t ipv6_mtu;
|
||||
|
||||
bool ipv6_accept_ra_use_dns;
|
||||
bool active_slave;
|
||||
@ -212,7 +210,7 @@ struct Network {
|
||||
IPv6PrivacyExtensions ipv6_privacy_extensions;
|
||||
|
||||
struct ether_addr *mac;
|
||||
size_t mtu;
|
||||
uint32_t mtu;
|
||||
int arp;
|
||||
bool unmanaged;
|
||||
bool configure_without_carrier;
|
||||
@ -292,7 +290,6 @@ int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsign
|
||||
int config_parse_lldp_mode(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);
|
||||
int config_parse_dhcp_route_table(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);
|
||||
int config_parse_ntp(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);
|
||||
int config_parse_ipv6_mtu(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);
|
||||
/* Legacy IPv4LL support */
|
||||
int config_parse_ipv4ll(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);
|
||||
|
||||
|
@ -1158,3 +1158,38 @@ int config_parse_join_controllers(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_mtu(
|
||||
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) {
|
||||
|
||||
uint32_t *mtu = data;
|
||||
int r;
|
||||
|
||||
assert(rvalue);
|
||||
assert(mtu);
|
||||
|
||||
r = parse_mtu(ltype, rvalue, mtu);
|
||||
if (r == -ERANGE) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Maximum transfer unit (MTU) value out of range. Permitted range is %" PRIu32 "…%" PRIu32 ", ignoring: %s",
|
||||
(uint32_t) (ltype == AF_INET6 ? IPV6_MIN_MTU : IPV4_MIN_MTU), (uint32_t) UINT32_MAX,
|
||||
rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to parse MTU value '%s', ignoring: %m", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -146,6 +146,7 @@ int config_parse_personality(GENERIC_PARSER_ARGS);
|
||||
int config_parse_ifname(GENERIC_PARSER_ARGS);
|
||||
int config_parse_ip_port(GENERIC_PARSER_ARGS);
|
||||
int config_parse_join_controllers(GENERIC_PARSER_ARGS);
|
||||
int config_parse_mtu(GENERIC_PARSER_ARGS);
|
||||
|
||||
typedef enum Disabled {
|
||||
DISABLED_CONFIGURATION,
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <math.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "errno-list.h"
|
||||
@ -757,6 +758,27 @@ static void test_parse_syscall_and_errno(void) {
|
||||
assert_se(parse_syscall_and_errno("hoge:", &n, &e) == -EINVAL);
|
||||
}
|
||||
|
||||
static void test_parse_mtu(void) {
|
||||
uint32_t mtu = 0;
|
||||
|
||||
assert_se(parse_mtu(AF_UNSPEC, "1500", &mtu) >= 0 && mtu == 1500);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "1400", &mtu) >= 0 && mtu == 1400);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "65535", &mtu) >= 0 && mtu == 65535);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "65536", &mtu) >= 0 && mtu == 65536);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "4294967295", &mtu) >= 0 && mtu == 4294967295);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "500", &mtu) >= 0 && mtu == 500);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "1280", &mtu) >= 0 && mtu == 1280);
|
||||
assert_se(parse_mtu(AF_INET6, "1280", &mtu) >= 0 && mtu == 1280);
|
||||
assert_se(parse_mtu(AF_INET6, "1279", &mtu) == -ERANGE);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "4294967296", &mtu) == -ERANGE);
|
||||
assert_se(parse_mtu(AF_INET6, "4294967296", &mtu) == -ERANGE);
|
||||
assert_se(parse_mtu(AF_INET6, "68", &mtu) == -ERANGE);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "68", &mtu) >= 0 && mtu == 68);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "67", &mtu) == -ERANGE);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "0", &mtu) == -ERANGE);
|
||||
assert_se(parse_mtu(AF_UNSPEC, "", &mtu) == -EINVAL);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
@ -779,6 +801,7 @@ int main(int argc, char *argv[]) {
|
||||
test_parse_dev();
|
||||
test_parse_errno();
|
||||
test_parse_syscall_and_errno();
|
||||
test_parse_mtu();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ Link.MACAddress, config_parse_hwaddr, 0,
|
||||
Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy)
|
||||
Link.Name, config_parse_ifname, 0, offsetof(link_config, name)
|
||||
Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
|
||||
Link.MTUBytes, config_parse_iec_size, 0, offsetof(link_config, mtu)
|
||||
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
|
||||
Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed)
|
||||
Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)
|
||||
Link.AutoNegotiation, config_parse_tristate, 0, offsetof(link_config, autonegotiation)
|
||||
|
@ -169,7 +169,7 @@ static int load_link(link_config_ctx *ctx, const char *filename) {
|
||||
else
|
||||
log_debug("Parsed configuration file %s", filename);
|
||||
|
||||
if (link->mtu > UINT_MAX || link->speed > UINT_MAX)
|
||||
if (link->speed > UINT_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
link->filename = strdup(filename);
|
||||
@ -466,7 +466,7 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
|
||||
|
||||
r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Could not set Alias, MACAddress or MTU on %s: %m", old_name);
|
||||
return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name);
|
||||
|
||||
*name = new_name;
|
||||
|
||||
|
@ -55,7 +55,7 @@ struct link_config {
|
||||
NamePolicy *name_policy;
|
||||
char *name;
|
||||
char *alias;
|
||||
size_t mtu;
|
||||
uint32_t mtu;
|
||||
size_t speed;
|
||||
Duplex duplex;
|
||||
int autonegotiation;
|
||||
|
Loading…
x
Reference in New Issue
Block a user