-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libteam] Add fallback support for single-member-port LAG #1118
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
9dce7cc
[libteam] Add fallback support for single-member-port LAG
hzheng5 28f3439
[libteam] resolve the merge conflict
hzheng5 6d4f830
[team] Add lacp fallback config to teamd.j2 template
hzheng5 4d5358d
[teamd] Resolve config conflict between fallback and minlink
hzheng5 381d263
[teamd] Only enable fallback if it is single-member-port LAG
hzheng5 a16d686
[teamd] Removing the admin status check in lacp_port_link_update
hzheng5 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
From ec966f9a0229bd7226e3abe15b56659b36af9d66 Mon Sep 17 00:00:00 2001 | ||
From: Haiyang Zheng <haiyang.z@alibaba-inc.com> | ||
Date: Fri, 15 Dec 2017 21:07:53 -0800 | ||
Subject: [patch libteam] [libteam] Add fallback support for single-member-port | ||
LAG | ||
|
||
Signed-off-by: Haiyang Zheng <haiyang.z@alibaba-inc.com> | ||
--- | ||
teamd/teamd_runner_lacp.c | 42 ++++++++++++++++++++++++++++++++++++++++-- | ||
1 file changed, 40 insertions(+), 2 deletions(-) | ||
|
||
diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c | ||
index 9c77fae..a3646a6 100644 | ||
--- a/teamd/teamd_runner_lacp.c | ||
+++ b/teamd/teamd_runner_lacp.c | ||
@@ -138,6 +138,8 @@ struct lacp { | ||
#define LACP_CFG_DFLT_SYS_PRIO 0xffff | ||
bool fast_rate; | ||
#define LACP_CFG_DFLT_FAST_RATE false | ||
+ bool fallback; | ||
+#define LACP_CFG_DFLT_FALLBACK false | ||
int min_ports; | ||
#define LACP_CFG_DFLT_MIN_PORTS 1 | ||
enum lacp_agg_select_policy agg_select_policy; | ||
@@ -272,6 +274,11 @@ static int lacp_load_config(struct teamd_context *ctx, struct lacp *lacp) | ||
lacp->cfg.fast_rate = LACP_CFG_DFLT_FAST_RATE; | ||
teamd_log_dbg("Using fast_rate \"%d\".", lacp->cfg.fast_rate); | ||
|
||
+ err = teamd_config_bool_get(ctx, &lacp->cfg.fallback, "$.runner.fallback"); | ||
+ if (err) | ||
+ lacp->cfg.fallback = LACP_CFG_DFLT_FALLBACK; | ||
+ teamd_log_dbg("Using fallback \"%d\".", lacp->cfg.fallback); | ||
+ | ||
err = teamd_config_int_get(ctx, &tmp, "$.runner.min_ports"); | ||
if (err) { | ||
lacp->cfg.min_ports = LACP_CFG_DFLT_MIN_PORTS; | ||
@@ -308,9 +315,24 @@ static bool lacp_port_loopback_free(struct lacp_port *lacp_port) | ||
return true; | ||
} | ||
|
||
+/* | ||
+ * is_lacp_fallback_eligible - is lacp_port eligible to go into lacp fallback mode | ||
+ * | ||
+ * Return true if it is, false otherwise | ||
+ */ | ||
+static bool is_lacp_fallback_eligible(struct lacp_port *lacp_port) | ||
+{ | ||
+ teamd_log_dbg("%s fallback eligible state \"%d \" cfg \"%d\".", | ||
+ lacp_port->tdport->ifname, lacp_port->state, | ||
+ lacp_port->lacp->cfg.fallback); | ||
+ return lacp_port->state == PORT_STATE_DEFAULTED && | ||
+ lacp_port->lacp->cfg.fallback; | ||
+} | ||
+ | ||
static bool lacp_port_selectable_state(struct lacp_port *lacp_port) | ||
{ | ||
- if (lacp_port->state == PORT_STATE_CURRENT) | ||
+ if (lacp_port->state == PORT_STATE_CURRENT || | ||
+ is_lacp_fallback_eligible(lacp_port)) | ||
return true; | ||
return false; | ||
} | ||
@@ -318,7 +340,8 @@ static bool lacp_port_selectable_state(struct lacp_port *lacp_port) | ||
static bool lacp_port_unselectable_state(struct lacp_port *lacp_port) | ||
{ | ||
if (lacp_port->state == PORT_STATE_CURRENT || | ||
- lacp_port->state == PORT_STATE_EXPIRED) | ||
+ lacp_port->state == PORT_STATE_EXPIRED || | ||
+ is_lacp_fallback_eligible(lacp_port)) | ||
return false; | ||
return true; | ||
} | ||
@@ -1452,6 +1475,16 @@ static int lacp_state_fast_rate_get(struct teamd_context *ctx, | ||
return 0; | ||
} | ||
|
||
+static int lacp_state_fallback_get(struct teamd_context *ctx, | ||
+ struct team_state_gsc *gsc, | ||
+ void *priv) | ||
+{ | ||
+ struct lacp *lacp = priv; | ||
+ | ||
+ gsc->data.bool_val = lacp->cfg.fallback; | ||
+ return 0; | ||
+} | ||
+ | ||
static int lacp_state_select_policy_get(struct teamd_context *ctx, | ||
struct team_state_gsc *gsc, | ||
void *priv) | ||
@@ -1479,6 +1512,11 @@ static const struct teamd_state_val lacp_state_vals[] = { | ||
.getter = lacp_state_fast_rate_get, | ||
}, | ||
{ | ||
+ .subpath = "fallback", | ||
+ .type = TEAMD_STATE_ITEM_TYPE_BOOL, | ||
+ .getter = lacp_state_fallback_get, | ||
+ }, | ||
+ { | ||
.subpath = "select_policy", | ||
.type = TEAMD_STATE_ITEM_TYPE_STRING, | ||
.getter = lacp_state_select_policy_get, | ||
-- | ||
2.7.4 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that "fallback" feature is currently not supporting multi-member portchannels, but what would be the behavior if a user (deliberately/accidentally) enables "fallback" for more than one member? Shouldn't we write some logic in minigraph/config_db parsers to prevent those scenarios? If the current "fallback" logic were to allow more than one port to come up, I'm concerned about the implications that may have as we would be keeping two L2 "doors" wide-opened to the same server (traffic-loops, broadcast-storms, etc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @rodnymolina for the code review.
Ideally, we should have cfgmgr to check such misconfig and reject if fallback is configured on multiple member port. However, the infra is not ready yet. If we add logic in minigraph/config_db parsers to reject such case, there will be discrepancy between the config_db and the config we applied on the LAG unless the parser is able to update the config DB.
The fallback is disabled by default on all LAGs, and we will make it clear in the release note. Anyone using such feature should avoid such misconfig.
Please let me know if you think such check logic is needed. I can add it to the teamd.j2 template to disable the member port is more than 1. However the user may still manually add more member port after the LAG is created using teamd cli.
There is no way to complete block fallback on a multiple member LAG>
Thanks,
Haiyang
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand all that. In fact, you can indeed prevent users from enabling fallback on multiple members (that's what vendors do), but that requires extra logic on teamd to always determine a single "winner" port (based on mac, or port name, etc). But I'm not suggesting to do all that. What i'm saying is that given the potential consequences a bogus configuration may bring, i would suggest you to enforce some prevention logic somewhere (perhaps teamd.j2 is the right location while we wait for a proper configMgr). Personally, i don't know how a server may behave in early bootup-stages. For example, it could see both NICs as UP, and it may be tempted to send traffic through both of them. Now, what if it uses the same source IP? This may trigger mac-move/learning events across your entire broadcast-domain. In essence, this is not a problem i would like to troubleshoot in my network. I will leave the final decision to you, so i'll approve this review now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @rodnymolina
As you suggested, I added some logic to teamd.j2 to only enable fallback if it is a single-member-port LAG.
+{% if PORTCHANNEL[pc]['fallback'] and ((PORTCHANNEL[pc]['members'] | length) == 1) %}
+{# Set fallback only if it has single member port #}
Thanks,
Haiyang