summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2016-09-17 12:56:06 (GMT)
committerMichael Biebl <biebl@debian.org>2016-09-23 21:53:08 (GMT)
commit0bb216356b69f2df305b921c9e38a0a2bb502c4d (patch)
tree11d7e13942af83bf43d34367a83b3358b215326e
parent6ca68536b2eae7d93e2df2c73d63481c5828edbd (diff)
Fix MAC address randomization
Cherry-pick a couple of upstream commits which work around driver bugs when MAC address randomization is used. Closes: #835822 Closes: #835553
-rw-r--r--debian/changelog3
-rw-r--r--debian/patches/device-add-hack-to-wait-after-changing-MAC-address.patch72
-rw-r--r--debian/patches/device-fix-spelling-in-logging.patch23
-rw-r--r--debian/patches/device-wait-for-MAC-address-change-to-complete-before-set.patch75
-rw-r--r--debian/patches/device-workaround-driver-issue-with-delayed-change-of-MAC.patch194
-rw-r--r--debian/patches/platform-split-processing-result-from-do_change_link.patch74
-rw-r--r--debian/patches/platform-workaround-kernel-wrongly-returning-ENFILE-when-.patch57
-rw-r--r--debian/patches/series7
-rw-r--r--debian/patches/shared-add-NM_MIN-NM_MAX-macros-to-replace-glib-s-MIN-MAX.patch65
9 files changed, 570 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index bfa7708..6fd7e92 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,6 +2,9 @@ network-manager (1.4.0-4) UNRELEASED; urgency=medium
* Drop override for dh_auto_test. We don't explicitly need to dump the log
files as dh_auto_test runs with VERBOSE=1 by default.
+ * Fix MAC address randomization.
+ Cherry-pick a couple of upstream commits which work around driver bugs
+ when MAC address randomization is used. (Closes: #835822, #835553)
-- Michael Biebl <biebl@debian.org> Sat, 17 Sep 2016 14:51:02 +0200
diff --git a/debian/patches/device-add-hack-to-wait-after-changing-MAC-address.patch b/debian/patches/device-add-hack-to-wait-after-changing-MAC-address.patch
new file mode 100644
index 0000000..94ae6a7
--- /dev/null
+++ b/debian/patches/device-add-hack-to-wait-after-changing-MAC-address.patch
@@ -0,0 +1,72 @@
+From: Thomas Haller <thaller@redhat.com>
+Date: Mon, 29 Aug 2016 18:28:34 +0200
+Subject: device: add hack to wait after changing MAC address
+
+It seems some drivers return success for nm_platform_link_set_address(),
+but at that point the address did not yet actually change *sigh*.
+It changes a bit later, possibly after setting the device up.
+
+Add a workaround to retry reading the MAC address when platform indicates
+success but the address still differs at first.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=770456
+(cherry picked from commit 67b685235847ac49712d77023e23ef5c38e82a9e)
+(cherry picked from commit 3b51959f48f2b40a4d85e1d36fd69a46548369cb)
+---
+ src/devices/nm-device.c | 28 +++++++++++++++++++++++++---
+ 1 file changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
+index 305a1bb..6939332 100644
+--- a/src/devices/nm-device.c
++++ b/src/devices/nm-device.c
+@@ -11774,6 +11774,7 @@ _hw_addr_set (NMDevice *self,
+ {
+ NMDevicePrivate *priv;
+ gboolean success = FALSE;
++ gboolean needs_refresh = FALSE;
+ NMPlatformError plerr;
+ const char *cur_addr;
+ guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX];
+@@ -11819,10 +11820,10 @@ _hw_addr_set (NMDevice *self,
+ _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
+ operation, addr, detail);
+ } else {
+- _LOGW (LOGD_DEVICE,
+- "set-hw-addr: new MAC address %s not successfully %s (%s)",
++ _LOGD (LOGD_DEVICE,
++ "set-hw-addr: new MAC address %s not successfully %s (%s) (refresh link)",
+ addr, operation, detail);
+- success = FALSE;
++ needs_refresh = TRUE;
+ }
+ } else {
+ _NMLOG (plerr == NM_PLATFORM_ERROR_NOT_FOUND ? LOGL_DEBUG : LOGL_WARN,
+@@ -11836,6 +11837,27 @@ _hw_addr_set (NMDevice *self,
+ return FALSE;
+ }
+
++ if (needs_refresh) {
++ /* The platform call indicated success, however the address is not
++ * as expected. May be a kernel issue and the MAC address takes
++ * a moment to change (bgo#770456).
++ *
++ * Try to reload the link and check again. */
++ nm_platform_link_refresh (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self));
++
++ nm_device_update_hw_address (self);
++ cur_addr = nm_device_get_hw_address (self);
++ if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) {
++ _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
++ operation, addr, detail);
++ } else {
++ _LOGW (LOGD_DEVICE,
++ "set-hw-addr: new MAC address %s not successfully %s (%s)",
++ addr, operation, detail);
++ return FALSE;
++ }
++ }
++
+ return success;
+ }
+
diff --git a/debian/patches/device-fix-spelling-in-logging.patch b/debian/patches/device-fix-spelling-in-logging.patch
new file mode 100644
index 0000000..b6b1f50
--- /dev/null
+++ b/debian/patches/device-fix-spelling-in-logging.patch
@@ -0,0 +1,23 @@
+From: Thomas Haller <thaller@redhat.com>
+Date: Mon, 29 Aug 2016 17:14:04 +0200
+Subject: device: fix spelling in logging
+
+(cherry picked from commit d51f2c2a4e99799739e2adbeaf578144b556c4b9)
+(cherry picked from commit b1f5d3d798498c53fe65257490b2df3e3f71e364)
+---
+ src/devices/nm-device.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
+index 199acc6..305a1bb 100644
+--- a/src/devices/nm-device.c
++++ b/src/devices/nm-device.c
+@@ -11820,7 +11820,7 @@ _hw_addr_set (NMDevice *self,
+ operation, addr, detail);
+ } else {
+ _LOGW (LOGD_DEVICE,
+- "set-hw-addr: new MAC address %s not successfully set to %s (%s)",
++ "set-hw-addr: new MAC address %s not successfully %s (%s)",
+ addr, operation, detail);
+ success = FALSE;
+ }
diff --git a/debian/patches/device-wait-for-MAC-address-change-to-complete-before-set.patch b/debian/patches/device-wait-for-MAC-address-change-to-complete-before-set.patch
new file mode 100644
index 0000000..8e5f29f
--- /dev/null
+++ b/debian/patches/device-wait-for-MAC-address-change-to-complete-before-set.patch
@@ -0,0 +1,75 @@
+From: Thomas Haller <thaller@redhat.com>
+Date: Sun, 11 Sep 2016 09:48:56 +0200
+Subject: device: wait for MAC address change to complete before setting
+ interface up
+
+Some drivers (brcmfmac) don't change the MAC address right away.
+NetworkManager works around that by waiting synchronously until
+the address changes (commit 1a85103765d4eaa0acab6b03658a4f9cfe684a64).
+
+wpa_supplicant on the other hand, only re-reads the MAC address
+when changing state from DISABLED to ENABLED, which happens when
+the interface comes up.
+
+That is a bug in wpa_supplicant and the driver, but we can work-around by
+waiting until the MAC address actually changed before setting the interface
+IFF_UP. Also note, that there is still a race in wpa_supplicant which might
+miss a change to DISABLED state altogether.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=770504
+https://bugzilla.redhat.com/show_bug.cgi?id=1374023
+(cherry picked from commit 32f7c1d4b9aba597a99128631f07c2985149f303)
+(cherry picked from commit cd8f2ecc617a896d8007e6fe825c676a626a3b8d)
+---
+ src/devices/nm-device.c | 27 ++++++++++++++++-----------
+ 1 file changed, 16 insertions(+), 11 deletions(-)
+
+diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
+index 6c720bb..dd77ccf 100644
+--- a/src/devices/nm-device.c
++++ b/src/devices/nm-device.c
+@@ -11840,12 +11840,8 @@ _hw_addr_set (NMDevice *self,
+ nm_platform_error_to_string (plerr));
+ }
+
+- if (was_up) {
+- if (!nm_device_bring_up (self, TRUE, NULL))
+- return FALSE;
+- }
+-
+ if (needs_refresh) {
++ success = TRUE;
+ if (_hw_addr_matches (self, addr)) {
+ /* the MAC address already changed during nm_device_bring_up() above. */
+ } else {
+@@ -11882,15 +11878,24 @@ handle_wait:
+ continue;
+ }
+ handle_fail:
+- _LOGW (LOGD_DEVICE,
+- "set-hw-addr: new MAC address %s not successfully %s (%s)",
+- addr, operation, detail);
+- return FALSE;
++ success = FALSE;
++ break;
+ }
+ }
+
+- _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
+- operation, addr, detail);
++ if (success) {
++ _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
++ operation, addr, detail);
++ } else {
++ _LOGW (LOGD_DEVICE,
++ "set-hw-addr: new MAC address %s not successfully %s (%s)",
++ addr, operation, detail);
++ }
++ }
++
++ if (was_up) {
++ if (!nm_device_bring_up (self, TRUE, NULL))
++ return FALSE;
+ }
+
+ return success;
diff --git a/debian/patches/device-workaround-driver-issue-with-delayed-change-of-MAC.patch b/debian/patches/device-workaround-driver-issue-with-delayed-change-of-MAC.patch
new file mode 100644
index 0000000..e764839
--- /dev/null
+++ b/debian/patches/device-workaround-driver-issue-with-delayed-change-of-MAC.patch
@@ -0,0 +1,194 @@
+From: Thomas Haller <thaller@redhat.com>
+Date: Wed, 7 Sep 2016 23:47:14 +0200
+Subject: device: workaround driver issue with delayed change of MAC address
+
+brcmfmac and possibly other drivers don't change the MAC address
+right away, but instead the result is delayed. That is problematic
+because we cannot continue activation before the MAC address is
+settled.
+
+Add a hack to workaround the issue by waiting until the MAC address
+changed.
+
+The previous attempt to workaround this was less intrusive: we would
+just refresh the link once and check the result. But that turns out
+not to be sufficent for all cases. Now, wait and poll.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=770456
+https://bugzilla.redhat.com/show_bug.cgi?id=1374023
+(cherry picked from commit 1a85103765d4eaa0acab6b03658a4f9cfe684a64)
+(cherry picked from commit 8d575403685208aad75f918484ae7adbc1a46085)
+---
+ src/devices/nm-device.c | 85 ++++++++++++++++++++++++++++++++++---------------
+ src/devices/nm-device.h | 2 +-
+ 2 files changed, 61 insertions(+), 26 deletions(-)
+
+diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
+index 6939332..6c720bb 100644
+--- a/src/devices/nm-device.c
++++ b/src/devices/nm-device.c
+@@ -11560,16 +11560,17 @@ nm_device_get_hw_address (NMDevice *self)
+ return priv->hw_addr;
+ }
+
+-void
++gboolean
+ nm_device_update_hw_address (NMDevice *self)
+ {
+ NMDevicePrivate *priv;
+ const guint8 *hwaddr;
+ gsize hwaddrlen = 0;
++ gboolean changed = FALSE;
+
+ priv = NM_DEVICE_GET_PRIVATE (self);
+ if (priv->ifindex <= 0)
+- return;
++ return FALSE;
+
+ hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &hwaddrlen);
+
+@@ -11596,6 +11597,7 @@ nm_device_update_hw_address (NMDevice *self)
+ * update our inital hw-address as well. */
+ nm_device_update_initial_hw_address (self);
+ }
++ changed = TRUE;
+ }
+ } else {
+ /* Invalid or no hardware address */
+@@ -11608,6 +11610,7 @@ nm_device_update_hw_address (NMDevice *self)
+ "hw-addr: failed reading current MAC address");
+ }
+ }
++ return changed;
+ }
+
+ void
+@@ -11767,6 +11770,15 @@ nm_device_hw_addr_is_explict (NMDevice *self)
+ }
+
+ static gboolean
++_hw_addr_matches (NMDevice *self, const char *addr)
++{
++ const char *cur_addr;
++
++ cur_addr = nm_device_get_hw_address (self);
++ return cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1);
++}
++
++static gboolean
+ _hw_addr_set (NMDevice *self,
+ const char *addr,
+ const char *operation,
+@@ -11776,7 +11788,6 @@ _hw_addr_set (NMDevice *self,
+ gboolean success = FALSE;
+ gboolean needs_refresh = FALSE;
+ NMPlatformError plerr;
+- const char *cur_addr;
+ guint8 addr_bytes[NM_UTILS_HWADDR_LEN_MAX];
+ guint hw_addr_len;
+ gboolean was_up;
+@@ -11787,11 +11798,9 @@ _hw_addr_set (NMDevice *self,
+
+ priv = NM_DEVICE_GET_PRIVATE (self);
+
+- cur_addr = nm_device_get_hw_address (self);
+-
+ /* Do nothing if current MAC is same */
+- if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) {
+- _LOGT (LOGD_DEVICE, "set-hw-addr: no MAC address change needed (%s)", cur_addr);
++ if (_hw_addr_matches (self, addr)) {
++ _LOGT (LOGD_DEVICE, "set-hw-addr: no MAC address change needed (%s)", addr);
+ return TRUE;
+ }
+
+@@ -11815,8 +11824,7 @@ _hw_addr_set (NMDevice *self,
+ if (success) {
+ /* MAC address succesfully changed; update the current MAC to match */
+ nm_device_update_hw_address (self);
+- cur_addr = nm_device_get_hw_address (self);
+- if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) {
++ if (_hw_addr_matches (self, addr)) {
+ _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
+ operation, addr, detail);
+ } else {
+@@ -11838,24 +11846,51 @@ _hw_addr_set (NMDevice *self,
+ }
+
+ if (needs_refresh) {
+- /* The platform call indicated success, however the address is not
+- * as expected. May be a kernel issue and the MAC address takes
+- * a moment to change (bgo#770456).
+- *
+- * Try to reload the link and check again. */
+- nm_platform_link_refresh (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self));
+-
+- nm_device_update_hw_address (self);
+- cur_addr = nm_device_get_hw_address (self);
+- if (cur_addr && nm_utils_hwaddr_matches (cur_addr, -1, addr, -1)) {
+- _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
+- operation, addr, detail);
++ if (_hw_addr_matches (self, addr)) {
++ /* the MAC address already changed during nm_device_bring_up() above. */
+ } else {
+- _LOGW (LOGD_DEVICE,
+- "set-hw-addr: new MAC address %s not successfully %s (%s)",
+- addr, operation, detail);
+- return FALSE;
++ gint64 poll_end, now;
++
++ /* The platform call indicated success, however the address is not
++ * as expected. That is either due to a driver issue (brcmfmac, bgo#770456,
++ * rh#1374023) or a race where externally the MAC address was reset.
++ * The race is rather unlikely.
++ *
++ * The alternative would be to postpone the activation in case the
++ * MAC address is not yet ready and poll without blocking. However,
++ * that is rather complicated and it is not expected that this case
++ * happens for regular drivers.
++ * Note that brcmfmac can block NetworkManager for 500 msec while
++ * taking down the device. Let's add annother 100 msec to that.
++ *
++ * wait/poll up to 100 msec until it changes. */
++
++ poll_end = nm_utils_get_monotonic_timestamp_us () + (100 * 1000);
++ for (;;) {
++ if (!nm_platform_link_refresh (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self)))
++ goto handle_fail;
++ if (!nm_device_update_hw_address (self))
++ goto handle_wait;
++ if (!_hw_addr_matches (self, addr))
++ goto handle_fail;
++
++ break;
++handle_wait:
++ now = nm_utils_get_monotonic_timestamp_us ();
++ if (now < poll_end) {
++ g_usleep (NM_MIN (poll_end - now, 500));
++ continue;
++ }
++handle_fail:
++ _LOGW (LOGD_DEVICE,
++ "set-hw-addr: new MAC address %s not successfully %s (%s)",
++ addr, operation, detail);
++ return FALSE;
++ }
+ }
++
++ _LOGI (LOGD_DEVICE, "set-hw-addr: %s MAC address to %s (%s)",
++ operation, addr, detail);
+ }
+
+ return success;
+diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
+index 34d31ca..0f91b21 100644
+--- a/src/devices/nm-device.h
++++ b/src/devices/nm-device.h
+@@ -588,7 +588,7 @@ void nm_device_reactivate_ip6_config (NMDevice *device,
+ NMSettingIPConfig *s_ip6_old,
+ NMSettingIPConfig *s_ip6_new);
+
+-void nm_device_update_hw_address (NMDevice *self);
++gboolean nm_device_update_hw_address (NMDevice *self);
+ void nm_device_update_initial_hw_address (NMDevice *self);
+ void nm_device_update_permanent_hw_address (NMDevice *self);
+ void nm_device_update_dynamic_ip_setup (NMDevice *self);
diff --git a/debian/patches/platform-split-processing-result-from-do_change_link.patch b/debian/patches/platform-split-processing-result-from-do_change_link.patch
new file mode 100644
index 0000000..d8c1449
--- /dev/null
+++ b/debian/patches/platform-split-processing-result-from-do_change_link.patch
@@ -0,0 +1,74 @@
+From: Thomas Haller <thaller@redhat.com>
+Date: Sun, 28 Aug 2016 13:52:32 +0200
+Subject: platform: split processing result from do_change_link()
+
+(cherry picked from commit 3dc09446771a3434ed948bdd5e6ca9f6ef9a9e76)
+(cherry picked from commit 471521ca84187cd32afcd20aebe5a369fe7368dc)
+---
+ src/platform/nm-linux-platform.c | 35 +++++++++++++++++++++++++++--------
+ 1 file changed, 27 insertions(+), 8 deletions(-)
+
+diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
+index 98c4e46..eeb24ca 100644
+--- a/src/platform/nm-linux-platform.c
++++ b/src/platform/nm-linux-platform.c
+@@ -4060,18 +4060,14 @@ out:
+ return !!nmp_cache_lookup_obj (priv->cache, obj_id);
+ }
+
+-static NMPlatformError
+-do_change_link (NMPlatform *platform,
+- int ifindex,
+- struct nl_msg *nlmsg)
++static WaitForNlResponseResult
++do_change_link_request (NMPlatform *platform,
++ int ifindex,
++ struct nl_msg *nlmsg)
+ {
+ nm_auto_pop_netns NMPNetns *netns = NULL;
+ WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
+ int nle;
+- char s_buf[256];
+- NMPlatformError result = NM_PLATFORM_ERROR_SUCCESS;
+- NMLogLevel log_level = LOGL_DEBUG;
+- const char *log_result = "failure", *log_detail = "";
+
+ if (!nm_platform_netns_push (platform, &netns))
+ return NM_PLATFORM_ERROR_UNSPECIFIED;
+@@ -4098,6 +4094,18 @@ retry:
+ nlmsg_hdr (nlmsg)->nlmsg_type = RTM_SETLINK;
+ goto retry;
+ }
++ return seq_result;
++}
++
++static NMPlatformError
++do_change_link_result (NMPlatform *platform,
++ int ifindex,
++ WaitForNlResponseResult seq_result)
++{
++ char s_buf[256];
++ NMPlatformError result = NM_PLATFORM_ERROR_SUCCESS;
++ NMLogLevel log_level = LOGL_DEBUG;
++ const char *log_result = "failure", *log_detail = "";
+
+ if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK) {
+ log_result = "success";
+@@ -4123,6 +4131,17 @@ retry:
+ return result;
+ }
+
++static NMPlatformError
++do_change_link (NMPlatform *platform,
++ int ifindex,
++ struct nl_msg *nlmsg)
++{
++ WaitForNlResponseResult seq_result;
++
++ seq_result = do_change_link_request (platform, ifindex, nlmsg);
++ return do_change_link_result (platform, ifindex, seq_result);
++}
++
+ static gboolean
+ link_add (NMPlatform *platform,
+ const char *name,
diff --git a/debian/patches/platform-workaround-kernel-wrongly-returning-ENFILE-when-.patch b/debian/patches/platform-workaround-kernel-wrongly-returning-ENFILE-when-.patch
new file mode 100644
index 0000000..bcf4c0b
--- /dev/null
+++ b/debian/patches/platform-workaround-kernel-wrongly-returning-ENFILE-when-.patch
@@ -0,0 +1,57 @@
+From: Thomas Haller <thaller@redhat.com>
+Date: Sun, 28 Aug 2016 14:08:42 +0200
+Subject: platform: workaround kernel wrongly returning ENFILE when changing
+ MAC address
+
+https://bugzilla.gnome.org/show_bug.cgi?id=770456
+(cherry picked from commit 2bef71611bd9fd2e333a7522205f0262ac25680f)
+(cherry picked from commit 06d1679aa9867682297316e7b2cfac6fc8f67c2a)
+---
+ src/platform/nm-linux-platform.c | 27 ++++++++++++++++++++++++++-
+ 1 file changed, 26 insertions(+), 1 deletion(-)
+
+diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
+index eeb24ca..c36e967 100644
+--- a/src/platform/nm-linux-platform.c
++++ b/src/platform/nm-linux-platform.c
+@@ -4449,6 +4449,8 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size
+ {
+ nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
+ gs_free char *mac = NULL;
++ WaitForNlResponseResult seq_result;
++ char s_buf[256];
+
+ if (!address || !length)
+ g_return_val_if_reached (NM_PLATFORM_ERROR_BUG);
+@@ -4468,7 +4470,30 @@ link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size
+
+ NLA_PUT (nlmsg, IFLA_ADDRESS, length, address);
+
+- return do_change_link (platform, ifindex, nlmsg);
++ seq_result = do_change_link_request (platform, ifindex, nlmsg);
++
++ if (NM_IN_SET (-((int) seq_result), ENFILE)) {
++ const NMPObject *obj_cache;
++
++ /* workaround ENFILE which may be wrongly returned (bgo #770456).
++ * If the MAC address is as expected, assume success? */
++
++ obj_cache = nmp_cache_lookup_link (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, ifindex);
++ if ( obj_cache
++ && obj_cache->link.addr.len == length
++ && memcmp (obj_cache->link.addr.data, address, length) == 0) {
++ _NMLOG (LOGL_DEBUG,
++ "do-change-link[%d]: %s changing link: %s%s",
++ ifindex,
++ "success",
++ wait_for_nl_response_to_string (seq_result, s_buf, sizeof (s_buf)),
++ " (assume success changing address)");
++ return NM_PLATFORM_ERROR_SUCCESS;
++ }
++ }
++
++ return do_change_link_result (platform, ifindex, seq_result);
++
+ nla_put_failure:
+ g_return_val_if_reached (NM_PLATFORM_ERROR_UNSPECIFIED);
+ }
diff --git a/debian/patches/series b/debian/patches/series
index 404165c..eafd037 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -5,3 +5,10 @@ Don-t-make-NetworkManager-D-Bus-activatable.patch
systemd-Don-t-enable-NetworkManager-wait-online.service-s.patch
Fix-iscsiadm-path.patch
Export-_IO_stdin_used-symbol-in-NetworkManager.ver.patch
+platform-split-processing-result-from-do_change_link.patch
+platform-workaround-kernel-wrongly-returning-ENFILE-when-.patch
+device-fix-spelling-in-logging.patch
+device-add-hack-to-wait-after-changing-MAC-address.patch
+shared-add-NM_MIN-NM_MAX-macros-to-replace-glib-s-MIN-MAX.patch
+device-workaround-driver-issue-with-delayed-change-of-MAC.patch
+device-wait-for-MAC-address-change-to-complete-before-set.patch
diff --git a/debian/patches/shared-add-NM_MIN-NM_MAX-macros-to-replace-glib-s-MIN-MAX.patch b/debian/patches/shared-add-NM_MIN-NM_MAX-macros-to-replace-glib-s-MIN-MAX.patch
new file mode 100644
index 0000000..d8a6c63
--- /dev/null
+++ b/debian/patches/shared-add-NM_MIN-NM_MAX-macros-to-replace-glib-s-MIN-MAX.patch
@@ -0,0 +1,65 @@
+From: Thomas Haller <thaller@redhat.com>
+Date: Mon, 5 Sep 2016 14:12:41 +0200
+Subject: shared: add NM_MIN()/NM_MAX() macros to replace glib's MIN()/MAX()
+
+(cherry picked from commit b2016fd2a52b82d45324526c965e7545d026cebe)
+(cherry picked from commit 811aaead4ca6f2f815f49b7353fa7a88554dca42)
+---
+ shared/nm-utils/nm-macros-internal.h | 44 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
+index 73075c6..8811c91 100644
+--- a/shared/nm-utils/nm-macros-internal.h
++++ b/shared/nm-utils/nm-macros-internal.h
+@@ -526,6 +526,50 @@ nm_strcmp_p_with_data (gconstpointer a, gconstpointer b, gpointer user_data)
+
+ /*****************************************************************************/
+
++/* Taken from systemd's UNIQ_T and UNIQ macros. */
++
++#define NM_UNIQ_T(x, uniq) G_PASTE(__unique_prefix_, G_PASTE(x, uniq))
++#define NM_UNIQ __COUNTER__
++
++/*****************************************************************************/
++
++/* glib's MIN()/MAX() macros don't have function-like behavior, in that they evaluate
++ * the argument possibly twice.
++ *
++ * Taken from systemd's MIN()/MAX() macros. */
++
++#define NM_MIN(a, b) __NM_MIN(NM_UNIQ, a, NM_UNIQ, b)
++#define __NM_MIN(aq, a, bq, b) \
++ ({ \
++ typeof (a) NM_UNIQ_T(A, aq) = (a); \
++ typeof (b) NM_UNIQ_T(B, bq) = (b); \
++ ((NM_UNIQ_T(A, aq) < NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \
++ })
++
++#define NM_MAX(a, b) __NM_MAX(NM_UNIQ, a, NM_UNIQ, b)
++#define __NM_MAX(aq, a, bq, b) \
++ ({ \
++ typeof (a) NM_UNIQ_T(A, aq) = (a); \
++ typeof (b) NM_UNIQ_T(B, bq) = (b); \
++ ((NM_UNIQ_T(A, aq) > NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \
++ })
++
++#define NM_CLAMP(x, low, high) __NM_CLAMP(NM_UNIQ, x, NM_UNIQ, low, NM_UNIQ, high)
++#define __NM_CLAMP(xq, x, lowq, low, highq, high) \
++ ({ \
++ typeof(x)NM_UNIQ_T(X,xq) = (x); \
++ typeof(low) NM_UNIQ_T(LOW,lowq) = (low); \
++ typeof(high) NM_UNIQ_T(HIGH,highq) = (high); \
++ \
++ ( (NM_UNIQ_T(X,xq) > NM_UNIQ_T(HIGH,highq)) \
++ ? NM_UNIQ_T(HIGH,highq) \
++ : (NM_UNIQ_T(X,xq) < NM_UNIQ_T(LOW,lowq)) \
++ ? NM_UNIQ_T(LOW,lowq) \
++ : NM_UNIQ_T(X,xq)); \
++ })
++
++/*****************************************************************************/
++
+ static inline guint
+ nm_encode_version (guint major, guint minor, guint micro) {
+ /* analog to the preprocessor macro NM_ENCODE_VERSION(). */