summaryrefslogtreecommitdiffstats
path: root/src/network/networkd-setlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/networkd-setlink.c')
-rw-r--r--src/network/networkd-setlink.c171
1 files changed, 93 insertions, 78 deletions
diff --git a/src/network/networkd-setlink.c b/src/network/networkd-setlink.c
index 011ea1f..058bc00 100644
--- a/src/network/networkd-setlink.c
+++ b/src/network/networkd-setlink.c
@@ -103,6 +103,19 @@ static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Requ
}
static int link_set_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
+ int r;
+
+ assert(link);
+
+ r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
+ if (r <= 0)
+ return r;
+
+ link->bridge_vlan_set = true;
+ return 0;
+}
+
+static int link_del_bridge_vlan_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ false, NULL);
}
@@ -160,19 +173,7 @@ static int link_unset_master_handler(sd_netlink *rtnl, sd_netlink_message *m, Re
}
static int link_set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Request *req, Link *link, void *userdata) {
- int r;
-
- r = set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
- if (r <= 0)
- return r;
-
- /* The kernel resets ipv6 mtu after changing device mtu;
- * we must set this here, after we've set device mtu */
- r = link_set_ipv6_mtu(link);
- if (r < 0)
- log_link_warning_errno(link, r, "Failed to set IPv6 MTU, ignoring: %m");
-
- return 0;
+ return set_link_handler_internal(rtnl, m, req, link, /* ignore = */ true, get_link_default_handler);
}
static int link_configure_fill_message(
@@ -326,29 +327,14 @@ static int link_configure_fill_message(
return r;
break;
case REQUEST_TYPE_SET_LINK_BRIDGE_VLAN:
- r = sd_rtnl_message_link_set_family(req, AF_BRIDGE);
- if (r < 0)
- return r;
-
- r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
+ r = bridge_vlan_set_message(link, req, /* is_set = */ true);
if (r < 0)
return r;
-
- if (link->master_ifindex <= 0) {
- /* master needs BRIDGE_FLAGS_SELF flag */
- r = sd_netlink_message_append_u16(req, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF);
- if (r < 0)
- return r;
- }
-
- r = bridge_vlan_append_info(link, req, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap);
- if (r < 0)
- return r;
-
- r = sd_netlink_message_close_container(req);
+ break;
+ case REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN:
+ r = bridge_vlan_set_message(link, req, /* is_set = */ false);
if (r < 0)
return r;
-
break;
case REQUEST_TYPE_SET_LINK_CAN:
r = can_set_netlink_message(link, req);
@@ -430,6 +416,8 @@ static int link_configure(Link *link, Request *req) {
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->master_ifindex);
else if (IN_SET(req->type, REQUEST_TYPE_SET_LINK_CAN, REQUEST_TYPE_SET_LINK_IPOIB))
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
+ else if (req->type == REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN)
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_DELLINK, link->ifindex);
else
r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_SETLINK, link->ifindex);
if (r < 0)
@@ -453,6 +441,43 @@ static bool netdev_is_ready(NetDev *netdev) {
return true;
}
+static uint32_t link_adjust_mtu(Link *link, uint32_t mtu) {
+ const char *origin;
+ uint32_t min_mtu;
+
+ 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;
+ }
+
+ 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;
+ }
+
+ return mtu;
+}
+
static int link_is_ready_to_set_link(Link *link, Request *req) {
int r;
@@ -480,9 +505,11 @@ static int link_is_ready_to_set_link(Link *link, Request *req) {
if (link->network->keep_master && link->master_ifindex <= 0 && !streq_ptr(link->kind, "bridge"))
return false;
-
break;
+ case REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN:
+ return link->bridge_vlan_set;
+
case REQUEST_TYPE_SET_LINK_CAN:
/* Do not check link->set_flags_messages here, as it is ok even if link->flags
* is outdated, and checking the counter causes a deadlock. */
@@ -568,13 +595,24 @@ static int link_is_ready_to_set_link(Link *link, Request *req) {
}))
return false;
- /* Changing FD mode may affect MTU. */
+ /* Changing FD mode may affect MTU.
+ * See https://docs.kernel.org/networking/can.html#can-fd-flexible-data-rate-driver-support
+ * MTU = 16 (CAN_MTU) => Classical CAN device
+ * MTU = 72 (CANFD_MTU) => CAN FD capable device */
if (ordered_set_contains(link->manager->request_queue,
&(const Request) {
.link = link,
.type = REQUEST_TYPE_SET_LINK_CAN,
}))
return false;
+
+ /* Now, it is ready to set MTU, but before setting, adjust requested MTU. */
+ uint32_t mtu = link_adjust_mtu(link, PTR_TO_UINT32(req->userdata));
+ if (mtu == link->mtu)
+ return -EALREADY; /* Not necessary to set the same value. */
+
+ req->userdata = UINT32_TO_PTR(mtu);
+ return true;
}
default:
break;
@@ -712,10 +750,14 @@ int link_request_to_set_bridge(Link *link) {
}
int link_request_to_set_bridge_vlan(Link *link) {
+ int r;
+
assert(link);
assert(link->network);
- if (!link->network->use_br_vlan)
+ /* If nothing configured, use the default vlan ID. */
+ if (memeqzero(link->network->bridge_vlan_bitmap, BRIDGE_VLAN_BITMAP_LEN * sizeof(uint32_t)) &&
+ link->network->bridge_vlan_pvid == BRIDGE_VLAN_KEEP_PVID)
return 0;
if (!link->network->bridge && !streq_ptr(link->kind, "bridge")) {
@@ -731,9 +773,21 @@ int link_request_to_set_bridge_vlan(Link *link) {
return 0;
}
- return link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE_VLAN,
- link_set_bridge_vlan_handler,
- NULL);
+ link->bridge_vlan_set = false;
+
+ r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_BRIDGE_VLAN,
+ link_set_bridge_vlan_handler,
+ NULL);
+ if (r < 0)
+ return r;
+
+ r = link_request_set_link(link, REQUEST_TYPE_DEL_LINK_BRIDGE_VLAN,
+ link_del_bridge_vlan_handler,
+ NULL);
+ if (r < 0)
+ return r;
+
+ return 0;
}
int link_request_to_set_can(Link *link) {
@@ -847,51 +901,12 @@ int link_request_to_set_master(Link *link) {
}
int link_request_to_set_mtu(Link *link, uint32_t mtu) {
- const char *origin;
- uint32_t min_mtu, max_mtu;
Request *req;
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;
- }
-
- max_mtu = link->max_mtu;
- if (link->iftype == ARPHRD_CAN)
- /* The maximum MTU may be changed when FD mode is changed.
- * See https://docs.kernel.org/networking/can.html#can-fd-flexible-data-rate-driver-support
- * MTU = 16 (CAN_MTU) => Classical CAN device
- * MTU = 72 (CANFD_MTU) => CAN FD capable device
- * So, even if the current maximum is 16, we should not reduce the requested value now. */
- max_mtu = MAX(max_mtu, 72u);
-
- if (mtu > max_mtu) {
- log_link_warning(link, "Reducing the requested MTU %"PRIu32" to the interface's maximum MTU %"PRIu32".",
- mtu, max_mtu);
- mtu = max_mtu;
- }
- if (link->mtu == mtu)
+ if (mtu == 0)
return 0;
r = link_request_set_link(link, REQUEST_TYPE_SET_LINK_MTU,