summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-05-25 11:16:17 +0200
committerThomas Haller <thaller@redhat.com>2016-05-25 15:11:47 +0200
commit791cbd08179737bb4e1b7b2d7064b0f676f688ff (patch)
treed552452a92d79e85651fb3ba5818e29f40b307cb
parent9cf1dbcaefd6128cf8c77cb4960cd57f972c6da0 (diff)
downloadNetworkManager-791cbd08179737bb4e1b7b2d7064b0f676f688ff.tar.gz
platform: handle missing netlink attribute IFLA_ADDRESS by cache-lookup
Sometimes the netlink event lacks the IFLA_ADDRESS attribute with the MAC address of the link. In this case, take the value from the cached link instance. A missing netlink attribute should have the meaning of reusing the previous value, not clearing the address.
-rw-r--r--src/platform/nm-linux-platform.c41
-rw-r--r--src/platform/nm-platform.h2
2 files changed, 26 insertions, 17 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 82e673a3c1..2c20d77c57 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -1434,6 +1434,8 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
gboolean *completed_from_cache = cache ? &completed_from_cache_val : NULL;
const NMPObject *link_cached = NULL;
NMPObject *lnk_data = NULL;
+ gboolean address_complete_from_cache = TRUE;
+ gboolean lnk_data_complete_from_cache = TRUE;
if (!nlmsg_valid_hdr (nlh, sizeof (*ifi)))
return NULL;
@@ -1498,6 +1500,7 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
memcpy (obj->link.addr.data, nla_data (tb[IFLA_ADDRESS]), l);
obj->link.addr.len = l;
}
+ address_complete_from_cache = FALSE;
}
if (tb[IFLA_AF_SPEC]) {
@@ -1547,28 +1550,34 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
lnk_data = _parse_lnk_vxlan (nl_info_kind, nl_info_data);
break;
default:
- goto lnk_data_handled;
+ lnk_data_complete_from_cache = FALSE;
+ break;
}
- /* We always try to look into the cache and reuse the object there.
- * We do that, because we consider the lnk object as immutable and don't
- * modify it after creating. Hence we can share it and reuse.
- *
- * Also, sometimes the info-data is missing for updates. In this case
- * we want to keep the previously received lnk_data. */
- if (completed_from_cache) {
+ if ( completed_from_cache
+ && ( lnk_data_complete_from_cache
+ || address_complete_from_cache)) {
_lookup_cached_link (cache, obj->link.ifindex, completed_from_cache, &link_cached);
- if ( link_cached
- && link_cached->link.type == obj->link.type
- && link_cached->_link.netlink.lnk
- && ( !lnk_data
- || nmp_object_equal (lnk_data, link_cached->_link.netlink.lnk))) {
- nmp_object_unref (lnk_data);
- lnk_data = nmp_object_ref (link_cached->_link.netlink.lnk);
+ if (link_cached) {
+ if ( lnk_data_complete_from_cache
+ && link_cached->link.type == obj->link.type
+ && link_cached->_link.netlink.lnk
+ && ( !lnk_data
+ || nmp_object_equal (lnk_data, link_cached->_link.netlink.lnk))) {
+ /* We always try to look into the cache and reuse the object there.
+ * We do that, because we consider the lnk object as immutable and don't
+ * modify it after creating. Hence we can share it and reuse.
+ *
+ * Also, sometimes the info-data is missing for updates. In this case
+ * we want to keep the previously received lnk_data. */
+ nmp_object_unref (lnk_data);
+ lnk_data = nmp_object_ref (link_cached->_link.netlink.lnk);
+ }
+ if (address_complete_from_cache)
+ obj->link.addr = link_cached->link.addr;
}
}
-lnk_data_handled:
obj->_link.netlink.lnk = lnk_data;
obj->_link.netlink.is_in_netlink = TRUE;
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index a5cca8ba75..ed21632836 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -141,7 +141,7 @@ struct _NMPlatformLink {
/* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */
guint32 arptype;
- /* rtnl_link_get_addr() */
+ /* rtnl_link_get_addr(), IFLA_ADDRESS */
struct {
guint8 data[20]; /* NM_UTILS_HWADDR_LEN_MAX */
guint8 len;