From 9dce7cc0c307248db3b6832815d62e33d7c93c1b Mon Sep 17 00:00:00 2001 From: Haiyang Zheng Date: Mon, 6 Nov 2017 01:28:39 -0800 Subject: [PATCH 1/5] [libteam] Add fallback support for single-member-port LAG * Allow the port to be selected if the LAG is configured with fallback and port is in defaulted state due to missing LACP PDUs from remote end * Only enable port if LAG is admin up and the member port is link up --- ...-fallback-support-for-single-member-.patch | 151 ++++++++++++++++++ src/libteam/Makefile | 1 + 2 files changed, 152 insertions(+) create mode 100644 src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch diff --git a/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch b/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch new file mode 100644 index 000000000000..5150a2e5bc7e --- /dev/null +++ b/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch @@ -0,0 +1,151 @@ +From 08f4c83a6960fd922d1baac2293a95250f36fa96 Mon Sep 17 00:00:00 2001 +From: Haiyang Zheng +Date: Mon, 6 Nov 2017 00:24:00 -0800 +Subject: [patch libteam] libteam: Add lacp fallback support for + single-member-port LAG + +Signed-off-by: Haiyang Zheng +--- + teamd/teamd_runner_lacp.c | 67 ++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 61 insertions(+), 6 deletions(-) + +diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c +index 9c77fae..872af8a 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; + } +@@ -1002,6 +1025,12 @@ static int lacp_port_link_update(struct lacp_port *lacp_port) + uint32_t speed = team_get_port_speed(team_port); + uint8_t duplex = team_get_port_duplex(team_port); + int err; ++ bool admin_state; ++ ++ admin_state = team_get_ifinfo_admin_state(lacp_port->ctx->ifinfo); ++ teamd_log_dbg("%s admin_state \"%d\" link_up \"%d\".", ++ lacp_port->tdport->ifname, ++ admin_state, linkup); + + if (linkup != lacp_port->__link_last.up || + duplex != lacp_port->__link_last.duplex) { +@@ -1011,8 +1040,9 @@ static int lacp_port_link_update(struct lacp_port *lacp_port) + * will provide speed == 0 and duplex == 0. If that is the + * case now, do not set disabled state and allow such devices + * to work properly. ++ * Only enable port if the it is admin_up and link_up. + */ +- if (linkup && (!duplex == !speed)) ++ if (linkup && (!duplex == !speed) && admin_state) + err = lacp_port_set_state(lacp_port, PORT_STATE_EXPIRED); + else + err = lacp_port_set_state(lacp_port, PORT_STATE_DISABLED); +@@ -1344,9 +1374,19 @@ static int lacp_event_watch_admin_state_changed(struct teamd_context *ctx, + + teamd_for_each_tdport(tdport, ctx) { + struct lacp_port *lacp_port = lacp_port_get(lacp, tdport); +- +- err = lacp_port_set_state(lacp_port, +- admin_state?PORT_STATE_EXPIRED:PORT_STATE_DISABLED); ++ /* Only enable port if it is admin_up and link_up.*/ ++ if (lacp_port->__link_last.up) { ++ teamd_log_dbg("%s admin_state \"%d\" link_up.", ++ lacp_port->tdport->ifname, ++ admin_state); ++ err = lacp_port_set_state(lacp_port, ++ admin_state?PORT_STATE_EXPIRED:PORT_STATE_DISABLED); ++ } else { ++ teamd_log_dbg("%s admin_state \"%d\" link_down.", ++ lacp_port->tdport->ifname, ++ admin_state); ++ err = lacp_port_set_state(lacp_port, PORT_STATE_DISABLED); ++ } + if (err) + return err; + } +@@ -1452,6 +1492,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 +1529,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 + diff --git a/src/libteam/Makefile b/src/libteam/Makefile index c2b8a09cff6f..f2915104b4c4 100644 --- a/src/libteam/Makefile +++ b/src/libteam/Makefile @@ -17,6 +17,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : # Apply patch git apply ../0001-libteam-Add-team_get_port_enabled-function.patch git apply ../0002-libteam-Temporarily-remove-redundant-debug-mes.patch + git apply ../0004-libteam-Add-lacp-fallback-support-for-single-member-.patch popd # Obtain debian packaging From 6d4f830ca254d90dfb5040144379c55f26c905e2 Mon Sep 17 00:00:00 2001 From: Haiyang Zheng Date: Sun, 26 Nov 2017 14:31:50 -0800 Subject: [PATCH 2/5] [team] Add lacp fallback config to teamd.j2 template --- dockers/docker-teamd/teamd.j2 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dockers/docker-teamd/teamd.j2 b/dockers/docker-teamd/teamd.j2 index d9ea1b790f89..e082858d9572 100644 --- a/dockers/docker-teamd/teamd.j2 +++ b/dockers/docker-teamd/teamd.j2 @@ -4,6 +4,9 @@ "runner": { "name": "lacp", "active": true, +{% if PORTCHANNEL[pc]['fallback'] %} + "fallback": {{ PORTCHANNEL[pc]['fallback'] }}, +{% endif %} {# Use 75% links upperbound as min-links #} "min_ports": {{ (PORTCHANNEL[pc]['members'] | length * 0.75) | round(0, 'ceil') | int }}, "tx_hash": ["eth", "ipv4", "ipv6"] From 4d5358db89b6ed1142d26fae20a5529e3508e5c0 Mon Sep 17 00:00:00 2001 From: Haiyang Zheng Date: Wed, 6 Dec 2017 14:43:07 -0800 Subject: [PATCH 3/5] [teamd] Resolve config conflict between fallback and minlink * Remove min_link config if fallback is configured * Add support for fallback config in minigraph --- dockers/docker-teamd/teamd.j2 | 3 ++- src/sonic-config-engine/minigraph.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/dockers/docker-teamd/teamd.j2 b/dockers/docker-teamd/teamd.j2 index e082858d9572..c99aefaa54cc 100644 --- a/dockers/docker-teamd/teamd.j2 +++ b/dockers/docker-teamd/teamd.j2 @@ -6,9 +6,10 @@ "active": true, {% if PORTCHANNEL[pc]['fallback'] %} "fallback": {{ PORTCHANNEL[pc]['fallback'] }}, -{% endif %} +{% else %} {# Use 75% links upperbound as min-links #} "min_ports": {{ (PORTCHANNEL[pc]['members'] | length * 0.75) | round(0, 'ceil') | int }}, +{% endif %} "tx_hash": ["eth", "ipv4", "ipv6"] }, "link_watch": { diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index 826997063349..5c7bdfb3edc4 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -148,7 +148,10 @@ def parse_dpg(dpg, hname): pcmbr_list = pcintfmbr.split(';') for i, member in enumerate(pcmbr_list): pcmbr_list[i] = port_alias_map.get(member, member) - pcs[pcintfname] = {'members': pcmbr_list} + if pcintf.find(str(QName(ns, "Fallback"))) != None: + pcs[pcintfname] = {'members': pcmbr_list, 'fallback': pcintf.find(str(QName(ns, "Fallback"))).text} + else: + pcs[pcintfname] = {'members': pcmbr_list} vlanintfs = child.find(str(QName(ns, "VlanInterfaces"))) vlan_intfs = [] From 381d263e9a987d22f924f4eb1523805a8a272155 Mon Sep 17 00:00:00 2001 From: Haiyang Zheng Date: Tue, 12 Dec 2017 15:05:02 -0800 Subject: [PATCH 4/5] [teamd] Only enable fallback if it is single-member-port LAG Signed-off-by: Haiyang Zheng --- dockers/docker-teamd/teamd.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dockers/docker-teamd/teamd.j2 b/dockers/docker-teamd/teamd.j2 index c99aefaa54cc..9f53534a808b 100644 --- a/dockers/docker-teamd/teamd.j2 +++ b/dockers/docker-teamd/teamd.j2 @@ -4,7 +4,7 @@ "runner": { "name": "lacp", "active": true, -{% if PORTCHANNEL[pc]['fallback'] %} +{% if PORTCHANNEL[pc]['fallback'] and ((PORTCHANNEL[pc]['members'] | length) == 1) %} "fallback": {{ PORTCHANNEL[pc]['fallback'] }}, {% else %} {# Use 75% links upperbound as min-links #} From a16d686141d88b0988dd2c94ec6eb1dd4b0f6645 Mon Sep 17 00:00:00 2001 From: Haiyang Zheng Date: Fri, 15 Dec 2017 21:10:20 -0800 Subject: [PATCH 5/5] [teamd] Removing the admin status check in lacp_port_link_update Will submit another pull request to fix this issue. Signed-off-by: Haiyang Zheng --- ...-fallback-support-for-single-member-.patch | 67 +++---------------- 1 file changed, 10 insertions(+), 57 deletions(-) diff --git a/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch b/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch index 5150a2e5bc7e..3139f83f33a4 100644 --- a/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch +++ b/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch @@ -1,16 +1,16 @@ -From 08f4c83a6960fd922d1baac2293a95250f36fa96 Mon Sep 17 00:00:00 2001 +From ec966f9a0229bd7226e3abe15b56659b36af9d66 Mon Sep 17 00:00:00 2001 From: Haiyang Zheng -Date: Mon, 6 Nov 2017 00:24:00 -0800 -Subject: [patch libteam] libteam: Add lacp fallback support for - single-member-port LAG +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 --- - teamd/teamd_runner_lacp.c | 67 ++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 61 insertions(+), 6 deletions(-) + 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..872af8a 100644 +index 9c77fae..a3646a6 100644 --- a/teamd/teamd_runner_lacp.c +++ b/teamd/teamd_runner_lacp.c @@ -138,6 +138,8 @@ struct lacp { @@ -48,7 +48,7 @@ index 9c77fae..872af8a 100644 + 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 && ++ return lacp_port->state == PORT_STATE_DEFAULTED && + lacp_port->lacp->cfg.fallback; +} + @@ -70,54 +70,7 @@ index 9c77fae..872af8a 100644 return false; return true; } -@@ -1002,6 +1025,12 @@ static int lacp_port_link_update(struct lacp_port *lacp_port) - uint32_t speed = team_get_port_speed(team_port); - uint8_t duplex = team_get_port_duplex(team_port); - int err; -+ bool admin_state; -+ -+ admin_state = team_get_ifinfo_admin_state(lacp_port->ctx->ifinfo); -+ teamd_log_dbg("%s admin_state \"%d\" link_up \"%d\".", -+ lacp_port->tdport->ifname, -+ admin_state, linkup); - - if (linkup != lacp_port->__link_last.up || - duplex != lacp_port->__link_last.duplex) { -@@ -1011,8 +1040,9 @@ static int lacp_port_link_update(struct lacp_port *lacp_port) - * will provide speed == 0 and duplex == 0. If that is the - * case now, do not set disabled state and allow such devices - * to work properly. -+ * Only enable port if the it is admin_up and link_up. - */ -- if (linkup && (!duplex == !speed)) -+ if (linkup && (!duplex == !speed) && admin_state) - err = lacp_port_set_state(lacp_port, PORT_STATE_EXPIRED); - else - err = lacp_port_set_state(lacp_port, PORT_STATE_DISABLED); -@@ -1344,9 +1374,19 @@ static int lacp_event_watch_admin_state_changed(struct teamd_context *ctx, - - teamd_for_each_tdport(tdport, ctx) { - struct lacp_port *lacp_port = lacp_port_get(lacp, tdport); -- -- err = lacp_port_set_state(lacp_port, -- admin_state?PORT_STATE_EXPIRED:PORT_STATE_DISABLED); -+ /* Only enable port if it is admin_up and link_up.*/ -+ if (lacp_port->__link_last.up) { -+ teamd_log_dbg("%s admin_state \"%d\" link_up.", -+ lacp_port->tdport->ifname, -+ admin_state); -+ err = lacp_port_set_state(lacp_port, -+ admin_state?PORT_STATE_EXPIRED:PORT_STATE_DISABLED); -+ } else { -+ teamd_log_dbg("%s admin_state \"%d\" link_down.", -+ lacp_port->tdport->ifname, -+ admin_state); -+ err = lacp_port_set_state(lacp_port, PORT_STATE_DISABLED); -+ } - if (err) - return err; - } -@@ -1452,6 +1492,16 @@ static int lacp_state_fast_rate_get(struct teamd_context *ctx, +@@ -1452,6 +1475,16 @@ static int lacp_state_fast_rate_get(struct teamd_context *ctx, return 0; } @@ -134,7 +87,7 @@ index 9c77fae..872af8a 100644 static int lacp_state_select_policy_get(struct teamd_context *ctx, struct team_state_gsc *gsc, void *priv) -@@ -1479,6 +1529,11 @@ static const struct teamd_state_val lacp_state_vals[] = { +@@ -1479,6 +1512,11 @@ static const struct teamd_state_val lacp_state_vals[] = { .getter = lacp_state_fast_rate_get, }, {