diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2014-12-04 16:22:39 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2014-12-11 11:49:29 +0100 |
commit | ed78d3b3dc1406f6a1186b482a160452527cba6e (patch) | |
tree | c0ed9f50a58e2228095af0a2293eb5f589f6cd76 /src | |
parent | 8019a51a0e78d6b10311562e8b2b573832fa1b90 (diff) | |
download | NetworkManager-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
Diffstat (limited to 'src')
-rw-r--r-- | src/platform/nm-linux-platform.c | 38 |
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); |