}
static int link_update_mtu(Link *link, sd_netlink_message *message) {
- uint32_t mtu;
+ uint32_t mtu, min_mtu = 0, max_mtu = UINT32_MAX;
int r;
assert(link);
if (r < 0)
return log_link_debug_errno(link, r, "rtnl: failed to read MTU in RTM_NEWLINK message: %m");
- if (mtu == 0 || link->mtu == mtu)
+ r = sd_netlink_message_read_u32(message, IFLA_MIN_MTU, &min_mtu);
+ if (r < 0 && r != -ENODATA)
+ return log_link_debug_errno(link, r, "rtnl: failed to read minimum MTU in RTM_NEWLINK message: %m");
+
+ r = sd_netlink_message_read_u32(message, IFLA_MAX_MTU, &max_mtu);
+ if (r < 0 && r != -ENODATA)
+ return log_link_debug_errno(link, r, "rtnl: failed to read maximum MTU in RTM_NEWLINK message: %m");
+
+ if (mtu == 0)
return 0;
+ if (max_mtu == 0)
+ max_mtu = UINT32_MAX;
+
+ link->min_mtu = min_mtu;
+ link->max_mtu = max_mtu;
+
if (link->original_mtu == 0) {
link->original_mtu = mtu;
- log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu);
+ log_link_debug(link, "Saved original MTU %" PRIu32" (min: %"PRIu32", max: %"PRIu32")",
+ link->original_mtu, link->min_mtu, link->max_mtu);
}
- if (link->mtu != 0)
- log_link_debug(link, "MTU is changed: %"PRIu32" → %"PRIu32, link->mtu, mtu);
+ if (link->mtu == mtu)
+ return 0;
+
+ log_link_debug(link, "MTU is changed: %"PRIu32" → %"PRIu32" (min: %"PRIu32", max: %"PRIu32")",
+ link->mtu, mtu, link->min_mtu, link->max_mtu);
link->mtu = mtu;
int link_request_to_set_mtu(Link *link, uint32_t mtu) {
Request *req = NULL; /* avoid false maybe-uninitialized warning */
+ const char *origin;
+ uint32_t min_mtu;
int r;
assert(link);
+ assert(link->network);
+
+ min_mtu = link->min_mtu;
+ origin = "the minimum MTU of the interface";
+ if (link_ipv6_enabled(link)) {
+ /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes on the interface. Bump up
+ * MTU bytes to IPV6_MTU_MIN. */
+ if (min_mtu < IPV6_MIN_MTU) {
+ min_mtu = IPV6_MIN_MTU;
+ origin = "the minimum IPv6 MTU";
+ }
+ if (min_mtu < link->network->ipv6_mtu) {
+ min_mtu = link->network->ipv6_mtu;
+ origin = "the requested IPv6 MTU in IPv6MTUBytes=";
+ }
+ }
+
+ if (mtu < min_mtu) {
+ log_link_warning(link, "Bumping the requested MTU %"PRIu32" to %s (%"PRIu32")",
+ mtu, origin, min_mtu);
+ mtu = min_mtu;
+ }
- /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes on the interface. Bump up
- * MTU bytes to IPV6_MTU_MIN. */
- if (mtu < IPV6_MIN_MTU && link_ipv6_enabled(link)) {
- log_link_warning(link, "Bumping MTU to " STRINGIFY(IPV6_MIN_MTU) ", as IPv6 is enabled "
- "and requires a minimum MTU of " STRINGIFY(IPV6_MIN_MTU) " bytes");
- mtu = IPV6_MIN_MTU;
+ if (mtu > link->max_mtu) {
+ log_link_warning(link, "Reducing the requested MTU %"PRIu32" to the interface's maximum MTU %"PRIu32".",
+ mtu, link->max_mtu);
+ mtu = link->max_mtu;
}
if (link->mtu == mtu)