Skip to content

Commit e049790

Browse files
Tamer Ahmedyxieca
Tamer Ahmed
authored andcommitted
Merged PR 3845699: [linkmgrd]: Introduce MUX cable linkmgrd
Linkmgrd monitors link status, mux status, and link state. Has the link becomes unhealthy, linkmgrd will trigger mux switchover on a standby ToR ensuring uninterrupted service to servers/blades. This PR is initial implementation of linkmgrd. Also, docker-mux container hold packages related to maintaining and managing mux cable. It currently runs linkmgrd binary that monitor and switches the mux if needed. This PR also introduces mux-container and starts linkmgrd as startup when build is configured with INCLUDE_MUX=y Edit: linkmgrd PR will follow. signed-off-by: Tamer Ahmed <[email protected]> Related work items: sonic-net#2315, #3146150
1 parent 9a1b1bc commit e049790

13 files changed

+189
-1
lines changed

Makefile.work

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
# * ENABLE_ZTP: Enables zero touch provisioning.
1111
# * SHUTDOWN_BGP_ON_START: Sets admin-down state for all bgp peerings after restart.
1212
# * INCLUDE_KUBERNETES: Allows including Kubernetes
13+
# * INCLUDE_MUX: Include MUX feature/services for TOR switch.
1314
# * ENABLE_PFCWD_ON_START: Enable PFC Watchdog (PFCWD) on server-facing ports
1415
# * by default for TOR switch.
1516
# * ENABLE_SYNCD_RPC: Enables rpc-based syncd builds.
@@ -267,6 +268,7 @@ SONIC_BUILD_INSTRUCTION := make \
267268
HTTPS_PROXY=$(https_proxy) \
268269
SONIC_INCLUDE_SYSTEM_TELEMETRY=$(INCLUDE_SYSTEM_TELEMETRY) \
269270
SONIC_INCLUDE_RESTAPI=$(INCLUDE_RESTAPI) \
271+
SONIC_INCLUDE_MUX=$(INCLUDE_MUX) \
270272
TELEMETRY_WRITABLE=$(TELEMETRY_WRITABLE) \
271273
EXTRA_DOCKER_TARGETS=$(EXTRA_DOCKER_TARGETS) \
272274
BUILD_LOG_TIMESTAMP=$(BUILD_LOG_TIMESTAMP) \

dockers/docker-mux/Dockerfile.j2

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{% from "dockers/dockerfile-macros.j2" import install_debian_packages, install_python_wheels, copy_files %}
2+
FROM docker-config-engine-buster
3+
4+
ARG docker_container_name
5+
RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf
6+
7+
## Make apt-get non-interactive
8+
ENV DEBIAN_FRONTEND=noninteractive
9+
10+
RUN apt-get update && \
11+
apt-get install -f -y \
12+
libmnl0
13+
14+
{% if docker_mux_debs.strip() -%}
15+
# Copy locally-built Debian package dependencies
16+
{{ copy_files("debs/", docker_mux_debs.split(' '), "/debs/") }}
17+
18+
# Install locally-built Debian packages and implicitly install their dependencies
19+
{{ install_debian_packages(docker_mux_debs.split(' ')) }}
20+
{%- endif %}
21+
22+
## Clean up
23+
RUN apt-get clean -y && \
24+
apt-get autoclean -y && \
25+
apt-get autoremove -y && \
26+
rm -rf /debs
27+
28+
COPY ["docker-init.sh", "/usr/bin/"]
29+
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
30+
COPY ["files/supervisor-proc-exit-listener", "/usr/bin"]
31+
COPY ["critical_processes", "/etc/supervisor/"]
32+
33+
## Copy all Jinja2 template files into the templates folder
34+
COPY ["*.j2", "/usr/share/sonic/templates/"]
35+
36+
ENTRYPOINT ["/usr/bin/docker-init.sh"]

dockers/docker-mux/critical_processes

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
program:linkmgrd

dockers/docker-mux/docker-init.sh

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env bash
2+
3+
# Generate supervisord config file
4+
mkdir -p /etc/supervisor/conf.d/
5+
6+
# The docker container should start this script as PID 1, so now that supervisord is
7+
# properly configured, we exec supervisord so that it runs as PID 1 for the
8+
# duration of the container's lifetime
9+
exec /usr/local/bin/supervisord

