From 95becee05d2bc31f2d65e210257ae6071001205c Mon Sep 17 00:00:00 2001 From: miatao Date: Tue, 19 May 2026 18:14:59 +0000 Subject: [PATCH] [YANG] Enhance PREFIX_LIST Yang model with optional fields Signed-off-by: miatao (cherry picked from commit e293361b0fee4ad761832e2e14aa656aa2492c09) --- src/sonic-yang-models/doc/Configuration.md | 31 +++- .../tests/files/sample_config_db.json | 18 +- .../tests/bgp_prefix_list.json | 49 +++++ .../tests_config/bgp_prefix_list.json | 174 ++++++++++++++++++ .../yang-models/sonic-bgp-prefix-list.yang | 55 +++++- 5 files changed, 321 insertions(+), 6 deletions(-) diff --git a/src/sonic-yang-models/doc/Configuration.md b/src/sonic-yang-models/doc/Configuration.md index bbd51be4bc..26e060dfe7 100644 --- a/src/sonic-yang-models/doc/Configuration.md +++ b/src/sonic-yang-models/doc/Configuration.md @@ -3297,11 +3297,38 @@ An example is as follows: ### Prefix List Prefix list table stores a list of prefixes with type and prefix separated by `|`. The specific configuration for the prefix type are then rendered by the PrefixListMgr. Currently ANCHOR_PREFIX is supported to add RADIAN configuration. -An example is as follows: +The following optional fields are supported for dynamic prefix list configuration: + +| Field | Type | Description | +|---------|--------|-----------------------------------------------------------------------------| +| action | string | Permit or deny action for this prefix entry (`permit` or `deny`) | +| seq | uint32 | Sequence number (1–4294967295) for ordering prefix list entries | +| ge | uint8 | Minimum prefix length to match, greater-than-or-equal (0–128) | +| le | uint8 | Maximum prefix length to match, less-than-or-equal (0–128) | + +Note: `seq`, `ge`, and `le` are modeled as numeric YANG types, but in CONFIG_DB JSON they are stored as strings, as shown in the examples below. + +Examples: ```json { "PREFIX_LIST": { - "ANCHOR_PREFIX|fc00::/48": {} + "ANCHOR_PREFIX|fc00::/48": {}, + "BGP_ALLOWED_IPV4|172.16.0.0/12": { + "action": "permit", + "seq": "200", + "ge": "16", + "le": "24" + }, + "BGP_ALLOWED_IPV6|2001:db8::/32": { + "action": "permit", + "seq": "30", + "ge": "48", + "le": "64" + }, + "BGP_DENIED_IPV4|10.255.0.0/16": { + "action": "deny", + "seq": "30" + } } } ``` 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 6d56fbf1b3..145f2cfc0c 100644 --- a/src/sonic-yang-models/tests/files/sample_config_db.json +++ b/src/sonic-yang-models/tests/files/sample_config_db.json @@ -3138,7 +3138,23 @@ }, "PREFIX_LIST": { "ANCHOR_PREFIX|10.0.0.0/8" : {}, - "ANCHOR_PREFIX|FC00::/48" : {} + "ANCHOR_PREFIX|FC00::/48" : {}, + "BGP_ALLOWED_IPV4|172.16.0.0/12": { + "action": "permit", + "seq": "200", + "ge": "16", + "le": "24" + }, + "BGP_ALLOWED_IPV6|2001:db8::/32": { + "action": "permit", + "seq": "30", + "ge": "48", + "le": "64" + }, + "BGP_DENIED_IPV4|10.255.0.0/16": { + "action": "deny", + "seq": "30" + } }, "DEBUG_COUNTER": { "DEBUG_4": { diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/bgp_prefix_list.json b/src/sonic-yang-models/tests/yang_model_tests/tests/bgp_prefix_list.json index 85d3f7956a..c8c79a24ae 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests/bgp_prefix_list.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests/bgp_prefix_list.json @@ -9,5 +9,54 @@ "desc": "Load BGP prefix list table with an invalid prefix", "eStrKey": "InvalidValue", "eStr": ["prefix"] + }, + "BGP_PREFIX_LIST_WITH_ALL_OPTIONAL_FIELDS": { + "desc": "Load BGP prefix list with action, seq, ge and le fields" + }, + "BGP_PREFIX_LIST_WITH_PERMIT_ACTION": { + "desc": "Load BGP prefix list with permit action only" + }, + "BGP_PREFIX_LIST_WITH_DENY_ACTION": { + "desc": "Load BGP prefix list with deny action only" + }, + "BGP_PREFIX_LIST_WITH_INVALID_ACTION": { + "desc": "Load BGP prefix list with invalid action value", + "eStrKey": "InvalidValue", + "eStr": ["action"] + }, + "BGP_PREFIX_LIST_WITH_INVALID_SEQ_ZERO": { + "desc": "Load BGP prefix list with seq value 0 (out of range)", + "eStrKey": "Range" + }, + "BGP_PREFIX_LIST_WITH_INVALID_GE": { + "desc": "Load BGP prefix list with ge value 129 (out of range)", + "eStrKey": "Range" + }, + "BGP_PREFIX_LIST_WITH_INVALID_LE": { + "desc": "Load BGP prefix list with le value 129 (out of range)", + "eStrKey": "Range" + }, + "BGP_PREFIX_LIST_WITH_INVALID_IPV4_GE_LENGTH": { + "desc": "Load BGP prefix list with IPv4 prefix and ge=33 (must fail)", + "eStr": ["ge value must be <= 32 for IPv4 or <= 128 for IPv6"] + }, + "BGP_PREFIX_LIST_WITH_INVALID_IPV4_LE_LENGTH": { + "desc": "Load BGP prefix list with IPv4 prefix and le=33 (must fail)", + "eStr": ["le value must be <= 32 for IPv4 or <= 128 for IPv6"] + }, + "BGP_PREFIX_LIST_WITH_IPV6_VALID_GE_LE": { + "desc": "Load BGP prefix list with IPv6 prefix and ge=64 le=128 (valid)" + }, + "BGP_PREFIX_LIST_WITH_INVALID_GE_GREATER_THAN_LE": { + "desc": "Load BGP prefix list with ge=24 and le=16 (ge > le must fail)", + "eStr": ["le value must be >= ge value"] + }, + "BGP_PREFIX_LIST_WITH_GE_LESS_THAN_PREFIX_LENGTH": { + "desc": "Load BGP prefix list with 10.0.0.0/24 and ge=16 (ge < prefix length must fail)", + "eStr": ["ge value must be >= prefix length"] + }, + "BGP_PREFIX_LIST_WITH_LE_LESS_THAN_PREFIX_LENGTH": { + "desc": "Load BGP prefix list with 10.0.0.0/24 and le=8 (le < prefix length must fail)", + "eStr": ["le value must be >= prefix length"] } } diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/bgp_prefix_list.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/bgp_prefix_list.json index 5191ba7e85..7599b80ec0 100644 --- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/bgp_prefix_list.json +++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/bgp_prefix_list.json @@ -36,5 +36,179 @@ }, "eStrKey": "InvalidValue", "eStr": ["prefix"] + }, + "BGP_PREFIX_LIST_WITH_ALL_OPTIONAL_FIELDS": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/8", + "action": "permit", + "seq": "100", + "ge": "16", + "le": "24" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_PERMIT_ACTION": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.1.0.0/16", + "action": "permit" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_DENY_ACTION": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "192.168.0.0/16", + "action": "deny" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_INVALID_ACTION": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/8", + "action": "reject" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_INVALID_SEQ_ZERO": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/8", + "seq": "0" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_INVALID_GE": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/8", + "ge": "129" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_INVALID_LE": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/8", + "le": "129" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_INVALID_IPV4_GE_LENGTH": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/8", + "ge": "33" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_INVALID_IPV4_LE_LENGTH": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/8", + "le": "33" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_IPV6_VALID_GE_LE": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "fc00::/48", + "ge": "64", + "le": "128" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_INVALID_GE_GREATER_THAN_LE": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/8", + "ge": "24", + "le": "16" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_GE_LESS_THAN_PREFIX_LENGTH": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/24", + "ge": "16" + } + ] + } + } + }, + "BGP_PREFIX_LIST_WITH_LE_LESS_THAN_PREFIX_LENGTH": { + "sonic-bgp-prefix-list:sonic-bgp-prefix-list": { + "sonic-bgp-prefix-list:PREFIX_LIST": { + "PREFIX_LIST_LIST": [ + { + "prefix_type": "DOWNSTREAM_PREFIX", + "ip-prefix": "10.0.0.0/24", + "le": "8" + } + ] + } + } } } \ No newline at end of file diff --git a/src/sonic-yang-models/yang-models/sonic-bgp-prefix-list.yang b/src/sonic-yang-models/yang-models/sonic-bgp-prefix-list.yang index 78441450ad..5a833baa61 100644 --- a/src/sonic-yang-models/yang-models/sonic-bgp-prefix-list.yang +++ b/src/sonic-yang-models/yang-models/sonic-bgp-prefix-list.yang @@ -10,14 +10,18 @@ module sonic-bgp-prefix-list { prefix stypes; } - import sonic-extension { - prefix ext; + import sonic-routing-policy-sets { + prefix rpolsets; } description "SONIC Device-specfifc BGP prefix lists data"; + revision 2026-05-18 { + description "Add optional action, seq, ge and le leaves for dynamic prefix list configuration"; + } + revision 2025-02-17 { - description "Updated description and leafs for PREFIX_LIST_LIST"; + description "Updated description and leaves for PREFIX_LIST_LIST"; } revision 2025-02-05 { @@ -60,6 +64,51 @@ module sonic-bgp-prefix-list { (contains(../ip-prefix, '.') and current()='IPv4')"; type stypes:ip-family; } + + leaf action { + type rpolsets:routing-policy-action-type; + description "Permit or deny action for this prefix entry"; + } + + leaf seq { + type uint32 { + range "1..4294967295"; + } + description "Sequence number for ordering prefix list entries. Optional, but should be provided when a specific execution order is needed"; + } + + leaf ge { + must "(contains(../ip-prefix, '.') and . <= 32) or + (contains(../ip-prefix, ':') and . <= 128)" { + error-message "ge value must be <= 32 for IPv4 or <= 128 for IPv6"; + } + must ". >= number(substring-after(../ip-prefix, '/'))" { + error-message "ge value must be >= prefix length"; + } + type uint8 { + range "0..128"; + } + description "Minimum prefix length to match (greater-than-or-equal)"; + } + + leaf le { + must "(contains(../ip-prefix, '.') and . <= 32) or + (contains(../ip-prefix, ':') and . <= 128)" { + error-message "le value must be <= 32 for IPv4 or <= 128 for IPv6"; + } + must ". >= number(substring-after(../ip-prefix, '/'))" { + error-message "le value must be >= prefix length"; + } + /* If ge is not set, skip this check. + If ge is set, enforce le >= ge. */ + must "not(../ge) or current() >= ../ge" { + error-message "le value must be >= ge value"; + } + type uint8 { + range "0..128"; + } + description "Maximum prefix length to match (less-than-or-equal)"; + } } } /* end of PREFIX_LIST */