diff --git a/dockers/docker-teamd/teamd.j2 b/dockers/docker-teamd/teamd.j2 index d9ea1b790f89..9f53534a808b 100644 --- a/dockers/docker-teamd/teamd.j2 +++ b/dockers/docker-teamd/teamd.j2 @@ -4,8 +4,12 @@ "runner": { "name": "lacp", "active": true, +{% if PORTCHANNEL[pc]['fallback'] and ((PORTCHANNEL[pc]['members'] | length) == 1) %} + "fallback": {{ PORTCHANNEL[pc]['fallback'] }}, +{% 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/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..3139f83f33a4 --- /dev/null +++ b/src/libteam/0004-libteam-Add-lacp-fallback-support-for-single-member-.patch @@ -0,0 +1,104 @@ +From ec966f9a0229bd7226e3abe15b56659b36af9d66 Mon Sep 17 00:00:00 2001 +From: Haiyang Zheng +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 | 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 + diff --git a/src/libteam/Makefile b/src/libteam/Makefile index c84250749477..c96266a5c7fd 100644 --- a/src/libteam/Makefile +++ b/src/libteam/Makefile @@ -18,6 +18,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : git apply ../0001-libteam-Add-team_get_port_enabled-function.patch git apply ../0002-libteam-Temporarily-remove-redundant-debug-mes.patch git apply ../0003-teamd-lacp-runner-will-send-lacp-update-right-after-.patch + git apply ../0004-libteam-Add-lacp-fallback-support-for-single-member-.patch popd # Obtain debian packaging 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 = []