summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2023-01-16 08:14:38 +0100
committerLubomir Rintel <lkundrak@v3.sk>2023-01-26 09:24:04 +0100
commit09eb729d599c468e2192a2dd9ad25134bd1aaeea (patch)
treebc5caed9e15fdda2c164b31b406c3913bbf579e2
parenta2345c318d479410c3cef2bb88b371fa608af809 (diff)
platform: retry link change on RESULT_FAILED_RESYNC
Sometimes the buffer space of the netlink socket runs out and we lose the response to our link change: <info> [1670321010.2952] platform-linux: netlink[rtnl]: read: too many netlink events. Need to resynchronize platform cache <warn> [1670321010.3467] platform-linux: do-change-link[2]: failure changing link: internal failure 3 With 3 above being WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC. Let's try harder. https://bugzilla.redhat.com/show_bug.cgi?id=2154350 (cherry picked from commit b8738002edd34c975b387d961458d2864c93c3ba)
-rw-r--r--src/libnm-platform/nm-linux-platform.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c
index 10c94933eb..b798d12d2a 100644
--- a/src/libnm-platform/nm-linux-platform.c
+++ b/src/libnm-platform/nm-linux-platform.c
@@ -7896,19 +7896,25 @@ do_change_link(NMPlatform *platform,
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
gs_free char *errmsg = NULL;
char s_buf[256];
- int result = 0;
- NMLogLevel log_level = LOGL_DEBUG;
- const char *log_detail = "";
+ int result;
+ NMLogLevel log_level;
+ const char *log_detail;
gs_free char *log_detail_free = NULL;
const NMPObject *obj_cache;
if (!nm_platform_netns_push(platform, &netns)) {
log_level = LOGL_ERR;
log_detail = ", failure to change network namespace";
+ result = -NME_UNSPEC;
goto out;
}
retry:
+ result = -NME_UNSPEC;
+ log_level = LOGL_WARN;
+ log_detail = "";
+ nm_clear_g_free(&log_detail_free);
+
nle = _netlink_send_nlmsg_rtnl(platform, nlmsg, &seq_result, &errmsg);
if (nle < 0) {
log_level = LOGL_ERR;
@@ -7926,13 +7932,19 @@ retry:
nm_assert(seq_result);
- if (NM_IN_SET(seq_result, -EOPNOTSUPP) && nlmsg_hdr(nlmsg)->nlmsg_type == RTM_NEWLINK) {
+ if (NM_IN_SET(seq_result, WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK, -EEXIST, -EADDRINUSE)) {
+ log_level = LOGL_DEBUG;
+ result = 0;
+ } else if (NM_IN_SET(seq_result, -EOPNOTSUPP) && nlmsg_hdr(nlmsg)->nlmsg_type == RTM_NEWLINK) {
nlmsg_hdr(nlmsg)->nlmsg_type = RTM_SETLINK;
- goto retry;
- }
- if (NM_IN_SET(seq_result, WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK, -EEXIST, -EADDRINUSE)) {
- /* */
+ log_level = LOGL_INFO;
+ log_detail = ", will try SETLINK instead of NEWLINK";
+ result = -EAGAIN;
+ } else if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_FAILED_RESYNC) {
+ log_level = LOGL_INFO;
+ log_detail = ", due to lost synchronization";
+ result = -EAGAIN;
} else if (NM_IN_SET(seq_result, -ESRCH, -ENOENT)) {
log_detail = ", firmware not found";
result = -NME_PL_NO_FIRMWARE;
@@ -7956,9 +7968,6 @@ retry:
} else if (seq_result == -EAFNOSUPPORT) {
log_level = LOGL_DEBUG;
result = -NME_PL_OPNOTSUPP;
- } else {
- log_level = LOGL_WARN;
- result = -NME_UNSPEC;
}
out:
@@ -7967,6 +7976,10 @@ out:
ifindex,
wait_for_nl_response_to_string(seq_result, errmsg, s_buf, sizeof(s_buf)),
log_detail);
+
+ if (result == -EAGAIN)
+ goto retry;
+
return result;
}