[teamd] do not process lacpdu before the port ifinfo is set (#2815)

Port libteam patch which fixes the race condition we observed during
warm reboot.

Remove early patches: 0006, 0008, 0009.

Signed-off-by: Ying Xie <ying.xie@microsoft.com>
This commit is contained in:
Ying Xie 2019-04-29 17:56:42 -07:00 committed by Ying Xie
parent 675a89959a
commit e4a663a606
5 changed files with 48 additions and 173 deletions

View File

@ -1,45 +0,0 @@
From 9a27e9b85afbbf6235e61c2426481e49a2139219 Mon Sep 17 00:00:00 2001
From: Shu0T1an ChenG <shuche@microsoft.com>
Date: Tue, 15 Jan 2019 12:23:02 -0800
Subject: [PATCH] Fix ifinfo_link_with_port race condition with newlink
The race condition could happen like this:
When an interface is enslaved into the port channel immediately after
it is created, the order of creating the ifinfo and linking the ifinfo to
the port is not guaranteed.
The team handler will listen to both netlink message to track new links
get created to allocate the ifinfo and add the ifinfo into its linked list,
and the team port change message to link the new port with ifinfo found
in its linkedin list. However, when the ifinfo is not yet created, the error
message "Failed to link port with ifinfo" is thrown with member port failed
to be added into the team handler's port list.
This fix adds a condition to check if ifinfo_link_with_port is linking ifinfo
to a port or to the team interface itself. If it is a port, ifinfo_find_create
function is used to fix the race condition.
Signed-off-by: Shu0T1an ChenG <shuche@microsoft.com>
---
libteam/ifinfo.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libteam/ifinfo.c b/libteam/ifinfo.c
index 44de4ca..444e0cd 100644
--- a/libteam/ifinfo.c
+++ b/libteam/ifinfo.c
@@ -429,7 +429,10 @@ int ifinfo_link_with_port(struct team_handle *th, uint32_t ifindex,
{
struct team_ifinfo *ifinfo;
- ifinfo = ifinfo_find(th, ifindex);
+ if (port)
+ ifinfo = ifinfo_find_create(th, ifindex);
+ else
+ ifinfo = ifinfo_find(th, ifindex);
if (!ifinfo)
return -ENOENT;
if (ifinfo->linked)
--
2.1.4

View File

@ -1,34 +0,0 @@
From 7dff9798c2c92eb75b0120737efb81febcdb80c1 Mon Sep 17 00:00:00 2001
From: Ying Xie <ying.xie@microsoft.com>
Date: Sun, 24 Mar 2019 21:49:59 +0000
Subject: [PATCH] [teamd] register change handler for TEAM_IFINFO_CHANGE as
well
There has been a race condition in the libnal/teamd interation, causing
TEAM_PORT_CHANGE to report a port with empty device name. Which then
causes the teamd unable to add the lag members into the lag.
Registering to the TEAM_IFINFO_CHANGE would give teamd another chance to
add member again.
Signed-off-by: Ying Xie <ying.xie@microsoft.com>
---
teamd/teamd_per_port.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/teamd/teamd_per_port.c b/teamd/teamd_per_port.c
index 09d1dc7..137da57 100644
--- a/teamd/teamd_per_port.c
+++ b/teamd/teamd_per_port.c
@@ -274,7 +274,7 @@ static int port_priv_change_handler_func(struct team_handle *th, void *priv,
static const struct team_change_handler port_priv_change_handler = {
.func = port_priv_change_handler_func,
- .type_mask = TEAM_PORT_CHANGE,
+ .type_mask = TEAM_PORT_CHANGE | TEAM_IFINFO_CHANGE,
};
int teamd_per_port_init(struct teamd_context *ctx)
--
2.7.4

View File

@ -1,90 +0,0 @@
From fb00b070482dc587eec7b4e34acec094be1af00d Mon Sep 17 00:00:00 2001
From: Ying Xie <ying.xie@microsoft.com>
Date: Fri, 29 Mar 2019 20:54:49 +0000
Subject: [PATCH 10/11] [teamd] prevent private change handler reentrance
While handling PORT_CHANGE, teamd could casue an INTERFACE_CHANGE in the
same context. Which will interfere with the PORT_CHANGE handling and
causing it to fail.
Lock is not needed because the re-entrance happened in the same thread
context.
This issue was noticed while dynamically adding a port into a lag.
Signed-off-by: Ying Xie <ying.xie@microsoft.com>
---
teamd/teamd.c | 2 ++
teamd/teamd.h | 2 ++
teamd/teamd_per_port.c | 13 +++++++++++--
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/teamd/teamd.c b/teamd/teamd.c
index e28aa7d..140b98b 100644
--- a/teamd/teamd.c
+++ b/teamd/teamd.c
@@ -1255,6 +1255,8 @@ static int teamd_init(struct teamd_context *ctx)
{
int err;
+ ctx->reentrant = false;
+
ctx->th = team_alloc();
if (!ctx->th) {
teamd_log_err("Team alloc failed.");
diff --git a/teamd/teamd.h b/teamd/teamd.h
index 622c365..7cd3266 100644
--- a/teamd/teamd.h
+++ b/teamd/teamd.h
@@ -160,6 +160,8 @@ struct teamd_context {
int pipe_r;
int pipe_w;
} workq;
+
+ bool reentrant;
};
struct teamd_port {
diff --git a/teamd/teamd_per_port.c b/teamd/teamd_per_port.c
index 137da57..8b4a457 100644
--- a/teamd/teamd_per_port.c
+++ b/teamd/teamd_per_port.c
@@ -250,6 +250,10 @@ static int port_priv_change_handler_func(struct team_handle *th, void *priv,
struct port_obj *port_obj;
int err;
+ if (ctx->reentrant) {
+ return 0;
+ }
+ ctx->reentrant = true;
team_for_each_port(port, th) {
uint32_t ifindex = team_get_port_ifindex(port);
@@ -258,17 +262,22 @@ static int port_priv_change_handler_func(struct team_handle *th, void *priv,
if (team_is_port_removed(port))
continue;
err = port_obj_create(ctx, &port_obj, ifindex, port);
- if (err)
+ if (err) {
+ ctx->reentrant = false;
return err;
+ }
}
if (team_is_port_changed(port)) {
err = teamd_event_port_changed(ctx, _port(port_obj));
- if (err)
+ if (err) {
+ ctx->reentrant = false;
return err;
+ }
}
if (team_is_port_removed(port))
port_obj_remove(ctx, port_obj);
}
+ ctx->reentrant = false;
return 0;
}
--
2.7.4

View File

@ -0,0 +1,46 @@
From 28ccb37eb388e7e3d214a9b05011f8421f0d65ac Mon Sep 17 00:00:00 2001
From: Ying Xie <ying.xie@microsoft.com>
Date: Fri, 26 Apr 2019 23:30:38 +0000
Subject: [PATCH] teamd: do not process lacpdu before the port ifinfo is set
Now the port ifinfo will be set in obj_input_newlink when a RTM_NEWLINK
event is received.
But when a port is being added, if a lacpdu gets received on this port
before the RTM_NEWLINK event, lacpdu_recv will process the packet with
incorrect port ifinfo.
In Patrick's case, as ifinfo->master_ifindex was 0, it would skip this
port in teamd_for_each_tdport, which caused lacp_port->agg_lead not to
be updated in lacp_switch_agg_lead. Later the lacp_port actor would go
to a unexpected state.
This patch is to avoid it by checking teamd_port_present in lacpdu_recv
so that it would not process lacpdu before the port ifinfo is set.
Reported-by: Patrick Talbert <ptalbert@redhat.com>
Tested-by: Patrick Talbert <ptalbert@redhat.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
teamd/teamd_runner_lacp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c
index 78f05dd..c8ae541 100644
--- a/teamd/teamd_runner_lacp.c
+++ b/teamd/teamd_runner_lacp.c
@@ -1132,6 +1132,9 @@ static int lacpdu_process(struct lacp_port *lacp_port, struct lacpdu* lacpdu)
{
int err;
+ if (!teamd_port_present(lacp_port->ctx, lacp_port->tdport))
+ return 0;
+
if (!lacpdu_check(lacpdu)) {
teamd_log_warn("malformed LACP PDU came.");
return 0;
--
2.7.4

View File

@ -3,9 +3,7 @@
0003-teamd-lacp-runner-will-send-lacp-update-right-after-.patch
0004-libteam-Add-lacp-fallback-support-for-single-member-.patch
0005-libteam-Add-warm_reboot-mode.patch
0006-Fix-ifinfo_link_with_port-race-condition-with-newlink.patch
0007-Skip-setting-the-same-hwaddr-to-lag-port-to-avoid-di.patch
0008-teamd-register-change-handler-for-TEAM_IFINFO_CHANGE.patch
0009-teamd-prevent-private-change-handler-reentrance.patch
0010-teamd-lacp-update-port-state-according-to-partners-sy.patch
0011-libteam-resynchronize-ifinfo-after-lost-RTNLGRP_LINK-.patch
0012-teamd-do-not-process-lacpdu-before-the-port-ifinfo-i.patch