dockers/docker-mux/supervisord.conf

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[supervisord]
2+
logfile_maxbytes=1MB
3+
logfile_backups=2
4+
nodaemon=true
5+
6+
[eventlistener:dependent-startup]
7+
command=python3 -m supervisord_dependent_startup
8+
autostart=true
9+
autorestart=unexpected
10+
startretries=0
11+
exitcodes=0,3
12+
events=PROCESS_STATE
13+
buffer_size=100
14+
15+
[eventlistener:supervisor-proc-exit-listener]
16+
command=/usr/bin/supervisor-proc-exit-listener --container-name mux
17+
events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING
18+
autostart=true
19+
autorestart=unexpected
20+
21+
[program:rsyslogd]
22+
command=/usr/sbin/rsyslogd -n -iNONE
23+
priority=1
24+
autostart=false
25+
autorestart=unexpected
26+
stdout_logfile=syslog
27+
stderr_logfile=syslog
28+
dependent_startup=true
29+
30+
[program:linkmgrd]
31+
command=nice -n -20 /usr/sbin/linkmgrd -v warning
32+
priority=2
33+
autostart=false
34+
autorestart=false
35+
startsecs=0
36+
startretries=0
37+
stdout_logfile=syslog
38+
stderr_logfile=syslog
39+
dependent_startup=true
40+
dependent_startup_wait_for=rsyslogd:running
41+

files/build_templates/init_cfg.json.j2

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
{%- if sonic_asic_platform == "vs" %}{% do features.append(("gbsyncd", "enabled", false, "enabled")) %}{% endif %}
3232
{%- if include_iccpd == "y" %}{% do features.append(("iccpd", "disabled", false, "enabled")) %}{% endif %}
3333
{%- if include_mgmt_framework == "y" %}{% do features.append(("mgmt-framework", "enabled", true, "enabled")) %}{% endif %}
34+
{%- if include_mux == "y" %}{% do features.append(("mux", "enabled", false, "enabled")) %}{% endif %}
3435
{%- if include_nat == "y" %}{% do features.append(("nat", "disabled", false, "enabled")) %}{% endif %}
3536
{%- if include_restapi == "y" %}{% do features.append(("restapi", "enabled", false, "enabled")) %}{% endif %}
3637
{%- if include_sflow == "y" %}{% do features.append(("sflow", "disabled", false, "enabled")) %}{% endif %}

files/build_templates/mux.service.j2

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[Unit]
2+
Description=MUX Cable Container
3+
Requires=database.service updategraph.service pmon.service swss.service
4+
After=pmon.service swss.service
5+
StartLimitIntervalSec=1200
6+
StartLimitBurst=3
7+
8+
[Service]
9+
User={{ sonicadmin_user }}
10+
ExecStartPre=/usr/bin/{{docker_container_name}}.sh start
11+
ExecStart=/usr/bin/{{docker_container_name}}.sh wait
12+
ExecStop=/usr/bin/{{docker_container_name}}.sh stop
13+
Restart=always
14+
RestartSec=30
15+
16+
[Install]
17+
WantedBy=multi-user.target

rules/config

+3
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,6 @@ SONIC_VERSION_CONTROL_COMPONENTS ?= none
191191
# Set the env variable ENABLE_DOCKER_BASE_PULL = y to enable pulling sonic-slave docker from registry
192192
REGISTRY_PORT ?= 443
193193
REGISTRY_SERVER ?= sonicdev-microsoft.azurecr.io
194+
195+
# INCLUDE_MUX - build docker-mux for dual ToR (Gemini)
196+
INCLUDE_MUX = y

rules/docker-mux.dep

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
DPATH := $($(DOCKER_MUX)_PATH)
3+
DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-mux.mk rules/docker-mux.dep
4+
DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
5+
DEP_FILES += $(shell git ls-files $(DPATH))
6+
7+
$(DOCKER_MUX)_CACHE_MODE := GIT_CONTENT_SHA
8+
$(DOCKER_MUX)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
9+
$(DOCKER_MUX)_DEP_FILES := $(DEP_FILES)
10+
11+
$(eval $(call add_dbg_docker,$(DOCKER_MUX),$(DOCKER_MUX_DBG)))
12+

rules/docker-mux.mk

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Docker image for MUX
2+
3+
DOCKER_MUX_STEM = docker-mux
4+
DOCKER_MUX = $(DOCKER_MUX_STEM).gz
5+
DOCKER_MUX_DBG = $(DOCKER_MUX_STEM)-$(DBG_IMAGE_MARK).gz
6+
7+
$(DOCKER_MUX)_PATH = $(DOCKERS_PATH)/$(DOCKER_MUX_STEM)
8+
9+
$(DOCKER_MUX)_DEPENDS = $(SONIC_LINKMGRD) $(LIBSWSSCOMMON) $(LIBHIREDIS)
10+
$(DOCKER_MUX)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_DEPENDS)
11+
$(DOCKER_MUX)_DBG_DEPENDS += $(SONIC_LINKMGRD_DBG) $(LIBSWSSCOMMON_DBG) $(LIBHIREDIS_DBG)
12+
13+
$(DOCKER_MUX)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BUSTER)_DBG_IMAGE_PACKAGES)
14+
15+
$(DOCKER_MUX)_LOAD_DOCKERS = $(DOCKER_CONFIG_ENGINE_BUSTER)
16+
17+
ifeq ($(INCLUDE_MUX), y)
18+
SONIC_DOCKER_IMAGES += $(DOCKER_MUX)
19+
SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_MUX)
20+
endif
21+
22+
ifeq ($(INCLUDE_MUX), y)
23+
SONIC_DOCKER_DBG_IMAGES += $(DOCKER_MUX_DBG)
24+
SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_MUX_DBG)
25+
endif
26+
27+
$(DOCKER_MUX)_CONTAINER_NAME = mux
28+
$(DOCKER_MUX)_RUN_OPT += --privileged -t
29+
$(DOCKER_MUX)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro
30+
$(DOCKER_ORCHAGENT)_RUN_OPT += -v /var/log/mux:/var/log/mux:rw
31+
$(DOCKER_MUX)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT)
32+

