summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2014-12-04 16:22:39 +0100
committerLubomir Rintel <lkundrak@v3.sk>2014-12-11 11:49:29 +0100
commited78d3b3dc1406f6a1186b482a160452527cba6e (patch)
treec0ed9f50a58e2228095af0a2293eb5f589f6cd76
parent8019a51a0e78d6b10311562e8b2b573832fa1b90 (diff)
downloadNetworkManager-ed78d3b3dc1406f6a1186b482a160452527cba6e.tar.gz
platform: ensure all objects in link cache are of AF_UNSPEC family
We assume that in nm_nl_cache_search() and correctly set that in get_kernel_object(), but we rtnl_link_alloc_cache() can initialize the cache with devices of other families. The consequence is that we don't notify when the bridge changes to IFF_UP as we fail to match and remove the old downed object from the cache: nm_device_bring_up(): [0xf506c0] (bridge0): bringing up device. nm_platform_link_set_up(): link: setting up 'bridge0' (12) link_change_flags(): link: change 12: flags set 'up' (1) get_kernel_object(): get_kernel_object for link: bridge0 (12, family 7) log_link(): signal: link added: 12: bridge0 <UP> mtu 1500 bridge driver 'bridge' udi '/sys/devices/virtual/net/bridge0' get_kernel_object(): get_kernel_object for link: bridge0 (12, family 7) log_link(): signal: link changed: 12: bridge0 <UP> mtu 1500 bridge driver 'bridge' udi '/sys/devices/virtual/net/bridge0' log_link(): signal: link changed: 12: bridge0 <UP> mtu 1500 bridge driver 'bridge' udi '/sys/devices/virtual/net/bridge0' (bridge0): device not up after timeout! (bridge0): preparing device
-rw-r--r--src/platform/nm-linux-platform.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 7ced0ba77b..668acdb933 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -3982,6 +3982,42 @@ ip6_route_exists (NMPlatform *platform, int ifindex, struct in6_addr network, in
/******************************************************************/
+/* Initialize the link cache while ensuring all links are of AF_UNSPEC,
+ * family (even though the kernel might set AF_BRIDGE for bridges).
+ * See also: _nl_link_family_unset() */
+static void
+init_link_cache (NMPlatform *platform)
+{
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
+ struct nl_object *object = NULL;
+
+ rtnl_link_alloc_cache (priv->nlh, AF_UNSPEC, &priv->link_cache);
+
+ do {
+ for (object = nl_cache_get_first (priv->link_cache); object; object = nl_cache_get_next (object)) {
+ if (rtnl_link_get_family ((struct rtnl_link *)object) != AF_UNSPEC)
+ break;
+ }
+
+ if (object) {
+ /* A non-AF_UNSPEC object encoutnered */
+ struct nl_object *existing;
+
+ nl_object_get (object);
+ nl_cache_remove (object);
+ rtnl_link_set_family ((struct rtnl_link *)object, AF_UNSPEC);
+ existing = nl_cache_search (priv->link_cache, object);
+ if (existing)
+ nl_object_put (existing);
+ else
+ nl_cache_add (priv->link_cache, object);
+ nl_object_put (object);
+ }
+ } while (object);
+}
+
+/******************************************************************/
+
#define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI))
#define ERROR_CONDITIONS ((GIOCondition) (G_IO_ERR | G_IO_NVAL))
#define DISCONNECT_CONDITIONS ((GIOCondition) (G_IO_HUP))
@@ -4233,7 +4269,7 @@ setup (NMPlatform *platform)
event_handler, platform);
/* Allocate netlink caches */
- rtnl_link_alloc_cache (priv->nlh, AF_UNSPEC, &priv->link_cache);
+ init_link_cache (platform);
rtnl_addr_alloc_cache (priv->nlh, &priv->address_cache);
rtnl_route_alloc_cache (priv->nlh, AF_UNSPEC, 0, &priv->route_cache);
g_assert (priv->link_cache && priv->address_cache && priv->route_cache);