Merge branch 'github' into 201904

This commit is contained in:
Shu0T1an ChenG 2019-06-17 12:10:10 -07:00
commit e9de16391c
20 changed files with 596 additions and 208 deletions

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
# OS-generated files
.DS_Store
# Build system related
.platform
.screen

View File

@ -319,6 +319,7 @@ set /files/etc/sysctl.conf/kernel.core_pattern '|/usr/bin/coredump-compress %e %
set /files/etc/sysctl.conf/kernel.softlockup_panic 1
set /files/etc/sysctl.conf/kernel.panic 10
set /files/etc/sysctl.conf/vm.panic_on_oom 2
set /files/etc/sysctl.conf/fs.suid_dumpable 2
set /files/etc/sysctl.conf/net.ipv4.conf.default.forwarding 1

View File

@ -2,6 +2,8 @@
try:
import time
import string
from ctypes import create_string_buffer
from sonic_sfp.sfputilbase import SfpUtilBase
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
@ -108,12 +110,6 @@ class SfpUtil(SfpUtilBase):
reg_file.write('1')
reg_file.close()
return True
def set_low_power_mode(self, port_nuM, lpmode):
raise NotImplementedError
def get_low_power_mode(self, port_num):
raise NotImplementedError
def get_presence(self, port_num):
# Check for invalid port_num
@ -159,3 +155,61 @@ class SfpUtil(SfpUtilBase):
on this platform.
"""
raise NotImplementedError
def get_low_power_mode(self, port_num):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
try:
eeprom = None
if not self.get_presence(port_num):
return False
eeprom = open(self.port_to_eeprom_mapping[port_num], "rb")
eeprom.seek(93)
lpmode = ord(eeprom.read(1))
if ((lpmode & 0x3) == 0x3):
return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1
else:
return False # High Power Mode if one of the following conditions is matched:
# 1. "Power override" bit is 0
# 2. "Power override" bit is 1 and "Power set" bit is 0
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
finally:
if eeprom is not None:
eeprom.close()
time.sleep(0.01)
def set_low_power_mode(self, port_num, lpmode):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
try:
eeprom = None
if not self.get_presence(port_num):
return False # Port is not present, unable to set the eeprom
# Fill in write buffer
regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode
buffer = create_string_buffer(1)
buffer[0] = chr(regval)
# Write to eeprom
eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b")
eeprom.seek(93)
eeprom.write(buffer[0])
return True
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
finally:
if eeprom is not None:
eeprom.close()
time.sleep(0.01)

View File

@ -1,7 +1,7 @@
{% set default_cable = '5m' %}
{% set ingress_lossless_pool_size = '8224768' %}
{% set ingress_lossy_pool_size = '8224768' %}
{% set egress_lossless_pool_size = '41943024' %}
{% set egress_lossless_pool_size = '38797200' %}
{% set egress_lossy_pool_size = '8224768' %}
{%- macro generate_port_lists(PORT_ALL) %}

View File

@ -1,7 +1,7 @@
{% set default_cable = '5m' %}
{% set ingress_lossless_pool_size = '12042240' %}
{% set ingress_lossy_pool_size = '12042240' %}
{% set egress_lossless_pool_size = '41943024' %}
{% set egress_lossless_pool_size = '38797200' %}
{% set egress_lossy_pool_size = '12042240' %}
{%- macro generate_port_lists(PORT_ALL) %}

View File

@ -29,6 +29,9 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
no bgp default ipv4-unicast
bgp graceful-restart restart-time 240
bgp graceful-restart
{% if DEVICE_METADATA['localhost']['type'] == 'ToRRouter' %}
bgp graceful-restart preserve-fw-state
{% endif %}
{% for (name, prefix) in LOOPBACK_INTERFACE|pfx_filter %}
{% if prefix | ipv4 and name == 'Loopback0' %}
bgp router-id {{ prefix | ip }}
@ -77,6 +80,12 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
{% endif %}
neighbor {{ neighbor_addr }} activate
neighbor {{ neighbor_addr }} soft-reconfiguration inbound
{% if bgp_session['rrclient'] | int != 0 %}
neighbor {{ neighbor_addr }} route-reflector-client
{% endif %}
{% if bgp_session['nhopself'] | int != 0 %}
neighbor {{ neighbor_addr }} next-hop-self
{% endif %}
maximum-paths 64
exit-address-family
{% endif %}
@ -87,6 +96,15 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
{% endif %}
neighbor {{ neighbor_addr }} activate
neighbor {{ neighbor_addr }} soft-reconfiguration inbound
{% if bgp_session['rrclient'] | int != 0 %}
neighbor {{ neighbor_addr }} route-reflector-client
{% endif %}
{% if bgp_session['nhopself'] | int != 0 %}
neighbor {{ neighbor_addr }} next-hop-self
{% endif %}
{% if bgp_session['asn'] != DEVICE_METADATA['localhost']['bgp_asn'] %}
neighbor {{ neighbor_addr }} route-map set-next-hop-global-v6 in
{% endif %}
maximum-paths 64
exit-address-family
{% endif %}
@ -138,3 +156,6 @@ route-map ISOLATE permit 10
set as-path prepend {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
{% endif %}
!
route-map set-next-hop-global-v6 permit 10
set ipv6 next-hop prefer-global
!

View File

@ -7,12 +7,12 @@ CONFIG_TYPE=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["docker_routing_co
if [ -z "$CONFIG_TYPE" ] || [ "$CONFIG_TYPE" == "separated" ]; then
sonic-cfggen -d -y /etc/sonic/deployment_id_asn_map.yml -t /usr/share/sonic/templates/bgpd.conf.j2 > /etc/frr/bgpd.conf
sonic-cfggen -d -t /usr/share/sonic/templates/zebra.conf.j2 > /etc/frr/zebra.conf
touch /etc/frr/vtysh.conf
echo "no service integrated-vtysh-config" > /etc/frr/vtysh.conf
rm -f /etc/frr/frr.conf
elif [ "$CONFIG_TYPE" == "unified" ]; then
sonic-cfggen -d -y /etc/sonic/deployment_id_asn_map.yml -t /usr/share/sonic/templates/frr.conf.j2 >/etc/frr/frr.conf
echo "service integrated-vtysh-config" > /etc/frr/vtysh.conf
rm -f /etc/frr/bgpd.conf /etc/frr/vtysh.conf
rm -f /etc/frr/bgpd.conf /etc/frr/zebra.conf
fi
sonic-cfggen -d -t /usr/share/sonic/templates/isolate.j2 > /usr/sbin/bgp-isolate

View File

@ -12,7 +12,8 @@
{
"SWITCH_TABLE:switch": {
"ecmp_hash_seed": "{{ hash_seed }}",
"lag_hash_seed": "{{ hash_seed }}"
"lag_hash_seed": "{{ hash_seed }}",
"fdb_aging_time": "600"
},
"OP": "SET"
}

View File

@ -7,7 +7,7 @@ RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%s
ENV DEBIAN_FRONTEND=noninteractive
# Install required packages
RUN apt-get update && apt-get install -y python-pip libpython2.7 ipmitool librrd8 librrd-dev rrdtool python-smbus ethtool
RUN apt-get update && apt-get install -y python-pip libpython2.7 ipmitool librrd8 librrd-dev rrdtool python-smbus ethtool dmidecode
{% if docker_platform_monitor_debs.strip() -%}
# Copy locally-built Debian package dependencies

View File

@ -130,8 +130,8 @@ start() {
{%- else %}
# Obtain our HWSKU as we will mount directories with these names in each docker
HWSKU=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hwsku"]'`
HOSTNAME=`sonic-cfggen -d -v 'DEVICE_METADATA["localhost"]["hostname"]'`
{%- endif %}
HOSTNAME=`sonic-cfggen -m -v 'DEVICE_METADATA["localhost"]["hostname"]'`
if [ -z "$HOSTNAME" ] || ! [[ $HOSTNAME =~ ^[a-zA-Z0-9.\-]*$ ]]; then
HOSTNAME=`hostname`
fi
@ -175,19 +175,16 @@ start() {
{%- endif %}
{%- if sonic_asic_platform == "mellanox" %}
{%- if docker_container_name == "syncd" %}
-e SX_SNIFFER_ENABLE \
-e SX_SNIFFER_TARGET \
-e PRM_SNIFFER \
-e PRM_SNIFFER_FILE_PATH \
-v /var/log/mellanox/sniffer:/var/log/mellanox/sniffer:rw \
-v mlnx_sdk_socket:/tmp \
-v /dev/shm:/dev/shm:rw \
{%- elif docker_container_name == "pmon" %}
-v /var/run/hw-management:/var/run/hw-management:rw \
-v mlnx_sdk_socket:/tmp \
-v /dev/shm:/dev/shm:rw \
{%- else %}
--tmpfs /tmp \
{%- endif %}
{%- if docker_container_name == "pmon" %}
-v /var/run/hw-management:/var/run/hw-management:rw \
{%- endif %}
{%- endif %}
-v /var/run/redis:/var/run/redis:rw \
-v /usr/share/sonic/device/$PLATFORM:/usr/share/sonic/platform:ro \

View File

@ -288,6 +288,11 @@ sudo chroot $FILESYSTEM_ROOT docker info
{% set imagename = imagefilename.split('.')|first -%}
sudo LANG=C chroot $FILESYSTEM_ROOT docker load < {{image}}
sudo LANG=C chroot $FILESYSTEM_ROOT docker tag {{imagename}}:latest {{imagename}}:$(sonic_get_version)
{% if imagename.endswith('-dbg') %}
{% set imagebasename = imagename.replace('-dbg', '') -%}
sudo LANG=C chroot $FILESYSTEM_ROOT docker tag {{imagename}}:latest {{imagebasename}}:$(sonic_get_version)
sudo LANG=C chroot $FILESYSTEM_ROOT docker tag {{imagename}}:latest {{imagebasename}}:latest
{% endif %}
{% endfor %}
sudo chroot $FILESYSTEM_ROOT service docker stop
sudo rm $FILESYSTEM_ROOT/etc/init.d/docker

View File

@ -40,5 +40,11 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) \
$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) \
$(BRCM_XLR_GTS_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_IMAGES)
ifeq ($(INSTALL_DEBUG_TOOLS),y)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES))
else
$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES)
endif
SONIC_INSTALLERS += $(SONIC_ONE_IMAGE)

View File

@ -1,9 +1,9 @@
BRCM_SAI = libsaibcm_3.5.2.1_amd64.deb
$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.5s/libsaibcm_3.5.2.1_amd64.deb?sv=2015-04-05&sr=b&sig=VsOGePXPU9TtxXxQTkLfM%2FIzW6BL8q6RxP6QputuuEU%3D&se=2156-03-28T05%3A37%3A02Z&sp=r"
BRCM_SAI = libsaibcm_3.5.2.3_amd64.deb
$(BRCM_SAI)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.5/libsaibcm_3.5.2.3_amd64.deb?sv=2015-04-05&sr=b&sig=anY6TeLouYsw7L6hfpH%2BTHOkvF8M3WR%2B6P2C7Dh8sHg%3D&se=2033-02-20T17%3A19%3A46Z&sp=r"
BRCM_SAI_DEV = libsaibcm-dev_3.5.2.1_amd64.deb
BRCM_SAI_DEV = libsaibcm-dev_3.5.2.3_amd64.deb
$(eval $(call add_derived_package,$(BRCM_SAI),$(BRCM_SAI_DEV)))
$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.5s/libsaibcm-dev_3.5.2.1_amd64.deb?sv=2015-04-05&sr=b&sig=3pWbROLKK5ZuVcAra%2BYo1pk4B0k1P3C76wVw4KiqOtY%3D&se=2156-03-28T05%3A35%3A35Z&sp=r"
$(BRCM_SAI_DEV)_URL = "https://sonicstorage.blob.core.windows.net/packages/bcmsai/3.5/libsaibcm-dev_3.5.2.3_amd64.deb?sv=2015-04-05&sr=b&sig=o%2BVIKwVnlNv8LAvVzcS2kIXc0%2BIKaTzmA8LIkIfsh6c%3D&se=2033-02-20T17%3A20%3A03Z&sp=r"
SONIC_ONLINE_DEBS += $(BRCM_SAI)
$(BRCM_SAI_DEV)_DEPENDS += $(BRCM_SAI)

View File

@ -22,3 +22,6 @@ $(LIBSAIREDIS)_DEPENDS += $(MLNX_SAI) $(LIBSAITHRIFT_DEV)
# Runtime dependency on mlnx sai is set only for syncd
$(SYNCD)_RDEPENDS += $(MLNX_SAI)
# Inject mlnx sdk libs to platform monitor
$(DOCKER_PLATFORM_MONITOR)_DEPENDS += $(APPLIBS) $(SX_COMPLIB) $(SXD_LIBS) $(SX_GEN_UTILS) $(PYTHON_SDK_API) $(APPLIBS_DEV) $(SX_COMPLIB_DEV) $(SXD_LIBS_DEV) $(SX_GEN_UTILS_DEV)

View File

@ -541,7 +541,8 @@ $(addprefix $(TARGET_PATH)/, $(DOCKER_DBG_IMAGES)) : $(TARGET_PATH)/%-$(DBG_IMAG
./build_debug_docker_j2.sh $* $(subst -,_,$(notdir $($*.gz_PATH)))_dbg_debs $(subst -,_,$(notdir $($*.gz_PATH)))_image_dbgs > $($*.gz_PATH)/Dockerfile-dbg.j2
j2 $($*.gz_PATH)/Dockerfile-dbg.j2 > $($*.gz_PATH)/Dockerfile-dbg
docker info $(LOG)
docker build --squash --no-cache \
docker build \
$(if $($*.gz_DBG_DEPENDS), --squash --no-cache, --no-cache) \
--build-arg http_proxy=$(HTTP_PROXY) \
--build-arg https_proxy=$(HTTPS_PROXY) \
--build-arg docker_container_name=$($*.gz_CONTAINER_NAME) \
@ -617,19 +618,19 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
$(foreach docker, $($*_DOCKERS),\
export docker_image="$(docker)"
export docker_image_name="$(basename $(docker))"
export docker_container_name="$($(docker)_CONTAINER_NAME)"
$(eval $(docker)_RUN_OPT += $($(docker)_$($*_IMAGE_TYPE)_RUN_OPT))
export docker_image_run_opt="$($(docker)_RUN_OPT)"
j2 files/build_templates/docker_image_ctl.j2 > $($(docker)_CONTAINER_NAME).sh
if [ -f files/build_templates/$($(docker)_CONTAINER_NAME).service.j2 ]; then
j2 files/build_templates/$($(docker)_CONTAINER_NAME).service.j2 > $($(docker)_CONTAINER_NAME).service
export docker_container_name="$($(docker:-dbg.gz=.gz)_CONTAINER_NAME)"
$(eval $(docker:-dbg.gz=.gz)_RUN_OPT += $($(docker:-dbg.gz=.gz)_$($*_IMAGE_TYPE)_RUN_OPT))
export docker_image_run_opt="$($(docker:-dbg.gz=.gz)_RUN_OPT)"
j2 files/build_templates/docker_image_ctl.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).sh
if [ -f files/build_templates/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 ]; then
j2 files/build_templates/$($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service.j2 > $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service
fi
chmod +x $($(docker)_CONTAINER_NAME).sh
chmod +x $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).sh
)
export installer_start_scripts="$(foreach docker, $($*_DOCKERS),$(addsuffix .sh, $($(docker)_CONTAINER_NAME)))"
export installer_services="$(foreach docker, $($*_DOCKERS),$(addsuffix .service, $($(docker)_CONTAINER_NAME)))"
export installer_extra_files="$(foreach docker, $($*_DOCKERS), $(foreach file, $($(docker)_BASE_IMAGE_FILES), $($(docker)_PATH)/base_image_files/$(file)))"
export installer_start_scripts="$(foreach docker, $($*_DOCKERS),$(addsuffix .sh, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME)))"
export installer_services="$(foreach docker, $($*_DOCKERS),$(addsuffix .service, $($(docker:-dbg.gz=.gz)_CONTAINER_NAME)))"
export installer_extra_files="$(foreach docker, $($*_DOCKERS), $(foreach file, $($(docker:-dbg.gz=.gz)_BASE_IMAGE_FILES), $($(docker:-dbg.gz=.gz)_PATH)/base_image_files/$(file)))"
j2 -f env files/initramfs-tools/union-mount.j2 onie-image.conf > files/initramfs-tools/union-mount
j2 -f env files/initramfs-tools/arista-convertfs.j2 onie-image.conf > files/initramfs-tools/arista-convertfs
@ -652,8 +653,8 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
./build_image.sh $(LOG)
$(foreach docker, $($*_DOCKERS), \
rm -f $($(docker)_CONTAINER_NAME).sh
rm -f $($(docker)_CONTAINER_NAME).service
rm -f $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).sh
rm -f $($(docker:-dbg.gz=.gz)_CONTAINER_NAME).service
)
$(if $($*_DOCKERS),

View File

@ -1,18 +1,15 @@
From fe097ebcadd52e56a589c38a9c821cf1a84d6b67 Mon Sep 17 00:00:00 2001
From: yorke <yorke.yuan@asterfusion.com>
Date: Mon, 3 Jun 2019 14:48:14 +0800
Subject: [PATCH 8/8] [libteam] Add warm_reboot mode From: pavel-shirshov
<pavelsh@microsoft.com> and Ying Xie <ying.xie@microsoft.com>
https://github.com/Azure/sonic-buildimage/pull/2173
From a21a3dec9f9b9d825a0229e2963e07862395bbba Mon Sep 17 00:00:00 2001
From: Pavel Shirshov <pavelsh@microsoft.com>
Date: Fri, 14 Jun 2019 14:20:05 -0700
Subject: [PATCH] [libteam]: Reimplement Warm-Reboot procedure
Signed-off-by: yorke <yorke.yuan@asterfusion.com>
---
libteam/ifinfo.c | 6 +-
teamd/teamd.c | 46 +++++++++-
teamd/teamd.h | 7 ++
teamd/teamd_events.c | 13 +++
teamd/teamd_runner_lacp.c | 209 +++++++++++++++++++++++++++++++++++++++-------
5 files changed, 245 insertions(+), 36 deletions(-)
teamd/teamd.c | 42 +++-
teamd/teamd.h | 6 +
teamd/teamd_events.c | 13 ++
teamd/teamd_runner_lacp.c | 474 +++++++++++++++++++++++++++++++++++---
5 files changed, 498 insertions(+), 43 deletions(-)
diff --git a/libteam/ifinfo.c b/libteam/ifinfo.c
index 46d56a2..b86d34c 100644
@ -37,7 +34,7 @@ index 46d56a2..b86d34c 100644
}
}
diff --git a/teamd/teamd.c b/teamd/teamd.c
index 9dc85b5..1a974d1 100644
index 9dc85b5..96794e8 100644
--- a/teamd/teamd.c
+++ b/teamd/teamd.c
@@ -117,7 +117,9 @@ static void print_help(const struct teamd_context *ctx) {
@ -51,15 +48,6 @@ index 9dc85b5..1a974d1 100644
ctx->argv0);
printf("Available runners: ");
for (i = 0; i < TEAMD_RUNNER_LIST_SIZE; i++) {
@@ -130,7 +132,7 @@ static void print_help(const struct teamd_context *ctx) {
static int parse_command_line(struct teamd_context *ctx,
int argc, char *argv[]) {
- int opt;
+ int opt, err;
static const struct option long_options[] = {
{ "help", no_argument, NULL, 'h' },
{ "daemonize", no_argument, NULL, 'd' },
@@ -151,10 +153,12 @@ static int parse_command_line(struct teamd_context *ctx,
{ "zmq-enable", required_argument, NULL, 'Z' },
{ "usock-enable", no_argument, NULL, 'U' },
@ -74,13 +62,12 @@ index 9dc85b5..1a974d1 100644
long_options, NULL)) >= 0) {
switch(opt) {
@@ -236,11 +240,29 @@ static int parse_command_line(struct teamd_context *ctx,
@@ -236,11 +240,27 @@ static int parse_command_line(struct teamd_context *ctx,
case 'u':
ctx->usock.enabled = false;
break;
+ case 'w':
+ ctx->warm_start_read = true;
+ ctx->warm_start_carrier = true;
+ ctx->warm_start_mode = true;
+ break;
+ case 'L':
+ ctx->lacp_directory = strdup(optarg);
@ -95,16 +82,15 @@ index 9dc85b5..1a974d1 100644
}
}
+ if (ctx->warm_start_read && !ctx->lacp_directory) {
+ if (ctx->warm_start_mode && !ctx->lacp_directory) {
+ fprintf(stderr, "Can't enable warm-start mode without lacp-directory specified\n");
+ ctx->warm_start_read = false;
+ ctx->warm_start_carrier = false;
+ ctx->warm_start_mode = false;
+ }
+
if (optind < argc) {
fprintf(stderr, "Too many arguments\n");
return -1;
@@ -390,8 +412,14 @@ static int teamd_run_loop_run(struct teamd_context *ctx)
@@ -390,8 +410,14 @@ static int teamd_run_loop_run(struct teamd_context *ctx)
if (err != -1) {
switch(ctrl_byte) {
case 'q':
@ -119,7 +105,7 @@ index 9dc85b5..1a974d1 100644
teamd_refresh_ports(ctx);
err = teamd_flush_ports(ctx);
if (err)
@@ -434,6 +462,12 @@ void teamd_run_loop_quit(struct teamd_context *ctx, int err)
@@ -434,6 +460,12 @@ void teamd_run_loop_quit(struct teamd_context *ctx, int err)
teamd_run_loop_sent_ctrl_byte(ctx, 'q');
}
@ -132,7 +118,7 @@ index 9dc85b5..1a974d1 100644
void teamd_run_loop_restart(struct teamd_context *ctx)
{
teamd_run_loop_sent_ctrl_byte(ctx, 'r');
@@ -700,6 +734,10 @@ static int callback_daemon_signal(struct teamd_context *ctx, int events,
@@ -700,6 +732,10 @@ static int callback_daemon_signal(struct teamd_context *ctx, int events,
teamd_log_warn("Got SIGINT, SIGQUIT or SIGTERM.");
teamd_run_loop_quit(ctx, 0);
break;
@ -143,7 +129,7 @@ index 9dc85b5..1a974d1 100644
}
return 0;
}
@@ -1531,7 +1569,7 @@ static int teamd_start(struct teamd_context *ctx, enum teamd_exit_code *p_ret)
@@ -1531,7 +1567,7 @@ static int teamd_start(struct teamd_context *ctx, enum teamd_exit_code *p_ret)
return -errno;
}
@ -153,21 +139,20 @@ index 9dc85b5..1a974d1 100644
daemon_retval_send(errno);
err = -errno;
diff --git a/teamd/teamd.h b/teamd/teamd.h
index e71a5dc..f83a2d9 100644
index e71a5dc..418214d 100644
--- a/teamd/teamd.h
+++ b/teamd/teamd.h
@@ -126,6 +126,10 @@ struct teamd_context {
@@ -126,6 +126,9 @@ struct teamd_context {
char * hwaddr;
uint32_t hwaddr_len;
bool hwaddr_explicit;
+ bool warm_start_read;
+ bool warm_start_carrier;
+ bool warm_start_mode;
+ bool keep_ports;
+ char * lacp_directory;
struct {
struct list_item callback_list;
int ctrl_pipe_r;
@@ -195,12 +199,15 @@ struct teamd_event_watch_ops {
@@ -195,12 +198,15 @@ struct teamd_event_watch_ops {
void *priv);
void (*refresh)(struct teamd_context *ctx,
struct teamd_port *tdport, void *priv);
@ -208,7 +193,7 @@ index 221803e..bd4dcc1 100644
struct teamd_port *tdport)
{
diff --git a/teamd/teamd_runner_lacp.c b/teamd/teamd_runner_lacp.c
index 4016b15..087efa9 100644
index 4016b15..81be5b7 100644
--- a/teamd/teamd_runner_lacp.c
+++ b/teamd/teamd_runner_lacp.c
@@ -31,6 +31,7 @@
@ -219,55 +204,348 @@ index 4016b15..087efa9 100644
#include "teamd.h"
#include "teamd_config.h"
@@ -131,6 +132,7 @@ struct lacp {
@@ -127,10 +128,18 @@ static const char *lacp_agg_select_policy_names_list[] = {
struct lacp_port;
+struct wr_tdport_state
+{
+ char name[IFNAMSIZ+1];
+ bool enabled;
+ bool checked;
+};
+
struct lacp {
struct teamd_context *ctx;
struct lacp_port *selected_agg_lead; /* leading port of selected aggregator */
bool carrier_up;
+ time_t warm_start_carrier_timer;
+ time_t warm_start_mode_timer;
struct {
bool active;
#define LACP_CFG_DFLT_ACTIVE true
@@ -174,6 +176,9 @@ struct lacp_port {
@@ -145,6 +154,11 @@ struct lacp {
enum lacp_agg_select_policy agg_select_policy;
#define LACP_CFG_DFLT_AGG_SELECT_POLICY LACP_AGG_SELECT_LACP_PRIO
} cfg;
+ struct {
+ bool carrier_up;
+ uint16_t nr_of_tdports;
+ struct wr_tdport_state *state;
+ } wr;
struct teamd_balancer *tb;
};
@@ -174,6 +188,8 @@ struct lacp_port {
struct lacp_port *agg_lead; /* leading port of aggregator.
* NULL in case this port is not selected */
enum lacp_port_state state;
+ bool lacpdu_saved;
+ bool lacpdu_read;
+ struct lacpdu last_pdu;
struct {
uint32_t speed;
uint8_t duplex;
@@ -493,15 +498,28 @@ static int lacp_update_carrier(struct lacp *lacp)
bool state;
@@ -189,6 +205,201 @@ struct lacp_port {
} cfg;
};
+static void generate_path(struct teamd_context *ctx, char path[PATH_MAX], const char* filename)
+{
+ strcpy(path, ctx->lacp_directory);
+ /* Add trailing slash if we don't have one in the filename */
+ if (path[strlen(path) - 1] != '/')
+ strcat(path, "/");
+ strcat(path, filename);
+}
+
+static int find_wr_info(struct lacp_port *lacp_port) {
+ struct lacp* lacp = lacp_port->lacp;
+ int i, found = -1;
+
+ for (i = 0; i < lacp->wr.nr_of_tdports; ++i) {
+ if (strcmp(lacp->wr.state[i].name, lacp_port->tdport->ifname) == 0) {
+ found = i;
+ break;
+ }
+ }
+
+ if (found == -1)
+ teamd_log_warn("WR-mode. Found a newly added LAG member port: '%s' after restart. "
+ "The configuration was changed?", lacp_port->tdport->ifname);
+
+ return found;
+}
+
+static void remove_file(struct teamd_context *ctx, const char *name) {
+ char filename[PATH_MAX];
+ int err;
+
+ generate_path(ctx, filename, name);
+
+ err = access(filename, R_OK);
+ if (err != 0) {
+ /* file is not present. Skip it */
+ return;
+ }
+
+ err = unlink(filename);
+ if (err < 0) {
+ teamd_log_err("WR-mode. Can't remove file %s: %s", filename, strerror(errno));
+ }
+}
+
+static void stop_wr_mode(struct lacp *lacp) {
+ int i;
+
+ teamd_log_info("WR-mode. Stopping WR start mode");
+
+ lacp->ctx->warm_start_mode = false;
+ lacp->warm_start_mode_timer = 0;
+
+ remove_file(lacp->ctx, lacp->ctx->team_devname);
+ for (i = 0; i < lacp->wr.nr_of_tdports; ++i) {
+ remove_file(lacp->ctx, lacp->wr.state[i].name);
+ }
+
+ lacp->wr.nr_of_tdports = 0;
+ if (lacp->wr.state)
+ free(lacp->wr.state);
+ lacp->wr.state = NULL;
+}
+
+static int lacpdu_read(struct lacp_port *lacp_port, struct lacpdu *lacpdu)
+{
+ FILE* fp;
+ char filename[PATH_MAX];
+ int err, nitems;
+
+ teamd_log_dbg("WR-mode. function lacpdu_read(): %s", lacp_port->tdport->ifname);
+
+ generate_path(lacp_port->ctx, filename, lacp_port->tdport->ifname);
+
+ /* check that file is readable. if there is no file, don't do anything */
+ err = access(filename, R_OK);
+ if (err != 0) {
+ teamd_log_err("WR-mode. LACPDU state file '%s' is unreadable", filename);
+ return err;
+ }
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ teamd_log_err("WR-mode. Can't open lacp-saved dump from file '%s': %s", filename, strerror(errno));
+ return errno;
+ }
+
+ nitems = fread(lacpdu, sizeof(struct lacpdu), 1, fp);
+ (void)fclose(fp);
+
+ err = unlink(filename);
+ if (err < 0) {
+ teamd_log_err("WR-mode. Can't remove file '%s': %s", filename, strerror(errno));
+ }
+
+ if (nitems != 1) {
+ teamd_log_err("WR-mode. Can't read lacp-saved dump from file '%s': %s", filename, strerror(errno));
+ return -EINVAL;
+ }
+
+ teamd_log_info("WR-mode. LACP state was read for port '%s'", lacp_port->tdport->ifname);
+
+ return 0;
+}
+
+static void lacp_state_save(struct teamd_context *ctx, struct lacp *lacp)
+{
+ char filename[PATH_MAX];
+ FILE *fp;
+ int i, err;
+
+ generate_path(ctx, filename, ctx->team_devname);
+
+ fp = fopen(filename, "wt");
+ if (!fp) {
+ teamd_log_err("WR-mode. Can't open the file '%s' to save the lacp dump: %s", filename, strerror(errno));
+ goto error;
+ }
+
+ err = fprintf(fp, "%d\n%d\n", lacp->carrier_up ? 1 : 0, lacp->wr.nr_of_tdports);
+ if (err < 0) {
+ teamd_log_err("WR-mode. Can't write to the file '%s' to save the lacp dump: %s", filename, strerror(errno));
+ goto error_with_close;
+ }
+
+ for (i = 0; i < lacp->wr.nr_of_tdports; ++i) {
+ err = fprintf(fp, "%s\n%d\n", lacp->wr.state[i].name, lacp->wr.state[i].enabled ? 1 : 0);
+ if (err < 0) {
+ teamd_log_err("WR-mode. Can't write to the file '%s' to save the lacp dump: %s", filename, strerror(errno));
+ goto error_with_close;
+ }
+ }
+
+error_with_close:
+ (void)fclose(fp);
+
+error:
+ (void)free(lacp->wr.state);
+ lacp->wr.state = NULL;
+ lacp->wr.nr_of_tdports = 0;
+}
+
+static int lacp_state_load(struct teamd_context *ctx, struct lacp *lacp)
+{
+ char filename[PATH_MAX];
+ FILE *fp;
+ int data1, data2, i, err;
+
+ teamd_log_dbg("WR-mode. function lacp_state_load()");
+
+ generate_path(ctx, filename, ctx->team_devname);
+
+ fp = fopen(filename, "rt");
+ if (!fp) {
+ teamd_log_err("WR-mode. Can't open the file '%s' to load the lacp dump: %s", filename, strerror(errno));
+ return errno;
+ }
+
+ err = fscanf(fp, "%d\n%d\n", &data1, &data2);
+ if (err != 2) {
+ teamd_log_err("WR-mode. Can't read the file '%s'. Wrong format", filename);
+ (void)fclose(fp);
+ return -1;
+ }
+ lacp->wr.carrier_up = data1 == 1;
+ lacp->wr.nr_of_tdports = data2;
+
+ lacp->wr.state = calloc(lacp->wr.nr_of_tdports, sizeof(struct wr_tdport_state));
+ if (!lacp->wr.state) {
+ teamd_log_err("WR-mode. lacp_state_load: Not enough memory. %s", ctx->team_devname);
+ return -1;
+ }
+ for (i = 0; i < lacp->wr.nr_of_tdports; ++i) {
+ err = fscanf(fp, "%16s\n%d\n", &lacp->wr.state[i].name[0], &data1);
+ if (err != 2) {
+ teamd_log_err("WR-mode. Can't read the file '%s'. Wrong format", filename);
+ (void)free(lacp->wr.state);
+ lacp->wr.state = NULL;
+ (void)fclose(fp);
+ return -1;
+ }
+ lacp->wr.state[i].enabled = data1 == 1;
+ lacp->wr.state[i].checked = false;
+ }
+
+ (void)fclose(fp);
+
+ err = unlink(filename);
+ if (err < 0) {
+ teamd_log_err("WR-mode. Can't remove file %s: %s", filename, strerror(errno));
+ }
+
+ return 0;
+}
+
static struct lacp_port *lacp_port_get(struct lacp *lacp,
struct teamd_port *tdport)
{
@@ -486,20 +697,95 @@ static int lacp_set_carrier(struct lacp *lacp, bool carrier_up)
return 0;
}
+static int lacpdu_process(struct lacp_port *lacp_port, struct lacpdu* lacpdu);
+
+#define LACP_WARM_START_CARRIER_TIMEOUT 3
+
static int lacp_update_carrier(struct lacp *lacp)
{
struct teamd_port *tdport;
int ports_enabled;
- bool state;
int err;
+ #define WARM_START_CARRIER_TIMEOUT 3
+ /* wait three seconds until disable warm_start_carrier mode */
+ if (lacp->ctx->warm_start_carrier &&
+ lacp->warm_start_carrier_timer >= (time(NULL) + WARM_START_CARRIER_TIMEOUT)) {
+ lacp->ctx->warm_start_carrier = false;
+ lacp->warm_start_carrier_timer = 0;
+ if (lacp->ctx->warm_start_mode) {
+ teamd_log_dbg("WR-mode. function lacp_update_carrier()");
+ }
+
ports_enabled = 0;
teamd_for_each_tdport(tdport, lacp->ctx) {
+ bool state;
err = teamd_port_enabled(lacp->ctx, tdport, &state);
if (err)
return err;
- if (state && ++ports_enabled >= lacp->cfg.min_ports)
+ if (state && ++ports_enabled >= lacp->cfg.min_ports) {
+ lacp->ctx->warm_start_carrier = false;
return lacp_set_carrier(lacp, true);
- return lacp_set_carrier(lacp, true);
+
+ if (state)
+ ++ports_enabled;
+
+ if (lacp->ctx->warm_start_mode) {
+ int found;
+ struct lacp_port* lacp_port;
+ bool linkup;
+
+ lacp_port = lacp_port_get(lacp, tdport);
+ found = find_wr_info(lacp_port);
+ if (found < 0) /* newly added port was found */
+ continue;
+
+ linkup = team_is_port_link_up(lacp_port->tdport->team_port);
+ if (linkup) { /* read when the port is in carrier up state */
+ if (!lacp->wr.state[found].checked) {
+ lacp->wr.state[found].checked = true;
+
+ if(lacp->wr.state[found].enabled) {
+ /* the port was up before the WR. Trying to restore it */
+ struct lacpdu lacpdu;
+ err = lacpdu_read(lacp_port, &lacpdu);
+ if (err) /* Can't read, so the port will start from scratch */
+ continue;
+ teamd_log_info("WR-mode. State of the LAG member port '%s' was restored.",
+ tdport->ifname);
+ return lacpdu_process(lacp_port, &lacpdu); /* it runs lacp_update_carrier() inside of it */
+ } else {
+ teamd_log_info("WR-mode. State of the LAG member port '%s' was down before the restart. Nothing to read",
+ tdport->ifname);
+ }
+ }
+ }
+ }
+ }
+
+ if (lacp->ctx->warm_start_mode) {
+ int i;
+ bool has_all_ports_added = true;
+ for (i = 0; i < lacp->wr.nr_of_tdports; ++i)
+ has_all_ports_added = has_all_ports_added && lacp->wr.state[i].checked;
+
+ if (has_all_ports_added) {
+ teamd_log_info("WR-mode. The state for all %d LAG member ports was restored.",
+ lacp->wr.nr_of_tdports);
+ stop_wr_mode(lacp);
+ }
+ }
+
+ if (lacp->ctx->warm_start_mode) {
+ if (lacp->warm_start_mode_timer == 0) {
+ lacp->warm_start_mode_timer = time(NULL) + LACP_WARM_START_CARRIER_TIMEOUT;
+ } else if (time(NULL) >= lacp->warm_start_mode_timer) {
+ teamd_log_err("WR-mode. Timeout occured. Can't start in WR mode in %d seconds",
+ LACP_WARM_START_CARRIER_TIMEOUT);
+ stop_wr_mode(lacp);
+ }
+ }
+
+ if (ports_enabled >= lacp->cfg.min_ports) {
+ teamd_log_dbg("Enable carrier. Number of enabled ports %d >= configured min_ports %d",
+ ports_enabled, lacp->cfg.min_ports);
+ return lacp_set_carrier(lacp, true);
+ }
+
+ if (lacp->ctx->warm_start_mode) {
+ teamd_log_info("WR-mode. lacp_update_carrier(): Keep LAG interface up because of WR start mode");
+ return lacp_set_carrier(lacp, true);
}
+ if (lacp->ctx->warm_start_carrier)
+ return 0; /* Don't put carrier down if we're in warm_start_carrier mode */
+
return lacp_set_carrier(lacp, false);
}
@@ -919,6 +937,18 @@ static void lacp_port_actor_system_update(struct lacp_port *lacp_port)
@@ -919,6 +1205,18 @@ static void lacp_port_actor_system_update(struct lacp_port *lacp_port)
memcpy(actor->system, lacp_port->ctx->hwaddr, ETH_ALEN);
}
@ -286,7 +564,7 @@ index 4016b15..087efa9 100644
static void lacp_port_actor_init(struct lacp_port *lacp_port)
{
struct lacpdu_info *actor = &lacp_port->actor;
@@ -926,7 +956,7 @@ static void lacp_port_actor_init(struct lacp_port *lacp_port)
@@ -926,7 +1224,7 @@ static void lacp_port_actor_init(struct lacp_port *lacp_port)
actor->system_priority = htons(lacp_port->lacp->cfg.sys_prio);
actor->key = htons(lacp_port->cfg.lacp_key);
actor->port_priority = htons(lacp_port->cfg.lacp_prio);
@ -295,7 +573,7 @@ index 4016b15..087efa9 100644
lacp_port_actor_system_update(lacp_port);
}
@@ -1006,6 +1036,13 @@ static int lacp_port_set_state(struct lacp_port *lacp_port,
@@ -1006,6 +1304,13 @@ static int lacp_port_set_state(struct lacp_port *lacp_port,
break;
}
@ -309,7 +587,7 @@ index 4016b15..087efa9 100644
teamd_log_info("%s: Changed port state: \"%s\" -> \"%s\"",
lacp_port->tdport->ifname,
lacp_port_state_name[lacp_port->state],
@@ -1095,34 +1132,26 @@ static int lacpdu_send(struct lacp_port *lacp_port)
@@ -1095,34 +1400,23 @@ static int lacpdu_send(struct lacp_port *lacp_port)
return err;
}
@ -329,9 +607,9 @@ index 4016b15..087efa9 100644
- admin_state = team_get_ifinfo_admin_state(lacp_port->ctx->ifinfo);
- if (!admin_state)
- return 0;
if (!teamd_port_present(lacp_port->ctx, lacp_port->tdport))
return 0;
-
- if (!teamd_port_present(lacp_port->ctx, lacp_port->tdport))
- return 0;
- if (!lacpdu_check(&lacpdu)) {
+ if (!lacpdu_check(lacpdu)) {
@ -352,7 +630,7 @@ index 4016b15..087efa9 100644
err = lacp_port_partner_update(lacp_port);
if (err)
return err;
@@ -1138,7 +1167,7 @@ static int lacpdu_recv(struct lacp_port *lacp_port)
@@ -1138,21 +1432,56 @@ static int lacpdu_recv(struct lacp_port *lacp_port)
lacp_port_actor_update(lacp_port);
/* Check if the other side has correct info about us */
@ -361,7 +639,16 @@ index 4016b15..087efa9 100644
sizeof(struct lacpdu_info))) {
err = lacpdu_send(lacp_port);
if (err)
@@ -1153,6 +1182,70 @@ static int lacpdu_recv(struct lacp_port *lacp_port)
return err;
}
err = lacp_port_timeout_set(lacp_port, false);
- if (err) {
+ if (err)
return err;
- }
+
teamd_loop_callback_enable(lacp_port->ctx,
LACP_TIMEOUT_CB_NAME, lacp_port);
return 0;
}
@ -377,62 +664,42 @@ index 4016b15..087efa9 100644
+ if (err <= 0)
+ return err;
+
+ if (!teamd_port_present(lacp_port->ctx, lacp_port->tdport))
+ return 0;
+
+ admin_state = team_get_ifinfo_admin_state(lacp_port->ctx->ifinfo);
+ if (!admin_state)
+ return 0;
+
+ return lacpdu_process(lacp_port, &lacpdu);
+}
+ /* if the lacpdu wasn't read yet, don't process received pdu */
+ if (lacp_port->ctx->warm_start_mode) {
+ int found;
+
+static int lacpdu_read(struct lacp_port *lacp_port)
+{
+ FILE* fp;
+ char filename[PATH_MAX];
+ struct lacpdu lacpdu;
+ int err, nitems;
+ struct teamd_port *tdport;
+
+ /* we read saved lacpdu for the current lacp_port */
+ lacp_port->lacpdu_read = true;
+
+ strcpy(filename, lacp_port->ctx->lacp_directory);
+ if (filename[strlen(filename) - 1] != '/')
+ strcat(filename, "/"); /* Add trailing slash if we don't have one in the filename */
+ strcat(filename, lacp_port->tdport->ifname);
+
+ /* check that file is readable. if there is no file, don't do anything */
+ if (access(filename, R_OK) != 0) {
+ return 0;
+ found = find_wr_info(lacp_port);
+ if (found >= 0 && !lacp_port->lacp->wr.state[found].checked) {
+ teamd_log_info("WR-mode. Received LACP PDU on %s. "
+ "But saved LACP PDU wasn't processed yet.",
+ lacp_port->tdport->ifname);
+ return 0;
+ }
+ }
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ teamd_log_err("Can't open lacp-saved dump from file %s: %s", filename, strerror(errno));
+ return errno;
+ }
+
+ nitems = fread(&lacpdu, sizeof(struct lacpdu), 1, fp);
+ (void)fclose(fp);
+
+ err = unlink(filename);
+ if (err < 0) {
+ teamd_log_err("Can't remove file %s: %s", filename, strerror(errno));
+ }
+
+ if (nitems != 1) {
+ teamd_log_err("Can't read lacp-saved dump from file %s: %s", filename, strerror(errno));
+ return err;
+ }
+
+ teamd_log_info("%s: LACP state was read", lacp_port->tdport->ifname);
+
+ return lacpdu_process(lacp_port, &lacpdu);
+}
+
static int lacp_callback_timeout(struct teamd_context *ctx, int events,
void *priv)
{
@@ -1304,6 +1397,13 @@ static int lacp_port_added(struct teamd_context *ctx,
@@ -1258,6 +1587,8 @@ static int lacp_port_added(struct teamd_context *ctx,
struct lacp *lacp = creator_priv;
int err;
+ teamd_log_dbg("function lacp_port_added(): %s", tdport->ifname);
+
lacp_port->ctx = ctx;
lacp_port->tdport = tdport;
lacp_port->lacp = lacp;
@@ -1304,6 +1635,13 @@ static int lacp_port_added(struct teamd_context *ctx,
goto periodic_callback_del;
}
@ -446,25 +713,13 @@ index 4016b15..087efa9 100644
/* Newly added ports are disabled */
err = team_set_port_enabled(ctx->th, tdport->ifindex, false);
if (err) {
@@ -1319,6 +1419,13 @@ static int lacp_port_added(struct teamd_context *ctx,
lacp_port_actor_init(lacp_port);
lacp_port_link_update(lacp_port);
+ /* Read data from file and process it */
+ if (ctx->warm_start_read) {
+ err = lacpdu_read(lacp_port);
+ if (err)
+ goto timeout_callback_del;
+ }
+
teamd_loop_callback_enable(ctx, LACP_SOCKET_CB_NAME, lacp_port);
return 0;
@@ -1341,7 +1448,11 @@ static void lacp_port_removed(struct teamd_context *ctx,
@@ -1341,7 +1679,13 @@ static void lacp_port_removed(struct teamd_context *ctx,
{
struct lacp_port *lacp_port = priv;
- lacp_port_set_state(lacp_port, PORT_STATE_DISABLED);
+ teamd_log_dbg("function lacp_port_removed(): %s", tdport->ifname);
+
+ if (!lacp_port->ctx->keep_ports) {
+ /* Don't transition into DISABLED state,
+ which sends EXPIRED LACP PDU update */
@ -473,7 +728,19 @@ index 4016b15..087efa9 100644
teamd_loop_callback_del(ctx, LACP_TIMEOUT_CB_NAME, lacp_port);
teamd_loop_callback_del(ctx, LACP_PERIODIC_CB_NAME, lacp_port);
teamd_loop_callback_del(ctx, LACP_SOCKET_CB_NAME, lacp_port);
@@ -1459,6 +1570,31 @@ static void lacp_event_watch_refresh(struct teamd_context *ctx,
@@ -1449,16 +1793,51 @@ static int lacp_event_watch_port_changed(struct teamd_context *ctx,
return lacp_port_link_update(lacp_port);
}
-static void lacp_event_watch_refresh(struct teamd_context *ctx,
- struct teamd_port *tdport, void *priv)
+static void lacp_event_watch_refresh(struct teamd_context *ctx, struct teamd_port *tdport, void *priv)
{
struct lacp *lacp = priv;
- struct lacp_port *lacp_port = lacp_port_get(lacp, tdport);
+ struct lacp_port *lacp_port = lacp_port_get(lacp, tdport);
if (lacp_port_selected(lacp_port))
(void) lacpdu_send(lacp_port);
}
@ -481,31 +748,42 @@ index 4016b15..087efa9 100644
+{
+ struct lacp *lacp = priv;
+
+ /* save dump information for each tdport */
+ lacp->wr.nr_of_tdports++;
+ lacp->wr.state = realloc(lacp->wr.state, sizeof(struct wr_tdport_state) * lacp->wr.nr_of_tdports);
+ if (lacp->wr.state) {
+ int err;
+ strcpy(lacp->wr.state[lacp->wr.nr_of_tdports-1].name, tdport->ifname);
+ err = teamd_port_enabled(ctx, tdport, &lacp->wr.state[lacp->wr.nr_of_tdports-1].enabled);
+ if (err)
+ lacp->wr.state[lacp->wr.nr_of_tdports-1].enabled = false;
+ } else {
+ teamd_log_err("WR-mode. Can't reallocate memory for LACP member %s dump", tdport->ifname);
+ lacp->wr.nr_of_tdports = 0;
+ }
+
+ struct lacp_port *lacp_port = lacp_port_get(lacp, tdport);
+ if (lacp_port->lacpdu_saved && lacp_port->ctx->lacp_directory) {
+ char filename[PATH_MAX];
+ strcpy(filename, lacp_port->ctx->lacp_directory);
+ if (filename[strlen(filename) - 1] != '/')
+ strcat(filename, "/"); /* Add trailing slash if we don't have one in the filename */
+ strcat(filename, lacp_port->tdport->ifname);
+ generate_path(lacp_port->ctx, filename, lacp_port->tdport->ifname);
+ FILE *fp = fopen(filename, "wb");
+ if (fp != NULL) {
+ (void)fwrite(&lacp_port->last_pdu, sizeof(struct lacpdu), 1, fp);
+ (void)fclose(fp);
+ } else {
+ teamd_log_err("Can't open file %s for writing %s", filename, strerror(errno));
+ teamd_log_err("WR-mode. Can't open file %s for writing %s", filename, strerror(errno));
+ }
+ } else {
+ teamd_log_err("Can't dump received lacp pdu for port %s. "
+ "Either it wasn't received, or directory to save wasn't configured",
+ lacp_port->tdport->ifname);
+ if (lacp_port->ctx->lacp_directory == NULL)
+ teamd_log_err("WR-mode. Can't dump received lacp pdu for port %s. "
+ "LACP directory wasn't configured", lacp_port->tdport->ifname);
+ }
+}
+
static const struct teamd_event_watch_ops lacp_event_watch_ops = {
.hwaddr_changed = lacp_event_watch_hwaddr_changed,
.port_hwaddr_changed = lacp_event_watch_port_hwaddr_changed,
@@ -1467,21 +1603,38 @@ static const struct teamd_event_watch_ops lacp_event_watch_ops = {
@@ -1467,21 +1846,35 @@ static const struct teamd_event_watch_ops lacp_event_watch_ops = {
.port_changed = lacp_event_watch_port_changed,
.admin_state_changed = lacp_event_watch_admin_state_changed,
.refresh = lacp_event_watch_refresh,
@ -518,32 +796,27 @@ index 4016b15..087efa9 100644
- /* initialize carrier control */
- err = team_carrier_set(ctx->th, false);
- if (err && err != -EOPNOTSUPP) {
- teamd_log_err("Failed to set carrier down.");
- return err;
+ if (ctx->warm_start_carrier) {
+ /* Read the current carrier state, don't change it */
+ bool state;
+ err = team_carrier_get(ctx->th, &state);
+ if (err && err != -EOPNOTSUPP) {
+ teamd_log_err("Failed to read carrier.");
+ return err;
+ }
+ lacp->carrier_up = state;
+ if (state) {
+ /* enable timer for warm_start_carrier mode */
+ lacp->warm_start_carrier_timer = time(NULL);
+ lacp->carrier_up = false;
+
+ if (ctx->warm_start_mode) {
+ teamd_log_dbg("WR-mode. function lacp_carrier_init()");
+
+ /* Disable WR start mode if LAG interface was down */
+ if (lacp->wr.carrier_up) {
+ teamd_log_info("WR-mode. Starting in WR mode");
+ } else {
+ /* disable warm_start_carrier mode. The LAG interface is already down. */
+ ctx->warm_start_carrier = false;
+ teamd_log_info("WR-mode. Starting in normal mode. The LAG interface was down before restart");
+ }
+ } else {
+ err = team_carrier_set(ctx->th, false);
+ if (err && err != -EOPNOTSUPP) {
+ teamd_log_err("Failed to set carrier down.");
+ return err;
+ }
+ lacp->carrier_up = false;
+ ctx->warm_start_mode = lacp->wr.carrier_up;
+ lacp->carrier_up = lacp->wr.carrier_up;
+ lacp->warm_start_mode_timer = 0;
+ }
+
+ err = team_carrier_set(ctx->th, lacp->carrier_up);
if (err && err != -EOPNOTSUPP) {
- teamd_log_err("Failed to set carrier down.");
+ teamd_log_err("Failed to set carrier");
return err;
}
- lacp->carrier_up = false;
@ -551,15 +824,34 @@ index 4016b15..087efa9 100644
return 0;
}
@@ -1993,7 +2146,7 @@ static void lacp_fini(struct teamd_context *ctx, void *priv)
@@ -1949,6 +2342,12 @@ static int lacp_init(struct teamd_context *ctx, void *priv)
}
lacp->ctx = ctx;
+ if (ctx->warm_start_mode) {
+ err = lacp_state_load(ctx, lacp);
+ if (err)
+ stop_wr_mode(lacp);
+ }
+
err = teamd_hash_func_set(ctx);
if (err)
return err;
@@ -1990,10 +2389,13 @@ static void lacp_fini(struct teamd_context *ctx, void *priv)
{
struct lacp *lacp = priv;
+ if (ctx->lacp_directory)
+ lacp_state_save(ctx, lacp);
teamd_state_val_unregister(ctx, &lacp_state_vg, lacp);
teamd_balancer_fini(lacp->tb);
teamd_event_watch_unregister(ctx, &lacp_event_watch_ops, lacp);
- lacp_carrier_fini(ctx, lacp);
+ if (!ctx->keep_ports) lacp_carrier_fini(ctx, lacp);
+ if (!ctx->keep_ports)
+ lacp_carrier_fini(ctx, lacp);
}
const struct teamd_runner teamd_runner_lacp = {
--
2.7.4
2.17.1.windows.2

View File

@ -6,9 +6,9 @@ minigraph file, config DB, json file(s), yaml files(s), command line input,
and write the data into DB, print as json, or render a jinja2 config template.
Examples:
Render template with minigraph:
Render template with minigraph:
sonic-cfggen -m -t /usr/share/template/bgpd.conf.j2
Dump config DB content into json file:
Dump config DB content into json file:
sonic-cfggen -d --print-data > db_dump.json
Load content of json file into config DB:
sonic-cfggen -j db_dump.json --write-to-db
@ -93,6 +93,10 @@ def pfx_filter(value):
For eg - VLAN_INTERFACE|Vlan1000 vs VLAN_INTERFACE|Vlan1000|192.168.0.1/21
"""
table = OrderedDict()
if not value:
return table
for key,val in value.items():
if not isinstance(key, tuple):
continue
@ -104,7 +108,7 @@ class FormatConverter:
We will move to DB schema and remove this class when the config templates are modified.
TODO(taoyl): Current version of config db only supports BGP admin states.
All other configuration are still loaded from minigraph. Plan to remove
All other configuration are still loaded from minigraph. Plan to remove
minigraph and move everything into config db in a later commit.
"""
@staticmethod
@ -214,7 +218,7 @@ def main():
for yaml_file in args.yaml:
with open(yaml_file, 'r') as stream:
additional_data = yaml.load(stream)
additional_data = yaml.load(stream)
deep_update(data, FormatConverter.to_deserialized(additional_data))
for json_file in args.json:
@ -223,7 +227,7 @@ def main():
if args.additional_data != None:
deep_update(data, json.loads(args.additional_data))
if args.from_db:
configdb = ConfigDBConnector(**db_kwargs)
configdb.connect()

@ -1 +1 @@
Subproject commit dcab09f2881a0b45a2c03c091e641ff66dfada8c
Subproject commit d5c89cd92d93cd0ec338c629046f67cf22a54e38

@ -1 +1 @@
Subproject commit d6167643c0ce4778ce1ec5be2530f48ef94ccc29
Subproject commit 7a1a97c8b4d9ada359b201f55fad0aa49771d3e6

@ -1 +1 @@
Subproject commit 485db073a17d2ac0cd9d6f29b0b8d7c245c66663
Subproject commit bd7d5941b6c026f7eb839f409331c2ba91ecf5f2