From 91ba49efb4c70407fe41efc66f2088a1d0da6f37 Mon Sep 17 00:00:00 2001 From: pavel-shirshov Date: Wed, 5 Feb 2020 01:09:16 -0800 Subject: [PATCH] teamd: fix possible race in master ifname callback (#4109) - What I did Ported a fix from libteam master to our master. Fixes #4070 Fixes #3649 - How I did it Applied patch jpirko/libteam@c723737 from upstream. - How to verify it Build image for your DUT and warm-reboot your DUT 10 times. Check that all PortChannels are up and no error messages in teamd.log --- ...sible-race-in-master-ifname-callback.patch | 101 ++++++++++++++++++ src/libteam/patch/series | 1 + 2 files changed, 102 insertions(+) create mode 100644 src/libteam/patch/0011-teamd-fix-possible-race-in-master-ifname-callback.patch diff --git a/src/libteam/patch/0011-teamd-fix-possible-race-in-master-ifname-callback.patch b/src/libteam/patch/0011-teamd-fix-possible-race-in-master-ifname-callback.patch new file mode 100644 index 000000000000..9203cd17c58b --- /dev/null +++ b/src/libteam/patch/0011-teamd-fix-possible-race-in-master-ifname-callback.patch @@ -0,0 +1,101 @@ +From c0eb9e4bfe1c6a0e77f02b1459d91498c1a3dcff Mon Sep 17 00:00:00 2001 +From: Pavel Shirshov +Date: Tue, 4 Feb 2020 09:39:08 -0800 +Subject: [PATCH 1/1] teamd: fix possible race in master ifname callback + +--- + teamd/teamd.h | 2 ++ + teamd/teamd_link_watch.c | 13 ++++++++++--- + teamd/teamd_per_port.c | 24 +++++++++++++++++++----- + 3 files changed, 31 insertions(+), 8 deletions(-) + +diff --git a/teamd/teamd.h b/teamd/teamd.h +index 418214d..1ce120e 100644 +--- a/teamd/teamd.h ++++ b/teamd/teamd.h +@@ -334,6 +334,8 @@ int teamd_port_remove_all(struct teamd_context *ctx); + void teamd_port_obj_remove_all(struct teamd_context *ctx); + int teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, + bool *enabled); ++int teamd_port_enabled_check(struct teamd_context *ctx, ++ struct teamd_port *tdport, bool *enabled); + int teamd_port_prio(struct teamd_context *ctx, struct teamd_port *tdport); + int teamd_port_check_enable(struct teamd_context *ctx, + struct teamd_port *tdport, +diff --git a/teamd/teamd_link_watch.c b/teamd/teamd_link_watch.c +index 62f8267..e4b3d3f 100644 +--- a/teamd/teamd_link_watch.c ++++ b/teamd/teamd_link_watch.c +@@ -423,9 +423,16 @@ static int link_watch_refresh_forced_send(struct teamd_context *ctx) + int err; + + teamd_for_each_tdport(tdport, ctx) { +- err = teamd_port_enabled(ctx, tdport, &port_enabled); +- if (err) +- return err; ++ err = teamd_port_enabled_check(ctx, tdport, &port_enabled); ++ if (err) { ++ /* Looks like the options are not ready for this port. ++ * This can happen when called from ++ * link_watch_port_master_ifindex_changed(). Skip this ++ * for now, let it be handled by future call of ++ * link_watch_enabled_option_changed(). ++ */ ++ continue; ++ } + __set_forced_send_for_port(tdport, port_enabled); + if (port_enabled) + enabled_port_count++; +diff --git a/teamd/teamd_per_port.c b/teamd/teamd_per_port.c +index a87e809..d10cfb2 100644 +--- a/teamd/teamd_per_port.c ++++ b/teamd/teamd_per_port.c +@@ -395,19 +395,21 @@ int teamd_port_remove_ifname(struct teamd_context *ctx, const char *port_name) + return teamd_port_remove(ctx, tdport); + } + +-int teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, +- bool *enabled) ++int __teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, ++ bool *enabled, bool may_fail) + { + struct team_option *option; + + option = team_get_option(ctx->th, "np", "enabled", tdport->ifindex); + if (!option) { +- teamd_log_err("%s: Failed to find \"enabled\" option.", +- tdport->ifname); ++ if (!may_fail) ++ teamd_log_err("%s: Failed to find \"enabled\" option.", ++ tdport->ifname); + return -ENOENT; + } + if (team_get_option_type(option) != TEAM_OPTION_TYPE_BOOL) { +- teamd_log_err("Unexpected type of \"enabled\" option."); ++ if (!may_fail) ++ teamd_log_err("Unexpected type of \"enabled\" option."); + return -EINVAL; + } + +@@ -415,6 +417,18 @@ int teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, + return 0; + } + ++int teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, ++ bool *enabled) ++{ ++ return __teamd_port_enabled(ctx, tdport, enabled, false); ++} ++ ++int teamd_port_enabled_check(struct teamd_context *ctx, ++ struct teamd_port *tdport, bool *enabled) ++{ ++ return __teamd_port_enabled(ctx, tdport, enabled, true); ++} ++ + int teamd_port_prio(struct teamd_context *ctx, struct teamd_port *tdport) + { + int prio; +-- +2.17.1.windows.2 + diff --git a/src/libteam/patch/series b/src/libteam/patch/series index 7be69525d9d0..62c39e780f1a 100644 --- a/src/libteam/patch/series +++ b/src/libteam/patch/series @@ -8,3 +8,4 @@ 0008-libteam-Add-warm_reboot-mode.patch 0009-Fix-ifinfo_link_with_port-race-condition-with-newlink.patch 0010-When-read-of-timerfd-returned-0-don-t-consider-this-.patch +0011-teamd-fix-possible-race-in-master-ifname-callback.patch