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.
160 lines
5.6 KiB
160 lines
5.6 KiB
7 years ago
|
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
|
||
|
|