You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
5.6 KiB
159 lines
5.6 KiB
From efaa6ae709bb4b59efacb0bb7301be2242b058bc Mon Sep 17 00:00:00 2001 |
|
Message-Id: <efaa6ae709bb4b59efacb0bb7301be2242b058bc.1518205291.git.mleitner@redhat.com> |
|
From: Xin Long <lucien.xin@gmail.com> |
|
Date: Fri, 20 Oct 2017 12:35:07 +0800 |
|
Subject: [PATCH 1/3] teamd: add port_hwaddr_changed for ab runner |
|
|
|
This patch to fix an events processing race issue when adding two ports |
|
into one team dev with ab mode with same_all hwaddr policy: |
|
|
|
team0 original hwaddr: 00:00:00:00:00:0a |
|
port1 original hwaddr: 00:00:00:00:00:01 |
|
port2 original hwaddr: 00:00:00:00:00:02 |
|
|
|
There are two sockets in teamd: nl_cli.sock_event for ifinfo updates |
|
and nl_sock_event for ports/options changes. During adding two ports, |
|
the events on these two sockets could be: |
|
|
|
nl_sock_event: |
|
[1] -- [2] -- |
|
|
|
[1]: port1 added event (added by enslaving port1) |
|
[2]: port2 added event (added by enslaving port2) |
|
|
|
nl_cli.sock_event: |
|
[a1] -- [b0] -- [c1] -- [d2] -- [e2] -- [f1] -- |
|
|
|
[a1]: port1 ifinfo event (added by setting port1's master) |
|
[b0]: team0 ifinfo event (added by setting team0's hwaddr) |
|
[c1]: port1 ifinfo event (added by set port1's hwaddr) |
|
[d2]: port2 ifinfo event (added by set port2's master) |
|
[e2]: port2 ifinfo event (added by set port2's hwaddr) |
|
[f1]: port1 ifinfo event (added by set port1's hwaddr) |
|
|
|
teamd can make sure the order for their processing is as above on the |
|
same socket, but not between two sockets. So if these events processing |
|
order is (monitoring team/ports' ifinfo, hwaddr, master): |
|
|
|
[ 1]: team0->ifinfo = 00:00:00:00:00:0a |
|
team0->hwaddr = 00:00:00:00:00:01 |
|
port1->hwaddr = 00:00:00:00:00:0a |
|
[a1]: port1->ifinfo = 00:00:00:00:00:01 |
|
port1->master = team0 |
|
[ 2]: port2->ifinfo = 00:00:00:00:00:02 |
|
port2->hwaddr = 00:00:00:00:00:0a |
|
(team0->ifinfo is not updated, it's still 00:00:00:00:00:0a) |
|
[b0]: team0->ifinfo = 00:00:00:00:00:01 |
|
port1->hwaddr = 00:00:00:00:00:01 |
|
(port2->master is not yet set, port2->hwaddr couldn't be updated) |
|
[c1]: no changes |
|
[d2]: port2->ifinfo = 00:00:00:00:00:0a |
|
port2->master = team0 |
|
(too late !!!) |
|
[e2]: no changes |
|
[f1]: no changes |
|
|
|
Then: |
|
team0 final hwaddr: 00:00:00:00:00:01 |
|
port1 final hwaddr: 00:00:00:00:00:01 |
|
port2 final hwaddr: 00:00:00:00:00:0a <----- issue |
|
|
|
This patch is to add port_hwaddr_changed for ab runner, in [e2] where |
|
we set it's hwaddr with team0 (port2->hwaddr = 00:00:00:00:00:01) IF |
|
port2->hwaddr != team0->ifinfo. |
|
|
|
I think the same issue also exists in lacp and lb mode for which I will |
|
fix them in another patches. |
|
|
|
v1 -> v2: |
|
fix some typos in changelog and couple of style problems in codes |
|
|
|
Reported-by: Jon Nikolakakis <jnikolak@redhat.com> |
|
Signed-off-by: Xin Long <lucien.xin@gmail.com> |
|
Signed-off-by: Jiri Pirko <jiri@mellanox.com> |
|
Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com> |
|
--- |
|
teamd/teamd_runner_activebackup.c | 39 +++++++++++++++++++++++++++++++++++++++ |
|
1 file changed, 39 insertions(+) |
|
|
|
diff --git a/teamd/teamd_runner_activebackup.c b/teamd/teamd_runner_activebackup.c |
|
index aec3a73d5ff61534c377b935fe0e5bc1f51af79d..8a3447f1a63d71055eb7a8784cbe96381ee2b451 100644 |
|
--- a/teamd/teamd_runner_activebackup.c |
|
+++ b/teamd/teamd_runner_activebackup.c |
|
@@ -39,6 +39,8 @@ struct ab_hwaddr_policy { |
|
const char *name; |
|
int (*hwaddr_changed)(struct teamd_context *ctx, |
|
struct ab *ab); |
|
+ int (*port_hwaddr_changed)(struct teamd_context *ctx, struct ab *ab, |
|
+ struct teamd_port *tdport); |
|
int (*port_added)(struct teamd_context *ctx, struct ab *ab, |
|
struct teamd_port *tdport); |
|
int (*active_set)(struct teamd_context *ctx, struct ab *ab, |
|
@@ -95,6 +97,26 @@ static int ab_hwaddr_policy_same_all_hwaddr_changed(struct teamd_context *ctx, |
|
return 0; |
|
} |
|
|
|
+static int |
|
+ab_hwaddr_policy_same_all_port_hwaddr_changed(struct teamd_context *ctx, |
|
+ struct ab *ab, |
|
+ struct teamd_port *tdport) |
|
+{ |
|
+ int err; |
|
+ |
|
+ if (!memcmp(team_get_ifinfo_hwaddr(tdport->team_ifinfo), |
|
+ ctx->hwaddr, ctx->hwaddr_len)) |
|
+ return 0; |
|
+ |
|
+ err = team_hwaddr_set(ctx->th, tdport->ifindex, ctx->hwaddr, |
|
+ ctx->hwaddr_len); |
|
+ if (err) |
|
+ teamd_log_err("%s: Failed to set port hardware address.", |
|
+ tdport->ifname); |
|
+ |
|
+ return err; |
|
+} |
|
+ |
|
static int ab_hwaddr_policy_same_all_port_added(struct teamd_context *ctx, |
|
struct ab *ab, |
|
struct teamd_port *tdport) |
|
@@ -114,6 +136,7 @@ static int ab_hwaddr_policy_same_all_port_added(struct teamd_context *ctx, |
|
static const struct ab_hwaddr_policy ab_hwaddr_policy_same_all = { |
|
.name = "same_all", |
|
.hwaddr_changed = ab_hwaddr_policy_same_all_hwaddr_changed, |
|
+ .port_hwaddr_changed = ab_hwaddr_policy_same_all_port_hwaddr_changed, |
|
.port_added = ab_hwaddr_policy_same_all_port_added, |
|
}; |
|
|
|
@@ -411,6 +434,21 @@ static int ab_event_watch_hwaddr_changed(struct teamd_context *ctx, void *priv) |
|
return 0; |
|
} |
|
|
|
+static int ab_event_watch_port_hwaddr_changed(struct teamd_context *ctx, |
|
+ struct teamd_port *tdport, |
|
+ void *priv) |
|
+{ |
|
+ struct ab *ab = priv; |
|
+ |
|
+ if (!teamd_port_present(ctx, tdport)) |
|
+ return 0; |
|
+ |
|
+ if (ab->hwaddr_policy->port_hwaddr_changed) |
|
+ return ab->hwaddr_policy->port_hwaddr_changed(ctx, ab, tdport); |
|
+ |
|
+ return 0; |
|
+} |
|
+ |
|
static int ab_port_load_config(struct teamd_context *ctx, |
|
struct ab_port *ab_port) |
|
{ |
|
@@ -491,6 +529,7 @@ static int ab_event_watch_prio_option_changed(struct teamd_context *ctx, |
|
|
|
static const struct teamd_event_watch_ops ab_event_watch_ops = { |
|
.hwaddr_changed = ab_event_watch_hwaddr_changed, |
|
+ .port_hwaddr_changed = ab_event_watch_port_hwaddr_changed, |
|
.port_added = ab_event_watch_port_added, |
|
.port_link_changed = ab_event_watch_port_link_changed, |
|
.option_changed = ab_event_watch_prio_option_changed, |
|
-- |
|
2.14.3 |
|
|
|
|