rules/linkmgrd.dep

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
SPATH := $($(SONIC_LINKMGRD)_SRC_PATH)
3+
DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/linkmgrd.mk rules/linkmgrd.dep
4+
DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
5+
SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files))
6+
7+
$(SONIC_LINKMGRD)_CACHE_MODE := GIT_CONTENT_SHA
8+
$(SONIC_LINKMGRD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
9+
$(SONIC_LINKMGRD)_DEP_FILES := $(DEP_FILES)
10+
$(SONIC_LINKMGRD)_SMDEP_FILES := $(SMDEP_FILES)
11+
$(SONIC_LINKMGRD)_SMDEP_PATHS := $(SPATH)

rules/linkmgrd.mk

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# SONiC LINK ManaGeR Daemon package
2+
3+
SONIC_LINKMGRD_VERSION = 1.0.0-1
4+
SONIC_LINKMGRD_PKG_NAME = linkmgrd
5+
6+
export SONIC_LINKMGRD_VERSION SONIC_LINKMGRD_PKG_NAME
7+
8+
SONIC_LINKMGRD = sonic-$(SONIC_LINKMGRD_PKG_NAME)_$(SONIC_LINKMGRD_VERSION)_$(CONFIGURED_ARCH).deb
9+
$(SONIC_LINKMGRD)_SRC_PATH = $(SRC_PATH)/$(SONIC_LINKMGRD_PKG_NAME)
10+
$(SONIC_LINKMGRD)_DEPENDS = $(LIBSWSSCOMMON_DEV) $(LIBSWSSCOMMON) $(LIBHIREDIS_DEV) $(LIBHIREDIS)
11+
12+
SONIC_DPKG_DEBS += $(SONIC_LINKMGRD)
13+
14+
SONIC_LINKMGRD_DBG = sonic-$(SONIC_LINKMGRD_PKG_NAME)-dbgsym_$(SONIC_LINKMGRD_VERSION)_$(CONFIGURED_ARCH).deb
15+
$(SONIC_LINKMGRD)_DBG_DEPENDS = $(LIBSWSSCOMMON_DEV) $(LIBSWSSCOMMON_DBG) $(LIBHIREDIS_DEV) $(LIBHIREDIS_DBG)
16+
$(eval $(call add_derived_package,$(SONIC_LINKMGRD),$(SONIC_LINKMGRD_DBG)))
17+
18+
export SONIC_LINKMGRD SONIC_LINKMGRD_DBG

slave.mk

+6-1
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ INCLUDE_NAT = y
153153
endif
154154

155155

156+
ifeq ($(SONIC_INCLUDE_MUX),y)
157+
INCLUDE_MUX = y
158+
endif
159+
156160
include $(RULES_PATH)/functions
157161

158162
ifeq ($(SONIC_USE_PDDF_FRAMEWORK),y)
@@ -266,6 +270,7 @@ $(info "INCLUDE_RESTAPI" : "$(INCLUDE_RESTAPI)")
266270
$(info "INCLUDE_SFLOW" : "$(INCLUDE_SFLOW)")
267271
$(info "INCLUDE_NAT" : "$(INCLUDE_NAT)")
268272
$(info "INCLUDE_KUBERNETES" : "$(INCLUDE_KUBERNETES)")
273+
$(info "INCLUDE_MUX" : "$(INCLUDE_MUX)")
269274
$(info "TELEMETRY_WRITABLE" : "$(TELEMETRY_WRITABLE)")
270275
$(info "PDDF_SUPPORT" : "$(PDDF_SUPPORT)")
271276
$(info "MULTIARCH_QEMU_ENVIRON" : "$(MULTIARCH_QEMU_ENVIRON)")
@@ -944,7 +949,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
944949
export python_swss_debs+=" $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(LIBSWSSCOMMON)) $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(PYTHON_SWSSCOMMON)) $(addprefix $(IMAGE_DISTRO_DEBS_PATH)/,$(PYTHON3_SWSSCOMMON))"
945950
export sonic_utilities_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_UTILITIES_PY3))"
946951
export sonic_host_services_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_HOST_SERVICES_PY3))"
947-
952+
export include_mux="$(INCLUDE_MUX)"
948953
$(foreach docker, $($*_DOCKERS),\
949954
export docker_image="$(docker)"
950955
export docker_image_name="$(basename $(docker))"

0 commit comments

Comments
 (0)