diff --git a/.gitmodules b/.gitmodules index e34e63f0261..3d805486d01 100644 --- a/.gitmodules +++ b/.gitmodules @@ -163,3 +163,6 @@ [submodule "src/supervisor"] path = src/supervisor url = https://github.com/Supervisor/supervisor +[submodule "src/sonic-l2mcd"] + path = src/sonic-l2mcd + url = https://github.com/sonic-net/sonic-l2mcd diff --git a/dockers/docker-l2mcd/Dockerfile.j2 b/dockers/docker-l2mcd/Dockerfile.j2 new file mode 100644 index 00000000000..a734a07bb1a --- /dev/null +++ b/dockers/docker-l2mcd/Dockerfile.j2 @@ -0,0 +1,45 @@ +{% from "dockers/dockerfile-macros.j2" import install_debian_packages, copy_files %} + +ARG BASE=docker-config-engine-bookworm-{{DOCKER_USERNAME}}:{{DOCKER_USERTAG}} + +FROM $BASE AS base + +ARG docker_container_name +ARG image_version + +ENV DEBIAN_FRONTEND=noninteractive +ENV IMAGE_VERSION=$image_version + +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +RUN apt-get update && apt-get install -f -y \ + libdbus-1-3 \ + libdaemon0 \ + libjansson4 \ + libpython3.11 \ + libjemalloc2 \ + libevent-dev + +{% if docker_l2mcd_debs.strip() -%} + +{{ copy_files("debs/", docker_l2mcd_debs.split(' '), "/debs/") }} + +{{ install_debian_packages(docker_l2mcd_debs.split(' ')) }} +{%- endif %} + +RUN apt-get clean -y && \ + apt-get autoclean -y && \ + apt-get autoremove -y && \ + rm -rf /debs + +COPY ["start.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["critical_processes", "/etc/supervisor/"] +RUN chmod +x /usr/bin/start.sh + +FROM $BASE + +RUN --mount=type=bind,from=base,target=/changes-to-image rsync -axAX --no-D --exclude=/sys --exclude=/proc --exclude=/dev --exclude=resolv.conf /changes-to-image/ / + + +ENTRYPOINT ["/usr/local/bin/supervisord"] diff --git a/dockers/docker-l2mcd/critical_processes b/dockers/docker-l2mcd/critical_processes new file mode 100644 index 00000000000..7bfd0ee0d5b --- /dev/null +++ b/dockers/docker-l2mcd/critical_processes @@ -0,0 +1,2 @@ +program:l2mcd +program:l2mcmgrd \ No newline at end of file diff --git a/dockers/docker-l2mcd/start.sh b/dockers/docker-l2mcd/start.sh new file mode 100644 index 00000000000..9255d2b8777 --- /dev/null +++ b/dockers/docker-l2mcd/start.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid +rm -f /var/run/l2mcd/* +rm -f /var/run/l2mcmgrd/* diff --git a/dockers/docker-l2mcd/supervisord.conf b/dockers/docker-l2mcd/supervisord.conf new file mode 100644 index 00000000000..452b786e468 --- /dev/null +++ b/dockers/docker-l2mcd/supervisord.conf @@ -0,0 +1,66 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[eventlistener:dependent-startup] +command=python3 -m supervisord_dependent_startup +autostart=true +autorestart=unexpected +startretries=0 +exitcodes=0,3 +events=PROCESS_STATE +buffer_size=1024 + +[eventlistener:supervisor-proc-exit-listener] +command=/usr/local/bin/supervisor-proc-exit-listener --container-name l2mcd +events=PROCESS_STATE_EXITED,PROCESS_STATE_RUNNING +autostart=true +autorestart=unexpected +buffer_size=1024 + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n -iNONE +priority=2 +autostart=false +autorestart=false +stdout_logfile=NONE +stdout_syslog=true +stderr_logfile=NONE +stderr_syslog=true +dependent_startup=true + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +stdout_logfile=NONE +stdout_syslog=true +stderr_logfile=NONE +stderr_syslog=true +dependent_startup=true + +[program:l2mcd] +command=/usr/bin/l2mcd -n 1 +priority=3 +autostart=false +autorestart=false +stdout_logfile=NONE +stdout_syslog=true +stderr_logfile=NONE +stderr_syslog=true +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running + +[program:l2mcmgrd] +command=/usr/bin/l2mcmgrd +priority=3 +autostart=false +autorestart=false +stdout_logfile=NONE +stdout_syslog=true +stderr_logfile=NONE +stderr_syslog=true +dependent_startup=true +dependent_startup_wait_for=rsyslogd:running diff --git a/dockers/docker-sonic-gnmi/telemetry_vars.j2 b/dockers/docker-sonic-gnmi/telemetry_vars.j2 index 4546ae5ab74..aeafb823018 100644 --- a/dockers/docker-sonic-gnmi/telemetry_vars.j2 +++ b/dockers/docker-sonic-gnmi/telemetry_vars.j2 @@ -1,5 +1,5 @@ { - "certs": {% if "certs" in GNMI.keys() %}{{ GNMI["certs"] }}{% else %}""{% endif %}, - "gnmi" : {% if "gnmi" in GNMI.keys() %}{{ GNMI["gnmi"] }}{% else %}""{% endif %}, - "x509" : {% if "x509" in DEVICE_METADATA.keys() %}{{ DEVICE_METADATA["x509"] }}{% else %}""{% endif %} + "certs": {% if GNMI is defined and "certs" in GNMI.keys() %}{{ GNMI["certs"] }}{% else %}""{% endif %}, + "gnmi" : {% if GNMI is defined and "gnmi" in GNMI.keys() %}{{ GNMI["gnmi"] }}{% else %}""{% endif %}, + "x509" : {% if DEVICE_METADATA is defined and "x509" in DEVICE_METADATA.keys() %}{{ DEVICE_METADATA["x509"] }}{% else %}""{% endif %} } diff --git a/files/build_templates/init_cfg.json.j2 b/files/build_templates/init_cfg.json.j2 index 1d1c1817b49..6ff4b9a5aab 100644 --- a/files/build_templates/init_cfg.json.j2 +++ b/files/build_templates/init_cfg.json.j2 @@ -21,6 +21,12 @@ {% endfor %} } }, + "MGMT_PORT": { + "eth0": { + "alias": "eth0", + "admin_status": "up" + } + }, "FLEX_COUNTER_TABLE": { "ACL": { "FLEX_COUNTER_STATUS": "enable", @@ -74,6 +80,7 @@ {%- if include_dhcp_server == "y" %}{% do features.append(("dhcp_server", "disabled", false, "enabled")) %}{% endif %} {%- if sonic_asic_platform == "vs" %}{% do features.append(("gbsyncd", "enabled", false, "enabled")) %}{% endif %} {%- if include_iccpd == "y" %}{% do features.append(("iccpd", "disabled", false, "enabled")) %}{% endif %} +{%- if include_l2mcd == "y" %}{% do features.append(("l2mcd", "disabled", false, "enabled")) %}{% endif %} {%- if include_mgmt_framework == "y" %}{% do features.append(("mgmt-framework", "enabled", true, "enabled")) %}{% endif %} {%- if include_mux == "y" %}{% do features.append(("mux", "{% if 'subtype' in DEVICE_METADATA['localhost'] and DEVICE_METADATA['localhost']['subtype'] == 'DualToR' %}enabled{% else %}always_disabled{% endif %}", false, "enabled")) %}{% endif %} {%- if include_nat == "y" %}{% do features.append(("nat", "disabled", false, "enabled")) %}{% endif %} diff --git a/files/build_templates/per_namespace/l2mcd.service.j2 b/files/build_templates/per_namespace/l2mcd.service.j2 new file mode 100644 index 00000000000..29bb0d0a45c --- /dev/null +++ b/files/build_templates/per_namespace/l2mcd.service.j2 @@ -0,0 +1,21 @@ +[Unit] +Description=L2MCD container +Requires=swss{% if multi_instance == 'true' %}@%i{% endif %}.service +After=swss{% if multi_instance == 'true' %}@%i{% endif %}.service +After=syncd{% if multi_instance == 'true' %}@%i{% endif %}.service +Requires=config-setup.service +After=config-setup.service +BindsTo=sonic.target +After=sonic.target +Before=ntp-config.service +BindsTo=sonic.target +After=sonic.target + +[Service] +User={{ sonicadmin_user }} +ExecStartPre=/usr/bin/{{docker_container_name}}.sh start{% if multi_instance == 'true' %} %i{% endif %} +ExecStart=/usr/bin/{{docker_container_name}}.sh wait{% if multi_instance == 'true' %} %i{% endif %} +ExecStop=/usr/bin/{{docker_container_name}}.sh stop{% if multi_instance == 'true' %} %i{% endif %} + +[Install] +WantedBy=sonic.target diff --git a/files/image_config/copp/copp_cfg.j2 b/files/image_config/copp/copp_cfg.j2 index fc2002cffd3..6e4fb4cc85d 100755 --- a/files/image_config/copp/copp_cfg.j2 +++ b/files/image_config/copp/copp_cfg.j2 @@ -85,7 +85,18 @@ "trap_action": "trap", "trap_priority": "1" - } + }, + "l2mcd_group": { + "cir":"600", + "cbs":"600", + "meter_type":"packets", + "mode":"sr_tcm", + "red_action":"drop", + "trap_action":"trap", + "trap_priority":"3", + "queue": "3", + "yellow_action":"drop" + } }, "COPP_TRAP": { "bgp": { @@ -136,6 +147,10 @@ "trap_ids": "neighbor_miss", "trap_group": "queue1_group3", "always_enabled": "true" + }, + "l2mcd": { + "trap_ids": "igmp_v1_report,igmp_query,igmp_leave,igmp_v2_report,igmp_v3_report,mld_v1_v2,mld_v1_report,mld_v1_done,mld_v2_report", + "trap_group": "l2mcd_group" } } } diff --git a/files/image_config/logrotate/rsyslog.j2 b/files/image_config/logrotate/rsyslog.j2 index 2d949ac0df6..b26a037faaf 100644 --- a/files/image_config/logrotate/rsyslog.j2 +++ b/files/image_config/logrotate/rsyslog.j2 @@ -29,6 +29,7 @@ /var/log/auth.log /var/log/cron.log /var/log/teamd.log +/var/log/l2mcd.log /var/log/telemetry.log /var/log/stpd.log /var/log/gnmi.log diff --git a/files/image_config/rsyslog/rsyslog.d/00-sonic.conf.j2 b/files/image_config/rsyslog/rsyslog.d/00-sonic.conf.j2 index ad05b9da7df..ccafc5ae43b 100644 --- a/files/image_config/rsyslog/rsyslog.d/00-sonic.conf.j2 +++ b/files/image_config/rsyslog/rsyslog.d/00-sonic.conf.j2 @@ -35,6 +35,12 @@ if $programname contains "teamd_" then { stop } + +if $programname contains "l2mc" then { + /var/log/l2mcd.log + stop +} + ## gnmi rules if $msg startswith " gnmi-native" then { /var/log/gnmi.log diff --git a/rules/config b/rules/config index fcc7e927213..d728cbb444c 100644 --- a/rules/config +++ b/rules/config @@ -125,6 +125,9 @@ INCLUDE_SYSTEM_TELEMETRY = n # INCLUDE_ICCPD - build docker-iccpd for mclag support INCLUDE_ICCPD = n +# INCLUDE_L2MCD - build docker-l2mcd for IGMP Snooping +INCLUDE_L2MCD = y + # INCLUDE_SFLOW - build docker-sflow for sFlow support INCLUDE_SFLOW = y @@ -158,7 +161,7 @@ ENABLE_AUTO_TECH_SUPPORT = y # ENABLE_TRANSLIB_WRITE - Enable translib write/config operations via the gNMI interface. # Uncomment to enable: -# ENABLE_TRANSLIB_WRITE = y +ENABLE_TRANSLIB_WRITE = y # ENABLE_NATIVE_WRITE - Enable native write/config operations via the gNMI interface. ENABLE_NATIVE_WRITE = y diff --git a/rules/docker-l2mcd.dep b/rules/docker-l2mcd.dep new file mode 100644 index 00000000000..59dac97ff1b --- /dev/null +++ b/rules/docker-l2mcd.dep @@ -0,0 +1,11 @@ + +DPATH := $($(DOCKER_L2MCD)_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/docker-l2mcd.mk rules/docker-l2mcd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(DPATH)) + +$(DOCKER_L2MCD)_CACHE_MODE := GIT_COMMIT_SHA +$(DOCKER_L2MCD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(DOCKER_L2MCD)_DEP_FILES := $(DEP_FILES) + +$(eval $(call add_dbg_docker,$(DOCKER_L2MCD),$(DOCKER_L2MCD_DBG))) \ No newline at end of file diff --git a/rules/docker-l2mcd.mk b/rules/docker-l2mcd.mk new file mode 100644 index 00000000000..7c97b8ce9c7 --- /dev/null +++ b/rules/docker-l2mcd.mk @@ -0,0 +1,30 @@ +# Docker image for L2MCD +DOCKER_L2MCD_STEM = docker-l2mcd +DOCKER_L2MCD = $(DOCKER_L2MCD_STEM).gz +DOCKER_L2MCD_DBG = $(DOCKER_L2MCD_STEM)-$(DBG_IMAGE_MARK).gz + +$(DOCKER_L2MCD)_PATH = $(DOCKERS_PATH)/docker-l2mcd + +$(DOCKER_L2MCD)_DEPENDS += $(LIBEVENT) $(L2MCD) $(SWSS) $(LIBSWSSCOMMON) +$(DOCKER_L2MCD)_DBG_DEPENDS = $($(DOCKER_CONFIG_ENGINE_BOOKWORM)_DBG_DEPENDS) +$(DOCKER_L2MCD)_DBG_DEPENDS += $(SWSS_DBG) $(LIBSWSSCOMMON_DBG) +$(DOCKER_L2MCD)_DBG_IMAGE_PACKAGES = $($(DOCKER_CONFIG_ENGINE_BOOKWORM)_DBG_IMAGE_PACKAGES) + +$(DOCKER_L2MCD)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_BOOKWORM) + +ifeq ($(INCLUDE_L2MCD), y) +SONIC_DOCKER_IMAGES += $(DOCKER_L2MCD) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_L2MCD) +SONIC_DOCKER_DBG_IMAGES += $(DOCKER_L2MCD_DBG) +SONIC_INSTALL_DOCKER_DBG_IMAGES += $(DOCKER_L2MCD_DBG) +endif + +$(DOCKER_L2MCD)_VERSION = 1.0.0 +$(DOCKER_L2MCD)_PACKAGE_NAME = l2mcd +$(DOCKER_L2MCD)_CONTAINER_NAME = l2mcd +$(DOCKER_L2MCD)_RUN_OPT += -t --cap-add=NET_ADMIN --cap-add=SYS_ADMIN +$(DOCKER_L2MCD)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_L2MCD)_RUN_OPT += -v /host/warmboot:/var/warmboot + +SONIC_BOOKWORM_DOCKERS += $(DOCKER_L2MCD) +SONIC_BOOKWORM_DBG_DOCKERS += $(DOCKER_L2MCD_DBG) diff --git a/rules/l2mcd.dep b/rules/l2mcd.dep new file mode 100644 index 00000000000..74a19250ed4 --- /dev/null +++ b/rules/l2mcd.dep @@ -0,0 +1,14 @@ + +SPATH := $($(L2MCD)_SRC_PATH) +DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/l2mcd.mk rules/l2mcd.dep +DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) +DEP_FILES += $(shell git ls-files $(SPATH)) + +SMDEP_SPATH := $(SPATH)/sonic-l2mcd +SMDEP_FILES := $(addprefix $(SMDEP_SPATH)/,$(shell cd $(SMDEP_SPATH) && git ls-files)) +$(L2MCD)_SMDEP_FILES := $(SMDEP_FILES) +$(L2MCD)_SMDEP_PATHS := $(SMDEP_SPATH) + +$(L2MCD)_CACHE_MODE := GIT_CONTENT_SHA +$(L2MCD)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) +$(L2MCD)_DEP_FILES := $(DEP_FILES) \ No newline at end of file diff --git a/rules/l2mcd.mk b/rules/l2mcd.mk new file mode 100644 index 00000000000..91881170fbc --- /dev/null +++ b/rules/l2mcd.mk @@ -0,0 +1,18 @@ +# L2MCD package +# +L2MCD_VERSION = 1.0.0 +export L2MCD_VERSION + +L2MCD = l2mcd_$(L2MCD_VERSION)_$(CONFIGURED_ARCH).deb +$(L2MCD)_SRC_PATH = $(SRC_PATH)/sonic-l2mcd +$(L2MCD)_DEPENDS += $(LIBSWSSCOMMON_DEV) +$(L2MCD)_RDEPENDS += $(LIBSWSSCOMMON) +$(L2MCD)_DEPENDS += $(LIBEVENT) +SONIC_DPKG_DEBS += $(L2MCD) + +# L2MCD_DBG = l2mcd-dbg_1.0.0_$(CONFIGURED_ARCH).deb +# $(L2MCD_DBG)_DEPENDS += $(L2MCD) +# $(L2MCD_DBG)_RDEPENDS += $(L2MCD) +$(eval $(call add_derived_package,$(L2MCD))) + +export L2MCD diff --git a/slave.mk b/slave.mk index 8a327279be0..de12ed56956 100644 --- a/slave.mk +++ b/slave.mk @@ -450,6 +450,7 @@ $(info "BLDENV" : "$(BLDENV)") $(info "VS_PREPARE_MEM" : "$(VS_PREPARE_MEM)") $(info "INCLUDE_MGMT_FRAMEWORK" : "$(INCLUDE_MGMT_FRAMEWORK)") $(info "INCLUDE_ICCPD" : "$(INCLUDE_ICCPD)") +$(info "INCLUDE_L2MCD" : "$(INCLUDE_L2MCD)") $(info "INCLUDE_STP" : "$(INCLUDE_STP)") $(info "INCLUDE_SYSTEM_TELEMETRY" : "$(INCLUDE_SYSTEM_TELEMETRY)") $(info "INCLUDE_SYSTEM_GNMI" : "$(INCLUDE_SYSTEM_GNMI)") @@ -1483,6 +1484,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ export include_dhcp_server="$(INCLUDE_DHCP_SERVER)" export include_mgmt_framework="$(INCLUDE_MGMT_FRAMEWORK)" export include_iccpd="$(INCLUDE_ICCPD)" + export include_l2mcd="$(INCLUDE_L2MCD)" export include_dash_ha="$(INCLUDE_DASH_HA)" export include_stp="$(INCLUDE_STP)" export pddf_support="$(PDDF_SUPPORT)" diff --git a/src/sonic-yang-models/setup.py b/src/sonic-yang-models/setup.py index d21cd79bb68..47e1ae5ee48 100644 --- a/src/sonic-yang-models/setup.py +++ b/src/sonic-yang-models/setup.py @@ -183,6 +183,8 @@ def print_yang_files_validation_report(yang_files_list): 'sonic-smart-switch.yang', 'sonic-snmp.yang', 'sonic-spanning-tree.yang', + 'sonic-igmp-snooping.yang', + 'sonic-mld-snooping.yang', 'sonic-srv6.yang', 'sonic-ssh-server.yang', 'sonic-static-route.yang', diff --git a/src/sonic-yang-models/tests/files/sample_config_db.json b/src/sonic-yang-models/tests/files/sample_config_db.json index 7ba4e05d47e..f514e3ff13b 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -3158,6 +3158,28 @@ ] } }, + "L2MC": { + "Vlan100": { + "enabled": "true", + "fast-leave": "false", + "last-member-query-interval": "1000", + "querier": "false", + "query-interval": "125", + "query-max-response-time": "10", + "version": "2" + } + }, + "MLD_L2MC": { + "Vlan100": { + "enabled": "true", + "fast-leave": "false", + "last-member-query-interval": "1000", + "querier": "false", + "query-interval": "125", + "query-max-response-time": "10", + "version": "2" + } + }, "STORMOND_CONFIG": { "INTERVALS": { "daemon_polling_interval" : "3600", diff --git a/src/sonic-yang-models/yang-models/sonic-device_metadata.yang b/src/sonic-yang-models/yang-models/sonic-device_metadata.yang index 9f5394113dc..2f20bda0f99 100644 --- a/src/sonic-yang-models/yang-models/sonic-device_metadata.yang +++ b/src/sonic-yang-models/yang-models/sonic-device_metadata.yang @@ -340,6 +340,31 @@ module sonic-device_metadata { } } /* end of container localhost */ + + container x509 { + + leaf ca_crt { + type string { + pattern '(/[a-zA-Z0-9_-]+)*/([a-zA-Z0-9_-]+)\.(cer|crt|pem)'; + } + description "Local path for ca_crt."; + } + + leaf server_crt { + type string { + pattern '(/[a-zA-Z0-9_-]+)*/([a-zA-Z0-9_-]+)\.(cer|crt|pem)'; + } + description "Local path for server_crt."; + } + + leaf server_key { + type string { + pattern '(/[a-zA-Z0-9_-]+)*/([a-zA-Z0-9_-]+).key'; + } + description "Local path for server_key."; + } + + } } /* end of container DEVICE_METADATA */ } diff --git a/src/sonic-yang-models/yang-models/sonic-igmp-snooping.yang b/src/sonic-yang-models/yang-models/sonic-igmp-snooping.yang new file mode 100644 index 00000000000..29135f048d3 --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-igmp-snooping.yang @@ -0,0 +1,255 @@ +module sonic-igmp-snooping { + namespace "http://github.com/sonic-net/sonic-igmp-snooping"; + prefix sigmps; + yang-version 1.1; + + import ietf-inet-types { + prefix inet; + } + + import sonic-port { + prefix prt; + } + + import sonic-portchannel { + prefix lag; + } + + import sonic-vlan { + prefix svlan; + } + + organization + "SONIC"; + + contact + "SONiC"; + + description + "SONIC IGMP SNOOPING"; + + revision 2019-10-15 { + description + "Initial revision."; + } + + container sonic-igmp-snooping { + + container L2MC_STATIC_GROUP { + + list L2MC_STATIC_GROUP_LIST { + key "vlan-name group-addr"; + + leaf vlan-name { + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } + + leaf group-addr { + type inet:ipv4-address; + } + + leaf-list static-members { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + description "List of interfaces/portchannels for the multicast group."; + } + } + } + + container L2MC_STATIC_MEMBER { + + list L2MC_STATIC_MEMBER_LIST { + + key "vlan-name group-addr out-intf"; + + leaf vlan-name { + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } + + leaf group-addr { + type inet:ipv4-address; + } + + leaf out-intf { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + } + leaf port { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + } + } + } + + container L2MC_MROUTER { + + list L2MC_MROUTER_LIST { + + key "vlan-name mrouter-intf"; + + leaf vlan-name { + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } + + leaf mrouter-intf { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + } + + leaf mrouter_port { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + } + } + } + + container L2MC { + + list L2MC_LIST { + key "vlan-name"; + + leaf vlan-name { + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } + + leaf enabled { + type boolean; + default false; + } + + leaf querier { + type boolean; + default false; + } + + leaf fast-leave { + type boolean; + default false; + } + + leaf version { + type uint8 { + range "1..3"{ + error-message "Invalid IGMP Snooping version."; + } + } + default 2; + } + + leaf query-interval { + must "current() > ../query-max-response-time" { + error-message "Invalid IGMP Snooping query interval value."; + } + + type uint32 { + range "1..18000" { + error-message "Invalid IGMP Snooping Query Interval."; + } + } + default 125; + } + + leaf last-member-query-interval { + type uint32 { + range "100..25500"{ + error-message "Invalid IGMP Snooping Last Member Query Interval."; + } + } + default 1000; + } + + leaf query-max-response-time { + must "current() < ../query-interval" { + error-message "Invalid IGMP Snooping query interval value."; + } + type uint16 { + range "1..25"{ + error-message "Invalid IGMP Snooping Query Max Response Time."; + } + } + default 10; + } + } + } + + container L2MC_SUPPRESS { + + list L2MC_SUPPRESS_LIST { + + key "vlan-name"; + + leaf vlan-name { + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } + + leaf ipv4-link-local-groups-suppression { + type enumeration { + enum enable; + enum disable; + } + } + + leaf ipv4-optimised-multicast-flood { + type enumeration { + enum enable; + enum disable; + } + } + + leaf ipv6-link-local-groups-suppression { + type enumeration { + enum enable; + enum disable; + } + } + + leaf ipv6-optimised-multicast-flood { + type enumeration { + enum enable; + enum disable; + } + } + } + } + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-mld-snooping.yang b/src/sonic-yang-models/yang-models/sonic-mld-snooping.yang new file mode 100644 index 00000000000..5fd606b3188 --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-mld-snooping.yang @@ -0,0 +1,213 @@ +module sonic-mld-snooping { + namespace "http://github.com/sonic-net/sonic-mld-snooping"; + prefix smlds; + yang-version 1.1; + + import ietf-inet-types { + prefix inet; + } + + import sonic-port { + prefix prt; + } + + import sonic-portchannel { + prefix lag; + } + + import sonic-vlan { + prefix svlan; + } + + organization + "SONIC"; + + contact + "SONiC"; + + description + "SONIC MLD SNOOPING"; + + revision 2025-11-14 { + description + "Initial revision."; + } + + container sonic-mld-snooping { + + container MLD_L2MC_STATIC_GROUP { + + list MLD_L2MC_STATIC_GROUP_LIST { + key "vlan-name group-addr"; + + leaf vlan-name { + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } + + leaf group-addr { + type inet:ipv6-address; + } + + leaf-list static-members { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + description "List of interfaces/portchannels for the multicast group."; + } + } + } + + container MLD_L2MC_STATIC_MEMBER { + + list MLD_L2MC_STATIC_MEMBER_LIST { + + key "vlan-name group-addr out-intf"; + + leaf vlan-name { + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } + + leaf group-addr { + type inet:ipv6-address; + } + + leaf out-intf { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + } + leaf port { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + } + } + } + + container MLD_L2MC_MROUTER { + + list MLD_L2MC_MROUTER_LIST { + + key "vlan-name mrouter-intf"; + + leaf vlan-name { + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } + + leaf mrouter-intf { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + } + + leaf mrouter_port { + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:name"; + } + type leafref { + path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name"; + } + } + } + } + } + + container MLD_L2MC { + + list MLD_L2MC_LIST { + key "vlan-name"; + + leaf vlan-name { + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } + + leaf enabled { + type boolean; + default false; + } + + leaf querier { + type boolean; + default false; + } + + leaf fast-leave { + type boolean; + default false; + } + + leaf version { + type uint8 { + range "1..2"{ + error-message "Invalid MLD Snooping version."; + } + } + default 2; + } + + leaf query-interval { + must "current() > ../query-max-response-time" { + error-message "Invalid MLD Snooping query interval value."; + } + + type uint32 { + range "1..18000" { + error-message "Invalid MLD Snooping Query Interval."; + } + } + default 125; + } + + leaf last-member-query-interval { + type uint32 { + range "100..25500"{ + error-message "Invalid MLD Snooping Last Member Query Interval."; + } + } + default 1000; + } + + leaf query-max-response-time { + must "current() < ../query-interval" { + error-message "Invalid MLD Snooping query interval value."; + } + type uint16 { + range "1..25"{ + error-message "Invalid MLD Snooping Query Max Response Time."; + } + } + default 10; + } + } + } + } +}