summaryrefslogtreecommitdiffstats
path: root/src/network/networkd-link.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/networkd-link.c')
-rw-r--r--src/network/networkd-link.c358
1 files changed, 280 insertions, 78 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 4ef1be4..6b0f099 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/* Make sure the net/if.h header is included before any linux/ one */
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if.h>
@@ -17,7 +18,6 @@
#include "bus-util.h"
#include "device-private.h"
#include "device-util.h"
-#include "dhcp-identifier.h"
#include "dhcp-lease-internal.h"
#include "env-file.h"
#include "ethtool-util.h"
@@ -35,6 +35,7 @@
#include "networkd-address.h"
#include "networkd-bridge-fdb.h"
#include "networkd-bridge-mdb.h"
+#include "networkd-bridge-vlan.h"
#include "networkd-can.h"
#include "networkd-dhcp-prefix-delegation.h"
#include "networkd-dhcp-server.h"
@@ -71,6 +72,53 @@
#include "udev-util.h"
#include "vrf.h"
+void link_required_operstate_for_online(Link *link, LinkOperationalStateRange *ret) {
+ assert(link);
+ assert(ret);
+
+ if (link->network && operational_state_range_is_valid(&link->network->required_operstate_for_online))
+ /* If explicitly specified, use it as is. */
+ *ret = link->network->required_operstate_for_online;
+ else if (link->iftype == ARPHRD_CAN)
+ /* CAN devices do not support addressing, hence defaults to 'carrier'. */
+ *ret = (const LinkOperationalStateRange) {
+ .min = LINK_OPERSTATE_CARRIER,
+ .max = LINK_OPERSTATE_CARRIER,
+ };
+ else if (link->network && link->network->bond)
+ /* Bonding slaves do not support addressing. */
+ *ret = (const LinkOperationalStateRange) {
+ .min = LINK_OPERSTATE_ENSLAVED,
+ .max = LINK_OPERSTATE_ENSLAVED,
+ };
+ else if (STRPTR_IN_SET(link->kind, "batadv", "bond", "bridge", "vrf"))
+ /* Some of slave interfaces may be offline. */
+ *ret = (const LinkOperationalStateRange) {
+ .min = LINK_OPERSTATE_DEGRADED_CARRIER,
+ .max = LINK_OPERSTATE_ROUTABLE,
+ };
+ else
+ *ret = LINK_OPERSTATE_RANGE_DEFAULT;
+}
+
+AddressFamily link_required_family_for_online(Link *link) {
+ assert(link);
+
+ if (link->network && link->network->required_family_for_online >= 0)
+ return link->network->required_family_for_online;
+
+ if (link->network && operational_state_range_is_valid(&link->network->required_operstate_for_online))
+ /* If RequiredForOnline= is explicitly specified, defaults to no. */
+ return ADDRESS_FAMILY_NO;
+
+ if (STRPTR_IN_SET(link->kind, "batadv", "bond", "bridge", "vrf"))
+ /* As the minimum required operstate for master interfaces is 'degraded-carrier',
+ * we should request an address assigned to the link for backward compatibility. */
+ return ADDRESS_FAMILY_YES;
+
+ return ADDRESS_FAMILY_NO;
+}
+
bool link_ipv6_enabled(Link *link) {
assert(link);
@@ -207,8 +255,6 @@ static Link *link_free(Link *link) {
link_ntp_settings_clear(link);
link_dns_settings_clear(link);
- link->routes = set_free(link->routes);
- link->nexthops = set_free(link->nexthops);
link->neighbors = set_free(link->neighbors);
link->addresses = set_free(link->addresses);
link->qdiscs = set_free(link->qdiscs);
@@ -227,7 +273,6 @@ static Link *link_free(Link *link) {
free(link->driver);
unlink_and_free(link->lease_file);
- unlink_and_free(link->lldp_file);
unlink_and_free(link->state_file);
sd_device_unref(link->dev);
@@ -251,7 +296,9 @@ int link_get_by_index(Manager *m, int ifindex, Link **ret) {
Link *link;
assert(m);
- assert(ifindex > 0);
+
+ if (ifindex <= 0)
+ return -EINVAL;
link = hashmap_get(m->links_by_index, INT_TO_PTR(ifindex));
if (!link)
@@ -320,7 +367,7 @@ void link_set_state(Link *link, LinkState state) {
}
int link_stop_engines(Link *link, bool may_keep_dhcp) {
- int r = 0, k;
+ int r, ret = 0;
assert(link);
assert(link->manager);
@@ -333,53 +380,55 @@ int link_stop_engines(Link *link, bool may_keep_dhcp) {
FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP_ON_STOP));
if (!keep_dhcp) {
- k = sd_dhcp_client_stop(link->dhcp_client);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop DHCPv4 client: %m");
+ r = sd_dhcp_client_stop(link->dhcp_client);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m"));
}
- k = sd_dhcp_server_stop(link->dhcp_server);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop DHCPv4 server: %m");
+ r = sd_dhcp_server_stop(link->dhcp_server);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop DHCPv4 server: %m"));
- k = sd_lldp_rx_stop(link->lldp_rx);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop LLDP Rx: %m");
+ r = sd_lldp_rx_stop(link->lldp_rx);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop LLDP Rx: %m"));
- k = sd_lldp_tx_stop(link->lldp_tx);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop LLDP Tx: %m");
+ r = sd_lldp_tx_stop(link->lldp_tx);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop LLDP Tx: %m"));
- k = sd_ipv4ll_stop(link->ipv4ll);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m");
+ r = sd_ipv4ll_stop(link->ipv4ll);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m"));
- k = ipv4acd_stop(link);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop IPv4 ACD client: %m");
+ r = ipv4acd_stop(link);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop IPv4 ACD client: %m"));
- k = sd_dhcp6_client_stop(link->dhcp6_client);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m");
+ r = sd_dhcp6_client_stop(link->dhcp6_client);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m"));
- k = dhcp_pd_remove(link, /* only_marked = */ false);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not remove DHCPv6 PD addresses and routes: %m");
+ r = dhcp_pd_remove(link, /* only_marked = */ false);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not remove DHCPv6 PD addresses and routes: %m"));
- k = ndisc_stop(link);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m");
+ r = ndisc_stop(link);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m"));
ndisc_flush(link);
- k = sd_radv_stop(link->radv);
- if (k < 0)
- r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Advertisement: %m");
+ r = sd_radv_stop(link->radv);
+ if (r < 0)
+ RET_GATHER(ret, log_link_warning_errno(link, r, "Could not stop IPv6 Router Advertisement: %m"));
- return r;
+ return ret;
}
void link_enter_failed(Link *link) {
+ int r;
+
assert(link);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
@@ -389,7 +438,22 @@ void link_enter_failed(Link *link) {
link_set_state(link, LINK_STATE_FAILED);
- (void) link_stop_engines(link, false);
+ if (!ratelimit_below(&link->automatic_reconfigure_ratelimit)) {
+ log_link_warning(link, "The interface entered the failed state frequently, refusing to reconfigure it automatically.");
+ goto stop;
+ }
+
+ log_link_info(link, "Trying to reconfigure the interface.");
+ r = link_reconfigure(link, /* force = */ true);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
+ goto stop;
+ }
+
+ return;
+
+stop:
+ (void) link_stop_engines(link, /* may_keep_dhcp = */ false);
}
void link_check_ready(Link *link) {
@@ -415,11 +479,9 @@ void link_check_ready(Link *link) {
if (!link->activated)
return (void) log_link_debug(link, "%s(): link is not activated.", __func__);
- if (link->iftype == ARPHRD_CAN) {
+ if (link->iftype == ARPHRD_CAN)
/* let's shortcut things for CAN which doesn't need most of checks below. */
- link_set_state(link, LINK_STATE_CONFIGURED);
- return;
- }
+ goto ready;
if (!link->stacked_netdevs_created)
return (void) log_link_debug(link, "%s(): stacked netdevs are not created.", __func__);
@@ -479,7 +541,7 @@ void link_check_ready(Link *link) {
* Note, ignore NDisc when ConfigureWithoutCarrier= is enabled, as IPv6AcceptRA= is enabled by default. */
if (!link_ipv4ll_enabled(link) && !link_dhcp4_enabled(link) &&
!link_dhcp6_enabled(link) && !link_dhcp_pd_is_enabled(link) &&
- (link->network->configure_without_carrier || !link_ipv6_accept_ra_enabled(link)))
+ (link->network->configure_without_carrier || !link_ndisc_enabled(link)))
goto ready;
bool ipv4ll_ready =
@@ -497,8 +559,8 @@ void link_check_ready(Link *link) {
(!link->network->dhcp_pd_assign ||
link_check_addresses_ready(link, NETWORK_CONFIG_SOURCE_DHCP_PD));
bool ndisc_ready =
- link_ipv6_accept_ra_enabled(link) && link->ndisc_configured &&
- (!link->network->ipv6_accept_ra_use_autonomous_prefix ||
+ link_ndisc_enabled(link) && link->ndisc_configured &&
+ (!link->network->ndisc_use_autonomous_prefix ||
link_check_addresses_ready(link, NETWORK_CONFIG_SOURCE_NDISC));
/* If the uplink for PD is self, then request the corresponding DHCP protocol is also ready. */
@@ -652,11 +714,9 @@ static int link_acquire_dynamic_ipv4_conf(Link *link) {
log_link_debug(link, "Acquiring IPv4 link-local address.");
}
- if (link->dhcp_server) {
- r = sd_dhcp_server_start(link->dhcp_server);
- if (r < 0)
- return log_link_warning_errno(link, r, "Could not start DHCP server: %m");
- }
+ r = link_start_dhcp4_server(link);
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not start DHCP server: %m");
r = ipv4acd_start(link);
if (r < 0)
@@ -930,15 +990,58 @@ static void link_drop_from_master(Link *link) {
link_unref(set_remove(master->slaves, link));
}
-static void link_drop_requests(Link *link) {
+static int link_drop_requests(Link *link) {
Request *req;
+ int ret = 0;
assert(link);
assert(link->manager);
- ORDERED_SET_FOREACH(req, link->manager->request_queue)
- if (req->link == link)
- request_detach(link->manager, req);
+ ORDERED_SET_FOREACH(req, link->manager->request_queue) {
+ if (req->link != link)
+ continue;
+
+ /* If the request is already called, but its reply is not received, then we need to
+ * drop the configuration (e.g. address) here. Note, if the configuration is known,
+ * it will be handled later by link_drop_foreign_addresses() or so. */
+ if (req->waiting_reply && link->state != LINK_STATE_LINGER)
+ switch (req->type) {
+ case REQUEST_TYPE_ADDRESS: {
+ Address *address = ASSERT_PTR(req->userdata);
+
+ if (address_get(link, address, NULL) < 0)
+ RET_GATHER(ret, address_remove(address, link));
+ break;
+ }
+ case REQUEST_TYPE_NEIGHBOR: {
+ Neighbor *neighbor = ASSERT_PTR(req->userdata);
+
+ if (neighbor_get(link, neighbor, NULL) < 0)
+ RET_GATHER(ret, neighbor_remove(neighbor, link));
+ break;
+ }
+ case REQUEST_TYPE_NEXTHOP: {
+ NextHop *nexthop = ASSERT_PTR(req->userdata);
+
+ if (nexthop_get_by_id(link->manager, nexthop->id, NULL) < 0)
+ RET_GATHER(ret, nexthop_remove(nexthop, link->manager));
+ break;
+ }
+ case REQUEST_TYPE_ROUTE: {
+ Route *route = ASSERT_PTR(req->userdata);
+
+ if (route_get(link->manager, route, NULL) < 0)
+ RET_GATHER(ret, route_remove(route, link->manager));
+ break;
+ }
+ default:
+ ;
+ }
+
+ request_detach(req);
+ }
+
+ return ret;
}
static Link *link_drop(Link *link) {
@@ -952,7 +1055,7 @@ static Link *link_drop(Link *link) {
/* Drop all references from other links and manager. Note that async netlink calls may have
* references to the link, and they will be dropped when we receive replies. */
- link_drop_requests(link);
+ (void) link_drop_requests(link);
link_free_bound_to_list(link);
link_free_bound_by_list(link);
@@ -1010,12 +1113,11 @@ static int link_drop_managed_config(Link *link) {
assert(link);
assert(link->manager);
- r = link_drop_managed_routes(link);
-
- RET_GATHER(r, link_drop_managed_nexthops(link));
- RET_GATHER(r, link_drop_managed_addresses(link));
- RET_GATHER(r, link_drop_managed_neighbors(link));
- RET_GATHER(r, link_drop_managed_routing_policy_rules(link));
+ r = link_drop_static_routes(link);
+ RET_GATHER(r, link_drop_static_nexthops(link));
+ RET_GATHER(r, link_drop_static_addresses(link));
+ RET_GATHER(r, link_drop_static_neighbors(link));
+ RET_GATHER(r, link_drop_static_routing_policy_rules(link));
return r;
}
@@ -1239,10 +1341,20 @@ int link_reconfigure_impl(Link *link, bool force) {
return 0;
if (network) {
+ _cleanup_free_ char *joined = strv_join(network->dropins, ", ");
+
if (link->state == LINK_STATE_INITIALIZED)
- log_link_info(link, "Configuring with %s.", network->filename);
+ log_link_info(link, "Configuring with %s%s%s%s.",
+ network->filename,
+ isempty(joined) ? "" : " (dropins: ",
+ joined,
+ isempty(joined) ? "" : ")");
else
- log_link_info(link, "Reconfiguring with %s.", network->filename);
+ log_link_info(link, "Reconfiguring with %s%s%s%s.",
+ network->filename,
+ isempty(joined) ? "" : " (dropins: ",
+ joined,
+ isempty(joined) ? "" : ")");
} else
log_link_full(link, link->state == LINK_STATE_INITIALIZED ? LOG_DEBUG : LOG_INFO,
"Unmanaging interface.");
@@ -1252,7 +1364,9 @@ int link_reconfigure_impl(Link *link, bool force) {
if (r < 0)
return r;
- link_drop_requests(link);
+ r = link_drop_requests(link);
+ if (r < 0)
+ return r;
if (network && !force && network->keep_configuration != KEEP_CONFIGURATION_YES)
/* When a new/updated .network file is assigned, first make all configs (addresses,
@@ -1346,6 +1460,80 @@ int link_reconfigure(Link *link, bool force) {
return 1; /* 1 means the interface will be reconfigured. */
}
+typedef struct ReconfigureData {
+ Link *link;
+ Manager *manager;
+ sd_bus_message *message;
+} ReconfigureData;
+
+static void reconfigure_data_destroy_callback(ReconfigureData *data) {
+ int r;
+
+ assert(data);
+ assert(data->link);
+ assert(data->manager);
+ assert(data->manager->reloading > 0);
+ assert(data->message);
+
+ link_unref(data->link);
+
+ data->manager->reloading--;
+ if (data->manager->reloading <= 0) {
+ r = sd_bus_reply_method_return(data->message, NULL);
+ if (r < 0)
+ log_warning_errno(r, "Failed to send reply for 'Reload' DBus method, ignoring: %m");
+ }
+
+ sd_bus_message_unref(data->message);
+ free(data);
+}
+
+static int reconfigure_handler_on_bus_method_reload(sd_netlink *rtnl, sd_netlink_message *m, ReconfigureData *data) {
+ assert(data);
+ assert(data->link);
+ return link_reconfigure_handler_internal(rtnl, m, data->link, /* force = */ false);
+}
+
+int link_reconfigure_on_bus_method_reload(Link *link, sd_bus_message *message) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ _cleanup_free_ ReconfigureData *data = NULL;
+ int r;
+
+ assert(link);
+ assert(link->manager);
+ assert(link->manager->rtnl);
+ assert(message);
+
+ /* See comments in link_reconfigure() above. */
+ if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_INITIALIZED, LINK_STATE_LINGER))
+ return 0;
+
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK, link->ifindex);
+ if (r < 0)
+ return r;
+
+ data = new(ReconfigureData, 1);
+ if (!data)
+ return -ENOMEM;
+
+ r = netlink_call_async(link->manager->rtnl, NULL, req,
+ reconfigure_handler_on_bus_method_reload,
+ reconfigure_data_destroy_callback, data);
+ if (r < 0)
+ return r;
+
+ *data = (ReconfigureData) {
+ .link = link_ref(link),
+ .manager = link->manager,
+ .message = sd_bus_message_ref(message),
+ };
+
+ link->manager->reloading++;
+
+ TAKE_PTR(data);
+ return 0;
+}
+
static int link_initialized_and_synced(Link *link) {
int r;
@@ -1443,9 +1631,9 @@ static int link_check_initialized(Link *link) {
return 0;
}
- r = sd_device_get_is_initialized(device);
+ r = device_is_processed(device);
if (r < 0)
- return log_link_warning_errno(link, r, "Could not determine whether the device is initialized: %m");
+ return log_link_warning_errno(link, r, "Could not determine whether the device is processed by udevd: %m");
if (r == 0) {
/* not yet ready */
log_link_debug(link, "link pending udev initialization...");
@@ -1693,7 +1881,7 @@ static int link_admin_state_up(Link *link) {
/* We set the ipv6 mtu after the device mtu, but the kernel resets
* ipv6 mtu on NETDEV_UP, so we need to reset it. */
- r = link_set_ipv6_mtu(link);
+ r = link_set_ipv6_mtu(link, LOG_INFO);
if (r < 0)
log_link_warning_errno(link, r, "Cannot set IPv6 MTU, ignoring: %m");
@@ -1781,14 +1969,18 @@ void link_update_operstate(Link *link, bool also_update_master) {
else
operstate = LINK_OPERSTATE_ENSLAVED;
+ LinkOperationalStateRange req;
+ link_required_operstate_for_online(link, &req);
+
/* Only determine online state for managed links with RequiredForOnline=yes */
if (!link->network || !link->network->required_for_online)
online_state = _LINK_ONLINE_STATE_INVALID;
- else if (operstate < link->network->required_operstate_for_online.min ||
- operstate > link->network->required_operstate_for_online.max)
+
+ else if (!operational_state_is_in_range(operstate, &req))
online_state = LINK_ONLINE_STATE_OFFLINE;
+
else {
- AddressFamily required_family = link->network->required_family_for_online;
+ AddressFamily required_family = link_required_family_for_online(link);
bool needs_ipv4 = required_family & ADDRESS_FAMILY_IPV4;
bool needs_ipv6 = required_family & ADDRESS_FAMILY_IPV6;
@@ -1797,14 +1989,14 @@ void link_update_operstate(Link *link, bool also_update_master) {
* to offline in the blocks below. */
online_state = LINK_ONLINE_STATE_ONLINE;
- if (link->network->required_operstate_for_online.min >= LINK_OPERSTATE_DEGRADED) {
+ if (req.min >= LINK_OPERSTATE_DEGRADED) {
if (needs_ipv4 && ipv4_address_state < LINK_ADDRESS_STATE_DEGRADED)
online_state = LINK_ONLINE_STATE_OFFLINE;
if (needs_ipv6 && ipv6_address_state < LINK_ADDRESS_STATE_DEGRADED)
online_state = LINK_ONLINE_STATE_OFFLINE;
}
- if (link->network->required_operstate_for_online.min >= LINK_OPERSTATE_ROUTABLE) {
+ if (req.min >= LINK_OPERSTATE_ROUTABLE) {
if (needs_ipv4 && ipv4_address_state < LINK_ADDRESS_STATE_ROUTABLE)
online_state = LINK_ONLINE_STATE_OFFLINE;
if (needs_ipv6 && ipv6_address_state < LINK_ADDRESS_STATE_ROUTABLE)
@@ -2242,6 +2434,13 @@ static int link_update_mtu(Link *link, sd_netlink_message *message) {
link->mtu = mtu;
+ if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
+ /* The kernel resets IPv6 MTU after changing device MTU. So, we need to re-set IPv6 MTU again. */
+ r = link_set_ipv6_mtu(link, LOG_INFO);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to set IPv6 MTU, ignoring: %m");
+ }
+
if (link->dhcp_client) {
r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
if (r < 0)
@@ -2339,7 +2538,7 @@ static int link_update_name(Link *link, sd_netlink_message *message) {
if (link->dhcp6_client) {
r = sd_dhcp6_client_set_ifname(link->dhcp6_client, link->ifname);
if (r < 0)
- return log_link_debug_errno(link, r, "Failed to update interface name in DHCP6 client: %m");
+ return log_link_debug_errno(link, r, "Failed to update interface name in DHCPv6 client: %m");
}
if (link->ndisc) {
@@ -2433,6 +2632,10 @@ static int link_update(Link *link, sd_netlink_message *message) {
if (r < 0)
return r;
+ r = link_update_bridge_vlan(link, message);
+ if (r < 0)
+ return r;
+
return needs_reconfigure;
}
@@ -2447,7 +2650,7 @@ static Link *link_drop_or_unref(Link *link) {
DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_drop_or_unref);
static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
- _cleanup_free_ char *ifname = NULL, *kind = NULL, *state_file = NULL, *lease_file = NULL, *lldp_file = NULL;
+ _cleanup_free_ char *ifname = NULL, *kind = NULL, *state_file = NULL, *lease_file = NULL;
_cleanup_(link_drop_or_unrefp) Link *link = NULL;
unsigned short iftype;
int r, ifindex;
@@ -2488,9 +2691,6 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
if (asprintf(&lease_file, "/run/systemd/netif/leases/%d", ifindex) < 0)
return log_oom_debug();
-
- if (asprintf(&lldp_file, "/run/systemd/netif/lldp/%d", ifindex) < 0)
- return log_oom_debug();
}
link = new(Link, 1);
@@ -2501,16 +2701,18 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
.n_ref = 1,
.state = LINK_STATE_PENDING,
.online_state = _LINK_ONLINE_STATE_INVALID,
+ .automatic_reconfigure_ratelimit = (const RateLimit) { .interval = 10 * USEC_PER_SEC, .burst = 5 },
.ifindex = ifindex,
.iftype = iftype,
.ifname = TAKE_PTR(ifname),
.kind = TAKE_PTR(kind),
+ .bridge_vlan_pvid = UINT16_MAX,
+
.ipv6ll_address_gen_mode = _IPV6_LINK_LOCAL_ADDRESS_GEN_MODE_INVALID,
.state_file = TAKE_PTR(state_file),
.lease_file = TAKE_PTR(lease_file),
- .lldp_file = TAKE_PTR(lldp_file),
.n_dns = UINT_MAX,
.dns_default_route = -1,