diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/nm-l3cfg.c | 69 | ||||
| -rw-r--r-- | src/core/nm-manager.c | 22 | ||||
| -rw-r--r-- | src/core/nm-netns.c | 19 | ||||
| -rw-r--r-- | src/core/nm-netns.h | 4 | ||||
| -rw-r--r-- | src/core/nm-policy.c | 35 |
5 files changed, 107 insertions, 42 deletions
diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c index a7189d3e..0d20bf44 100644 --- a/src/core/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -370,6 +370,8 @@ G_DEFINE_TYPE(NML3Cfg, nm_l3cfg, G_TYPE_OBJECT) #define _NETNS_WATCHER_IP_ADDR_TAG(self, addr_family) \ ((gconstpointer) & (((char *) self)[1 + NM_IS_IPv4(addr_family)])) +#define _NETNS_WATCHER_MPTCP_IPV6_TAG(self) ((gconstpointer) & (((char *) self)[3])) + /*****************************************************************************/ #define _NMLOG_DOMAIN LOGD_CORE @@ -4764,7 +4766,7 @@ next: } out: - nm_netns_watcher_remove_all(self->priv.netns, TAG, FALSE); + nm_netns_watcher_remove_dirty(self->priv.netns, TAG); } /*****************************************************************************/ @@ -4777,6 +4779,30 @@ _global_tracker_mptcp_untrack(NML3Cfg *self, int addr_family) TRUE); } +static void +mptcp_ipv6_addr_cb(NMNetns *netns, + NMNetnsWatcherType watcher_type, + const NMNetnsWatcherData *watcher_data, + gconstpointer tag, + const NMNetnsWatcherEventData *event_data, + gpointer user_data) +{ + NML3Cfg *self = user_data; + + if (event_data->ip_addr.change_type == NM_PLATFORM_SIGNAL_REMOVED) + return; + + nm_assert(NMP_OBJECT_GET_TYPE(event_data->ip_addr.obj) == NMP_OBJECT_TYPE_IP6_ADDRESS); + + if (event_data->ip_addr.obj->ip6_address.n_ifa_flags & IFA_F_TENTATIVE) + return; + + /* We are inside the handler for a platform event, we should not + * perform other operations on platform synchronously. Schedule a + * commit in a idle handler. */ + nm_l3cfg_commit_on_idle_schedule(self, NM_L3_CFG_COMMIT_TYPE_AUTO); +} + static gboolean _l3_commit_mptcp_af(NML3Cfg *self, NML3CfgCommitType commit_type, @@ -4855,6 +4881,8 @@ _l3_commit_mptcp_af(NML3Cfg *self, self->priv.p->combined_l3cd_commited, addr_family, (const NMPlatformIPAddress **) &addr) { + const NMPObject *obj; + /* We want to evaluate the with-{loopback,link_local}-{4,6} flags based on the actual * ifa_scope that the address will have once we configure it. * "addr" is an address we want to configure, we expect that it will @@ -4881,6 +4909,34 @@ _l3_commit_mptcp_af(NML3Cfg *self, break; } + obj = nm_platform_ip_address_get(self->priv.platform, + addr_family, + self->priv.ifindex, + addr); + if (!obj) { + /* The address is not yet configured in platform, typically due to + * IPv4 DAD; skip it for now otherwise the kernel will try to use + * the endpoint, it will fail, and it will never try it again. */ + goto skip_addr; + } + if (!IS_IPv4 && (obj->ip6_address.n_ifa_flags & IFA_F_TENTATIVE)) { + NMNetnsWatcherData watcher_data = {}; + + /* The endpoint is not usable when the address is tentative. + * Watch the address until it becomes non-tentative and then + * schedule a new commit. */ + watcher_data.ip_addr.addr.addr_family = AF_INET6; + watcher_data.ip_addr.addr.addr.addr6 = addr->a6.address; + + nm_netns_watcher_add(self->priv.netns, + NM_NETNS_WATCHER_TYPE_IP_ADDR, + &watcher_data, + _NETNS_WATCHER_MPTCP_IPV6_TAG(self), + mptcp_ipv6_addr_cb, + self); + goto skip_addr; + } + a.addr = nm_ip_addr_init(addr_family, addr->ax.address_ptr); /* We track the address with different priorities, that depends @@ -4909,6 +4965,8 @@ skip_addr: } } + nm_netns_watcher_remove_dirty(self->priv.netns, _NETNS_WATCHER_MPTCP_IPV6_TAG(self)); + if (!any_tracked) { /* We need to make it known that this ifindex is used. Track a dummy object. */ if (nmp_global_tracker_track( @@ -5636,12 +5694,9 @@ finalize(GObject *object) gboolean changed; if (self->priv.netns) { - nm_netns_watcher_remove_all(self->priv.netns, - _NETNS_WATCHER_IP_ADDR_TAG(self, AF_INET), - TRUE); - nm_netns_watcher_remove_all(self->priv.netns, - _NETNS_WATCHER_IP_ADDR_TAG(self, AF_INET6), - TRUE); + nm_netns_watcher_remove_all(self->priv.netns, _NETNS_WATCHER_IP_ADDR_TAG(self, AF_INET)); + nm_netns_watcher_remove_all(self->priv.netns, _NETNS_WATCHER_IP_ADDR_TAG(self, AF_INET6)); + nm_netns_watcher_remove_all(self->priv.netns, _NETNS_WATCHER_MPTCP_IPV6_TAG(self)); } nm_prioq_destroy(&self->priv.p->failedobj_prioq); diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c index b96a9053..03285402 100644 --- a/src/core/nm-manager.c +++ b/src/core/nm-manager.c @@ -4536,7 +4536,7 @@ nm_manager_get_best_device_for_connection(NMManager *self, NMSettingsConnection *sett_conn, NMConnection *connection, gboolean for_user_request, - GHashTable *unavailable_devices, + GHashTable *exclude_devices, GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); @@ -4619,7 +4619,7 @@ nm_manager_get_best_device_for_connection(NMManager *self, ac_device = nm_active_connection_get_device(ac); if (ac_device - && ((unavailable_devices && g_hash_table_contains(unavailable_devices, ac_device)) + && (nm_g_hash_table_contains(exclude_devices, ac_device) || !nm_device_check_connection_available(ac_device, connection, flags, NULL, NULL))) ac_device = NULL; @@ -4635,9 +4635,7 @@ nm_manager_get_best_device_for_connection(NMManager *self, NMDevice *ac_device2 = nm_active_connection_get_device(ac2); NMActiveConnectionState ac_state2; - if (!ac_device2 - || (unavailable_devices - && g_hash_table_contains(unavailable_devices, ac_device2)) + if (!ac_device2 || nm_g_hash_table_contains(exclude_devices, ac_device2) || !nm_device_check_connection_available(ac_device2, connection, flags, @@ -4698,7 +4696,19 @@ found_better: GError *local = NULL; DeviceActivationPrio prio; - if (unavailable_devices && g_hash_table_contains(unavailable_devices, device)) + if (nm_g_hash_table_contains(exclude_devices, device)) + continue; + + /* During startup, NM performs a cleanup of the ovsdb to remove previous entries. + * Before the device is suitable for the connection, it must have ovsdb->ready set + * to TRUE. Performing this check in all kind of interfaces is too agressive and leads + * to race conditions, e.g when a non-virtual bond port gets a carrier, preventing the + * device to be a good candidate for the connection. */ + if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_OVS_INTERFACE + && !nm_device_is_available(device, + for_user_request + ? NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST + : NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) continue; /* determine the priority of this device. Currently, this priority is independent diff --git a/src/core/nm-netns.c b/src/core/nm-netns.c index ed33d336..4d286561 100644 --- a/src/core/nm-netns.c +++ b/src/core/nm-netns.c @@ -1369,8 +1369,8 @@ nm_netns_watcher_remove_handle(NMNetns *self, NMNetnsWatcherHandle *handle) g_object_unref(self); } -void -nm_netns_watcher_remove_all(NMNetns *self, gconstpointer tag, gboolean all) +static void +watcher_remove(NMNetns *self, gconstpointer tag, gboolean all) { NMNetnsPrivate *priv; WatcherByTag *watcher_by_tag; @@ -1420,6 +1420,21 @@ nm_netns_watcher_remove_all(NMNetns *self, gconstpointer tag, gboolean all) } } +void +nm_netns_watcher_remove_all(NMNetns *self, gconstpointer tag) +{ + watcher_remove(self, tag, TRUE); +} + +/* Similar to nm_netns_watcher_remove_all(), but removes only watchers + * that were marked as "dirty" in a previous call of this function and were + * not added back via nm_netns_watcher_add() in the meantime. */ +void +nm_netns_watcher_remove_dirty(NMNetns *self, gconstpointer tag) +{ + watcher_remove(self, tag, FALSE); +} + /*****************************************************************************/ static void diff --git a/src/core/nm-netns.h b/src/core/nm-netns.h index 7725ae79..43e9c781 100644 --- a/src/core/nm-netns.h +++ b/src/core/nm-netns.h @@ -98,7 +98,7 @@ void nm_netns_watcher_add(NMNetns *self, NMNetnsWatcherCallback callback, gpointer user_data); -void -nm_netns_watcher_remove_all(NMNetns *self, gconstpointer tag, gboolean all /* or only dirty */); +void nm_netns_watcher_remove_all(NMNetns *self, gconstpointer tag); +void nm_netns_watcher_remove_dirty(NMNetns *self, gconstpointer tag); #endif /* __NM_NETNS_H__ */ diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c index 05d4d006..57edb69a 100644 --- a/src/core/nm-policy.c +++ b/src/core/nm-policy.c @@ -1873,8 +1873,7 @@ unblock_autoconnect_for_children(NMPolicy *self, const char *parent_device, const char *parent_uuid_settings, const char *parent_uuid_applied, - const char *parent_mac_addr, - gboolean reset_devcon_autoconnect) + const char *parent_mac_addr) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); NMSettingsConnection *const *connections; @@ -1915,10 +1914,8 @@ unblock_autoconnect_for_children(NMPolicy *self, parent_mac_addr)) continue; - if (reset_devcon_autoconnect) { - if (nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn)) - changed = TRUE; - } + if (nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn)) + changed = TRUE; /* unblock the devices associated with that connection */ if (nm_manager_devcon_autoconnect_blocked_reason_set( @@ -1940,12 +1937,11 @@ static void unblock_autoconnect_for_ports(NMPolicy *self, const char *controller_device, const char *controller_uuid_settings, - const char *controller_uuid_applied, - gboolean reset_devcon_autoconnect) + const char *controller_uuid_applied) { NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); NMSettingsConnection *const *connections; - gboolean changed; + gboolean changed = FALSE; guint i; _LOGT(LOGD_CORE, @@ -1959,7 +1955,6 @@ unblock_autoconnect_for_ports(NMPolicy *self, "\"", "")); - changed = FALSE; connections = nm_settings_get_connections(priv->settings, NULL); for (i = 0; connections[i]; i++) { NMSettingsConnection *sett_conn = connections[i]; @@ -1977,10 +1972,8 @@ unblock_autoconnect_for_ports(NMPolicy *self, controller_uuid_settings)) continue; - if (reset_devcon_autoconnect) { - if (nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn)) - changed = TRUE; - } + if (nm_manager_devcon_autoconnect_retries_reset(priv->manager, NULL, sett_conn)) + changed = TRUE; /* unblock the devices associated with that connection */ if (nm_manager_devcon_autoconnect_blocked_reason_set( @@ -2015,7 +2008,7 @@ unblock_autoconnect_for_ports_for_sett_conn(NMPolicy *self, NMSettingsConnection controller_uuid_settings = nm_setting_connection_get_uuid(s_con); controller_device = nm_setting_connection_get_interface_name(s_con); - unblock_autoconnect_for_ports(self, controller_device, controller_uuid_settings, NULL, TRUE); + unblock_autoconnect_for_ports(self, controller_device, controller_uuid_settings, NULL); } static void @@ -2028,7 +2021,6 @@ activate_port_or_children_connections(NMPolicy *self, const char *controller_uuid_applied = NULL; const char *parent_mac_addr = NULL; NMActRequest *req; - gboolean internal_activation = FALSE; controller_device = nm_device_get_iface(device); nm_assert(controller_device); @@ -2039,7 +2031,6 @@ activate_port_or_children_connections(NMPolicy *self, if (req) { NMConnection *connection; NMSettingsConnection *sett_conn; - NMAuthSubject *subject; sett_conn = nm_active_connection_get_settings_connection(NM_ACTIVE_CONNECTION(req)); if (sett_conn) @@ -2051,25 +2042,19 @@ activate_port_or_children_connections(NMPolicy *self, if (nm_streq0(controller_uuid_settings, controller_uuid_applied)) controller_uuid_applied = NULL; - - subject = nm_active_connection_get_subject(NM_ACTIVE_CONNECTION(req)); - internal_activation = - subject && (nm_auth_subject_get_subject_type(subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL); } if (!activate_children_connections_only) { unblock_autoconnect_for_ports(self, controller_device, controller_uuid_settings, - controller_uuid_applied, - !internal_activation); + controller_uuid_applied); } unblock_autoconnect_for_children(self, controller_device, controller_uuid_settings, controller_uuid_applied, - parent_mac_addr, - !internal_activation); + parent_mac_addr); } static gboolean |