From 6b4fd1a68bd19e7f83e610e01bc04bcb3d1a37ca Mon Sep 17 00:00:00 2001 From: DendroLabs Date: Tue, 17 Mar 2026 11:54:20 -0400 Subject: [PATCH 1/4] Add YANG model for link event dampening feature Adds 6 configuration leaves to the PORT_LIST in sonic-port.yang for the link event dampening feature (sonic-net/SONiC#1071): - link_event_damping_algorithm (disabled/aied/aied-monitor) - max_suppress_time - decay_half_life - suppress_threshold - reuse_threshold - flap_penalty The aied-monitor mode is a SONiC-specific enhancement recommended by RFC 7196 that calculates penalties without suppressing events, allowing safe parameter tuning in production. Signed-off-by: DendroLabs --- .../yang-models/sonic-port.yang | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/sonic-yang-models/yang-models/sonic-port.yang b/src/sonic-yang-models/yang-models/sonic-port.yang index df574f70ab6..80fc3a86f6b 100644 --- a/src/sonic-yang-models/yang-models/sonic-port.yang +++ b/src/sonic-yang-models/yang-models/sonic-port.yang @@ -243,6 +243,73 @@ module sonic-port{ description "Enable or disable fast link-up on the port"; } + leaf link_event_damping_algorithm { + description "Link event damping algorithm. + 'disabled' - no damping applied to this interface. + 'aied' - Additive Increase Exponential Decrease algorithm + based on RFC 2439. Actively suppresses link events + when penalty exceeds suppress threshold. + 'aied-monitor' - Same AIED algorithm but monitor-only mode. + Calculates penalties and emits syslog messages but + does NOT suppress link events. Use to safely tune + parameters in production before enabling full + dampening. Recommended by RFC 7196."; + type string { + pattern "disabled|aied|aied-monitor"; + } + default "disabled"; + } + + leaf max_suppress_time { + description "Maximum time in seconds that an interface can remain + in damped (suppressed) state since the last link-down + event, regardless of accumulated penalty. + A value of 0 means this parameter is not configured. + Industry default: 20 seconds."; + type uint32; + default 0; + } + + leaf decay_half_life { + description "Time in seconds after which the accumulated penalty + is halved if the interface remains stable (no flaps). + Must be less than or equal to max_suppress_time. + A value of 0 means this parameter is not configured. + Industry default: 5 seconds."; + type uint32; + default 0; + } + + leaf suppress_threshold { + description "Penalty threshold above which damping is activated + on the interface. Link events are suppressed when the + accumulated penalty exceeds this value. + A value of 0 means this parameter is not configured. + Industry default: 2000."; + type uint32; + default 0; + } + + leaf reuse_threshold { + description "Penalty threshold at or below which damping is + deactivated. The interface returns to normal operation + when penalty decays to this value. + Must be less than or equal to suppress_threshold. + A value of 0 means this parameter is not configured. + Industry default: 1000."; + type uint32; + default 0; + } + + leaf flap_penalty { + description "Penalty value added to accumulated penalty for each + link-down (UP to DOWN) transition event. + A value of 0 means this parameter is not configured. + Industry standard: 1000."; + type uint32; + default 0; + } + } /* end of list PORT_LIST */ From 3c025e08c230cea54b3051ac8e62be9f89c999e1 Mon Sep 17 00:00:00 2001 From: DendroLabs Date: Tue, 17 Mar 2026 11:54:20 -0400 Subject: [PATCH 2/4] [Link Event Damping] Add YANG must constraints and test cases - Add must constraint: decay_half_life <= max_suppress_time - Add must constraint: reuse_threshold <= suppress_threshold - Add valid and invalid test cases for dampening parameters Signed-off-by: DendroLabs --- .../tests/yang_model_tests/tests/port.json | 18 ++++- .../yang_model_tests/tests_config/port.json | 81 ++++++++++++++++++- .../yang-models/sonic-port.yang | 6 ++ 3 files changed, 102 insertions(+), 3 deletions(-) diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/port.json b/src/sonic-yang-models/tests/yang_model_tests/tests/port.json index db68bd865b6..6c87679865d 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/port.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/port.json @@ -175,8 +175,22 @@ }, "PORT_WITH_NO_LANES_ON_MULT_ASIC_VS_2": { "desc": "PORT_WITH_NO_LANES_ON_MULT_ASIC_VS_2 no failure." + }, + "PORT_VALID_DAMPING_AIED_TEST": { + "desc": "PORT_VALID_DAMPING_AIED_TEST no failure." + }, + "PORT_VALID_DAMPING_AIED_MONITOR_TEST": { + "desc": "PORT_VALID_DAMPING_AIED_MONITOR_TEST no failure." + }, + "PORT_INVALID_DAMPING_ALGORITHM_TEST": { + "desc": "PORT_INVALID_DAMPING_ALGORITHM_TEST invalid algorithm pattern failure.", + "eStrKey" : "Pattern", + "eStr": ["disabled|aied|aied-monitor"] + }, + "PORT_INVALID_DAMPING_HALFLIFE_GT_MAXSUPPRESS_TEST": { + "desc": "PORT_INVALID_DAMPING_HALFLIFE_GT_MAXSUPPRESS_TEST must condition failure.", + "eStrKey" : "Must", + "eStr": ["decay_half_life must be less than or equal to max_suppress_time"] } - - } diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/port.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/port.json index 1b519268b0b..d8844e03e03 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/port.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/port.json @@ -1013,7 +1013,86 @@ "alias": "etp1a", "speed": 100000, "role": "Int" - + + } + ] + } + } + }, + + "PORT_VALID_DAMPING_AIED_TEST": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "name": "Ethernet8", + "alias": "eth8", + "lanes": "65", + "speed": 25000, + "link_event_damping_algorithm": "aied", + "max_suppress_time": 20, + "decay_half_life": 5, + "suppress_threshold": 2000, + "reuse_threshold": 1000, + "flap_penalty": 1000 + } + ] + } + } + }, + + "PORT_VALID_DAMPING_AIED_MONITOR_TEST": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "name": "Ethernet8", + "alias": "eth8", + "lanes": "65", + "speed": 25000, + "link_event_damping_algorithm": "aied-monitor", + "max_suppress_time": 20, + "decay_half_life": 5, + "suppress_threshold": 2000, + "reuse_threshold": 1000, + "flap_penalty": 1000 + } + ] + } + } + }, + + "PORT_INVALID_DAMPING_ALGORITHM_TEST": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "name": "Ethernet8", + "alias": "eth8", + "lanes": "65", + "speed": 25000, + "link_event_damping_algorithm": "invalid_value" + } + ] + } + } + }, + + "PORT_INVALID_DAMPING_HALFLIFE_GT_MAXSUPPRESS_TEST": { + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [ + { + "name": "Ethernet8", + "alias": "eth8", + "lanes": "65", + "speed": 25000, + "link_event_damping_algorithm": "aied", + "max_suppress_time": 10, + "decay_half_life": 15, + "suppress_threshold": 2000, + "reuse_threshold": 1000, + "flap_penalty": 1000 } ] } diff --git a/src/sonic-yang-models/yang-models/sonic-port.yang b/src/sonic-yang-models/yang-models/sonic-port.yang index 80fc3a86f6b..a371a19488c 100644 --- a/src/sonic-yang-models/yang-models/sonic-port.yang +++ b/src/sonic-yang-models/yang-models/sonic-port.yang @@ -276,6 +276,9 @@ module sonic-port{ Must be less than or equal to max_suppress_time. A value of 0 means this parameter is not configured. Industry default: 5 seconds."; + must "current() = 0 or ../max_suppress_time = 0 or current() <= ../max_suppress_time" { + error-message "decay_half_life must be less than or equal to max_suppress_time"; + } type uint32; default 0; } @@ -297,6 +300,9 @@ module sonic-port{ Must be less than or equal to suppress_threshold. A value of 0 means this parameter is not configured. Industry default: 1000."; + must "current() = 0 or ../suppress_threshold = 0 or current() <= ../suppress_threshold" { + error-message "reuse_threshold must be less than or equal to suppress_threshold"; + } type uint32; default 0; } From 175b2b98645dc233b387412064f4bcf901509d83 Mon Sep 17 00:00:00 2001 From: DendroLabs Date: Tue, 17 Mar 2026 13:09:30 -0400 Subject: [PATCH 3/4] Fix YANG test: use None eStrKey for custom error-message When a must constraint has a custom error-message, libyang outputs the custom message directly instead of the generic "Must condition not satisfied". Change eStrKey from "Must" to "None" so the test only checks for our custom error string. Signed-off-by: DendroLabs --- src/sonic-yang-models/tests/yang_model_tests/tests/port.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/port.json b/src/sonic-yang-models/tests/yang_model_tests/tests/port.json index 6c87679865d..ca1e8f09de9 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/port.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/port.json @@ -189,7 +189,7 @@ }, "PORT_INVALID_DAMPING_HALFLIFE_GT_MAXSUPPRESS_TEST": { "desc": "PORT_INVALID_DAMPING_HALFLIFE_GT_MAXSUPPRESS_TEST must condition failure.", - "eStrKey" : "Must", + "eStrKey" : "None", "eStr": ["decay_half_life must be less than or equal to max_suppress_time"] } From bc3488e337da4dfc863a56b2795b129f2e95a8ff Mon Sep 17 00:00:00 2001 From: DendroLabs Date: Fri, 19 Jun 2026 19:11:05 -0400 Subject: [PATCH 4/4] [Link Event Damping] Add sample config and document PORT dampening fields Address review feedback on #26231: add a link event damping sample to tests/files/sample_config_db.json and document the six new PORT attributes in doc/Configuration.md. Signed-off-by: DendroLabs --- src/sonic-yang-models/doc/Configuration.md | 21 ++++++++++++++++++- .../tests/files/sample_config_db.json | 8 ++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/sonic-yang-models/doc/Configuration.md b/src/sonic-yang-models/doc/Configuration.md index d906c6e395e..bfde66b3f79 100644 --- a/src/sonic-yang-models/doc/Configuration.md +++ b/src/sonic-yang-models/doc/Configuration.md @@ -2086,6 +2086,19 @@ In this table the physical port configurations are defined. Each object will have port name as its key, and port name alias and port speed as optional attributes. +The following optional attributes configure per port link event damping +(AIED algorithm, based on RFC 2439), which suppresses link events from a +flapping interface: + +| Attribute | Description | +| ------------------------------ | ----------- | +| `link_event_damping_algorithm` | `disabled` (default), `aied` (suppress link events when penalty exceeds the suppress threshold), or `aied-monitor` (RFC 7196 monitor only mode: calculate penalties and emit syslog but do not suppress; pending swss support). | +| `max_suppress_time` | Maximum seconds an interface may stay suppressed since the last link down event, regardless of penalty. Industry default 20. | +| `decay_half_life` | Seconds after which the accumulated penalty halves while the interface is stable. Must be less than or equal to `max_suppress_time`. Industry default 5. | +| `suppress_threshold` | Penalty above which damping activates. Industry default 2000. | +| `reuse_threshold` | Penalty at or below which damping deactivates. Must be less than or equal to `suppress_threshold`. Industry default 1000. | +| `flap_penalty` | Penalty added for each link down transition. Industry standard 1000. | + ``` { "PORT": { @@ -2102,7 +2115,13 @@ optional attributes. "dom_polling": "enabled", "core_id": "1", "core_port_id": "1", - "num_voq": "8" + "num_voq": "8", + "link_event_damping_algorithm": "aied", + "max_suppress_time": "20", + "decay_half_life": "5", + "suppress_threshold": "2000", + "reuse_threshold": "1000", + "flap_penalty": "1000" }, "Ethernet1": { "index": "1", 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 a07217a5bbc..a17db082f5c 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -635,7 +635,13 @@ "laser_freq": "191600", "tx_power": "-26.6", "mode":"trunk", - "dhcp_rate_limit": "300" + "dhcp_rate_limit": "300", + "link_event_damping_algorithm": "aied", + "max_suppress_time": "20", + "decay_half_life": "5", + "suppress_threshold": "2000", + "reuse_threshold": "1000", + "flap_penalty": "1000" }, "Ethernet1": { "alias": "Eth1/2",