diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case-remap-disabled.xml b/src/sonic-config-engine/tests/simple-sample-graph-case-remap-disabled.xml
index 4ae1b33023..2d26bc9106 100644
--- a/src/sonic-config-engine/tests/simple-sample-graph-case-remap-disabled.xml
+++ b/src/sonic-config-engine/tests/simple-sample-graph-case-remap-disabled.xml
@@ -142,7 +142,7 @@
ab2
- fortyGigE0/4
+ PortChannel01
192.0.0.1
fc02:2000::3;fc02:2000::4
2000
diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case-remap-enabled-no-tunnel-attributes.xml b/src/sonic-config-engine/tests/simple-sample-graph-case-remap-enabled-no-tunnel-attributes.xml
index 6bc2a6db1b..650f56e4de 100644
--- a/src/sonic-config-engine/tests/simple-sample-graph-case-remap-enabled-no-tunnel-attributes.xml
+++ b/src/sonic-config-engine/tests/simple-sample-graph-case-remap-enabled-no-tunnel-attributes.xml
@@ -142,7 +142,7 @@
ab2
- fortyGigE0/4
+ PortChannel01
192.0.0.1
fc02:2000::3;fc02:2000::4
2000
diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case-remap-enabled.xml b/src/sonic-config-engine/tests/simple-sample-graph-case-remap-enabled.xml
index 8c69f04962..b290eb7c6c 100644
--- a/src/sonic-config-engine/tests/simple-sample-graph-case-remap-enabled.xml
+++ b/src/sonic-config-engine/tests/simple-sample-graph-case-remap-enabled.xml
@@ -142,7 +142,7 @@
ab2
- fortyGigE0/4
+ PortChannel01
192.0.0.1
fc02:2000::3;fc02:2000::4
2000
diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case.xml b/src/sonic-config-engine/tests/simple-sample-graph-case.xml
index ddb5f03c58..008719c85b 100644
--- a/src/sonic-config-engine/tests/simple-sample-graph-case.xml
+++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml
@@ -143,7 +143,7 @@
ab2
- fortyGigE0/4
+ PortChannel01
192.0.0.1
fc02:2000::3;fc02:2000::4
2000
diff --git a/src/sonic-config-engine/tests/t0-sample-graph-two-mgmt.xml b/src/sonic-config-engine/tests/t0-sample-graph-two-mgmt.xml
index da1b56fe13..5d201cc3e2 100644
--- a/src/sonic-config-engine/tests/t0-sample-graph-two-mgmt.xml
+++ b/src/sonic-config-engine/tests/t0-sample-graph-two-mgmt.xml
@@ -281,7 +281,7 @@
Vlan2000
- fortyGigE0/112;fortyGigE0/116;fortyGigE0/120
+ PortChannel01;PortChannel02;PortChannel03
False
0.0.0.0/0
diff --git a/src/sonic-config-engine/tests/t0-sample-graph.xml b/src/sonic-config-engine/tests/t0-sample-graph.xml
index 05db8246ec..b343a8b5e3 100644
--- a/src/sonic-config-engine/tests/t0-sample-graph.xml
+++ b/src/sonic-config-engine/tests/t0-sample-graph.xml
@@ -265,7 +265,7 @@
Vlan2000
- fortyGigE0/112;fortyGigE0/116;fortyGigE0/120
+ PortChannel01;PortChannel02;PortChannel03
False
0.0.0.0/0
diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py
index 8bad0f5f35..a5578b841d 100644
--- a/src/sonic-config-engine/tests/test_minigraph_case.py
+++ b/src/sonic-config-engine/tests/test_minigraph_case.py
@@ -129,7 +129,7 @@ class TestCfgGenCaseInsensitive(TestCase):
output = self.run_script(argument)
expected = {
'Vlan1000|Ethernet8': {'tagging_mode': 'untagged'},
- 'Vlan2000|Ethernet4': {'tagging_mode': 'untagged'}
+ 'Vlan2000|PortChannel01': {'tagging_mode': 'untagged'}
}
self.assertEqual(
utils.to_dict(output.strip()),
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 050f4433ba..720ee29568 100644
--- a/src/sonic-yang-models/tests/files/sample_config_db.json
+++ b/src/sonic-yang-models/tests/files/sample_config_db.json
@@ -1185,10 +1185,7 @@
"Vlan111|Ethernet0": {
"tagging_mode": "untagged"
},
- "Vlan111|Ethernet1": {
- "tagging_mode": "untagged"
- },
- "Vlan111|Ethernet2": {
+ "Vlan111|PortChannel0004": {
"tagging_mode": "untagged"
},
"Vlan111|Ethernet3": {
@@ -2262,7 +2259,7 @@
"span": {
"direction": "RX",
"type": "SPAN",
- "dst_port": "Ethernet2",
+ "dst_port": "Ethernet7",
"src_port": "Ethernet3,Ethernet4"
}
},
diff --git a/src/sonic-yang-models/tests/yang_model_tests/test_yang_model.py b/src/sonic-yang-models/tests/yang_model_tests/test_yang_model.py
index d776f479cd..d80293587a 100644
--- a/src/sonic-yang-models/tests/yang_model_tests/test_yang_model.py
+++ b/src/sonic-yang-models/tests/yang_model_tests/test_yang_model.py
@@ -234,8 +234,8 @@ class Test_yang_models:
desc = self.SpecialTests[test]['desc']
self.logStartTest(desc)
jInput = json.loads(self.readJsonInput(test))
- # check all Vlan from 1 to 4094
- for i in range(4095):
+ # check all Vlan from 2 to 4094
+ for i in range(2,4095):
vlan = 'Vlan'+str(i)
jInput["sonic-vlan:sonic-vlan"]["sonic-vlan:VLAN"]["VLAN_LIST"]\
[0]["name"] = vlan
diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests/vlan.json b/src/sonic-yang-models/tests/yang_model_tests/tests/vlan.json
index 7f1cb4eb35..a795a7e3b3 100644
--- a/src/sonic-yang-models/tests/yang_model_tests/tests/vlan.json
+++ b/src/sonic-yang-models/tests/yang_model_tests/tests/vlan.json
@@ -86,5 +86,33 @@
"VLAN_INTERFACE_INVALID_ENABLE_IPV6_LINK_LOCAL": {
"desc": "Enable the ipv6 link-local as true.",
"eStr": "Invalid value \"true\" in \"ipv6_use_link_local_only\" element."
+ },
+ "VLAN_MEMBERS_WITHOUT_CREATING_VLAN":{
+ "desc": "Vlan members without Creating Vlan",
+ "eStrKey": "LeafRef"
+ },
+ "VLAN_CREATE_VLAN_WITH_MISSMATCHING_NAME": {
+ "desc": "Create Vlan so that name doesn't match id",
+ "eStr": "The vlanid must correspond to the VLAN name"
+ },
+ "IP_PREFIX_WITHOUT_CREATNG_VLAN": {
+ "desc": "Create IP on not created Vlan",
+ "eStrKey": "LeafRef"
+ },
+ "MIRROR_SESSION_ON_VLAN_MEMBER_PORT": {
+ "desc": "Set mirror dst port to a Vlan member",
+ "eStr": "Port is used as a destination port in a mirror session"
+ },
+ "VLAN_ADD_PORT_CHANNEL_MEMBER": {
+ "desc": "Add port channel member to Vlan",
+ "eStr": "Port is a member of a port channel"
+ },
+ "VLAN_ADD_PORT_THAT_IS_UNTAGGED": {
+ "desc": "Add port that is already untagged",
+ "eStr": "Port can be untagged in at most one VLAN"
+ },
+ "VLAN_ADD_PORT_THAT_IS_ROUTER_INTERFACE": {
+ "desc": "Add to Vlan port that is router interface",
+ "eStr": "Port is a router interface"
}
}
diff --git a/src/sonic-yang-models/tests/yang_model_tests/tests_config/vlan.json b/src/sonic-yang-models/tests/yang_model_tests/tests_config/vlan.json
index 9f3086b60c..b4288472cf 100644
--- a/src/sonic-yang-models/tests/yang_model_tests/tests_config/vlan.json
+++ b/src/sonic-yang-models/tests/yang_model_tests/tests_config/vlan.json
@@ -719,5 +719,248 @@
]
}
}
+ },
+
+ "VLAN_MEMBERS_WITHOUT_CREATING_VLAN": {
+ "sonic-port:sonic-port": {
+ "sonic-port:PORT": {
+ "PORT_LIST": [
+ {
+ "admin_status": "up",
+ "name": "Ethernet0"
+ }
+ ]
+ }
+ },
+ "sonic-vlan:sonic-vlan": {
+ "sonic-vlan:VLAN_MEMBER": {
+ "VLAN_MEMBER_LIST": [
+ {
+ "port": "Ethernet0",
+ "tagging_mode": "tagged",
+ "name": "Vlan100"
+ }
+ ]
+ }
+ }
+ },
+ "VLAN_CREATE_VLAN_WITH_MISSMATCHING_NAME": {
+ "sonic-vlan:sonic-vlan": {
+ "sonic-vlan:VLAN": {
+ "VLAN_LIST": [
+ {
+ "name": "Vlan10",
+ "vlanid":11
+ }
+ ]
+ }
+ }
+ },
+ "IP_PREFIX_WITHOUT_CREATNG_VLAN": {
+ "sonic-vlan:sonic-vlan": {
+ "sonic-vlan:VLAN": {
+ "VLAN_LIST": [
+ {
+ "description": "server_vlan",
+ "name": "Vlan10"
+ }
+ ]
+ },
+ "sonic-vlan:VLAN_INTERFACE": {
+ "VLAN_INTERFACE_IPPREFIX_LIST": [
+ {
+ "family": "IPv4",
+ "ip-prefix": "20.0.0.1/24",
+ "scope": "global",
+ "name": "Vlan100"
+ }
+ ],
+ "VLAN_INTERFACE_LIST": [
+ {
+ "name": "Vlan100"
+ }
+ ]
+ }
+ }
+ },
+ "MIRROR_SESSION_ON_VLAN_MEMBER_PORT": {
+ "sonic-port:sonic-port": {
+ "sonic-port:PORT": {
+ "PORT_LIST": [
+ {
+ "admin_status": "up",
+ "name": "Ethernet1",
+ "speed": 25000,
+ "lanes": "1"
+ },
+ {
+ "admin_status": "up",
+ "name": "Ethernet2",
+ "speed": 25000,
+ "lanes": "1"
+ }
+ ]
+ }
+ },
+ "sonic-vlan:sonic-vlan": {
+ "sonic-vlan:VLAN": {
+ "VLAN_LIST": [
+ {
+ "name": "Vlan10"
+ }
+ ]
+ },
+ "sonic-vlan:VLAN_MEMBER": {
+ "VLAN_MEMBER_LIST": [
+ {
+ "port": "Ethernet2",
+ "tagging_mode": "tagged",
+ "name": "Vlan10"
+ }
+ ]
+ }
+ },
+ "sonic-mirror-session:sonic-mirror-session": {
+ "sonic-mirror-session:MIRROR_SESSION": {
+ "MIRROR_SESSION_LIST": [ {
+ "name":"mirror_session_dscp",
+ "type": "SPAN",
+ "src_port": "Ethernet1",
+ "dst_port": "Ethernet2"
+ }]
+ }
+ }
+ },
+ "VLAN_ADD_PORT_CHANNEL_MEMBER": {
+ "sonic-port:sonic-port": {
+ "sonic-port:PORT": {
+ "PORT_LIST": [{
+ "admin_status": "up",
+ "name": "Ethernet1",
+ "speed": 25000,
+ "lanes": "1"
+ }]
+ }
+ },
+ "sonic-portchannel:sonic-portchannel": {
+ "sonic-portchannel:PORTCHANNEL": {
+ "PORTCHANNEL_LIST": [
+ {
+ "admin_status": "up",
+ "min_links": "1",
+ "mtu": "9100",
+ "tpid": "0x8100",
+ "lacp_key": "auto",
+ "name": "PortChannel0001",
+ "fast_rate": "false",
+ "fallback" : "false",
+ "mode" : "routed"
+ }
+ ]
+ },
+ "sonic-portchannel:PORTCHANNEL_MEMBER": {
+ "PORTCHANNEL_MEMBER_LIST": [
+ {
+ "name": "PortChannel0001",
+ "port": "Ethernet1"
+ }
+ ]
+ }
+ },
+ "sonic-vlan:sonic-vlan": {
+ "sonic-vlan:VLAN": {
+ "VLAN_LIST": [
+ {
+ "name": "Vlan10"
+ }
+ ]
+ },
+ "sonic-vlan:VLAN_MEMBER": {
+ "VLAN_MEMBER_LIST": [
+ {
+ "port": "Ethernet1",
+ "tagging_mode": "tagged",
+ "name": "Vlan10"
+ }
+ ]
+ }
+ }
+ },
+ "VLAN_ADD_PORT_THAT_IS_UNTAGGED": {
+ "sonic-port:sonic-port": {
+ "sonic-port:PORT": {
+ "PORT_LIST": [{
+ "admin_status": "up",
+ "name": "Ethernet1",
+ "speed": 25000,
+ "lanes": "1"
+ }]
+ }
+ },
+ "sonic-vlan:sonic-vlan": {
+ "sonic-vlan:VLAN": {
+ "VLAN_LIST": [
+ {
+ "name": "Vlan10"
+ },
+ {
+ "name": "Vlan11"
+ }
+ ]
+ },
+ "sonic-vlan:VLAN_MEMBER": {
+ "VLAN_MEMBER_LIST": [
+ {
+ "port": "Ethernet1",
+ "tagging_mode": "untagged",
+ "name": "Vlan10"
+ },
+ {
+ "port": "Ethernet1",
+ "tagging_mode": "untagged",
+ "name": "Vlan11"
+ }
+ ]
+ }
+ }
+ },
+ "VLAN_ADD_PORT_THAT_IS_ROUTER_INTERFACE": {
+ "sonic-interface:sonic-interface": {
+ "sonic-interface:INTERFACE": {
+ "INTERFACE_LIST": [
+ {
+ "name": "Ethernet1"
+ }
+ ]
+ }
+ },
+ "sonic-port:sonic-port": {
+ "sonic-port:PORT": {
+ "PORT_LIST": [{
+ "admin_status": "up",
+ "name": "Ethernet1",
+ "speed": 25000,
+ "lanes": "1"
+ }]
+ }
+ },
+ "sonic-vlan:sonic-vlan": {
+ "sonic-vlan:VLAN": {
+ "VLAN_LIST": [
+ {
+ "name": "Vlan10"
+ }
+ ]
+ },
+ "sonic-vlan:VLAN_MEMBER": {
+ "VLAN_MEMBER_LIST": [
+ {
+ "port": "Ethernet1",
+ "tagging_mode": "untagged",
+ "name": "Vlan10"
+ }
+ ]
+ }
+ }
}
}
diff --git a/src/sonic-yang-models/yang-models/sonic-vlan.yang b/src/sonic-yang-models/yang-models/sonic-vlan.yang
index ad1ab8d743..f0f1aa603e 100644
--- a/src/sonic-yang-models/yang-models/sonic-vlan.yang
+++ b/src/sonic-yang-models/yang-models/sonic-vlan.yang
@@ -1,6 +1,6 @@
module sonic-vlan {
- yang-version 1.1;
+ yang-version 1.1;
namespace "http://github.com/sonic-net/sonic-vlan";
prefix vlan;
@@ -34,8 +34,19 @@ module sonic-vlan {
prefix vrf;
}
+ import sonic-mirror-session {
+ prefix sms;
+ }
+ import sonic-interface {
+ prefix intf;
+ }
+
description "VLAN yang Module for SONiC OS";
+ revision 2024-03-07 {
+ description "Add Constraints that are implemented in CLI";
+ }
+
revision 2021-04-22 {
description "Modify Vlan Member to include PortChannel along with Port";
}
@@ -62,7 +73,7 @@ module sonic-vlan {
leaf name {
type leafref {
- path /vlan:sonic-vlan/vlan:VLAN/vlan:VLAN_LIST/vlan:name;
+ path "/vlan:sonic-vlan/vlan:VLAN/vlan:VLAN_LIST/vlan:name";
}
}
@@ -80,7 +91,7 @@ module sonic-vlan {
error-app-tag nat-zone-invalid;
}
}
- default "0";
+ default "0";
}
leaf mpls {
description "Enable/disable MPLS routing for the vlan interface";
@@ -109,10 +120,10 @@ module sonic-vlan {
}
- leaf loopback_action {
- description "Packet action when a packet ingress and gets routed on the same IP interface";
- type stypes:loopback_action;
- }
+ leaf loopback_action {
+ description "Packet action when a packet ingress and gets routed on the same IP interface";
+ type stypes:loopback_action;
+ }
}
/* end of VLAN_INTERFACE_LIST */
@@ -149,9 +160,9 @@ module sonic-vlan {
leaf family {
/* family leaf needed for backward compatibility
- Both ip4 and ip6 address are string in IETF RFC 6021,
- so must statement can check based on : or ., family
- should be IPv4 or IPv6 according.
+ Both ip4 and ip6 address are string in IETF RFC 6021,
+ so must statement can check based on : or ., family
+ should be IPv4 or IPv6 according.
*/
must "(contains(../ip-prefix, ':') and current()='IPv6') or
@@ -164,7 +175,7 @@ module sonic-vlan {
type boolean;
}
}
- /* end of VLAN_INTERFACE_LIST */
+ /* end of VLAN_INTERFACE_IPPREFIX_LIST */
}
/* end of VLAN_INTERFACE container */
@@ -178,13 +189,15 @@ module sonic-vlan {
leaf name {
type string {
- pattern 'Vlan([0-9]{1,3}|[1-3][0-9]{3}|[4][0][0-8][0-9]|[4][0][9][0-4])';
+ pattern 'Vlan(409[0-5]|40[0-8][0-9]|[1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[2-9])';
}
}
-
leaf vlanid {
type uint16 {
- range 1..4094;
+ range 2..4094;
+ }
+ must "substring-after(../name, 'Vlan') = current()"{
+ error-message "The vlanid must correspond to the VLAN name";
}
}
@@ -239,7 +252,6 @@ module sonic-vlan {
path "/vlan:sonic-vlan/vlan:VLAN/vlan:VLAN_LIST/vlan:name";
}
}
-
leaf port {
/* key elements are mandatory by default */
type union {
@@ -250,17 +262,29 @@ module sonic-vlan {
path "/lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:name";
}
}
+ must "not(/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:MIRROR_SESSION_LIST[sms:dst_port=current()])"
+ {
+ error-message "Port is used as a destination port in a mirror session.";
+ }
+ must "not(/lag:sonic-portchannel/lag:PORTCHANNEL_MEMBER/lag:PORTCHANNEL_MEMBER_LIST[lag:port=current()]/lag:name)" {
+ error-message "Port is a member of a port channel.";
+ }
+ must "not(/intf:sonic-interface/intf:INTERFACE/intf:INTERFACE_LIST[intf:name=current()])" {
+ error-message "Port is a router interface.";
+ }
+ must "count(../../vlan:VLAN_MEMBER_LIST[vlan:port=current() and vlan:tagging_mode='untagged']) <= 1" {
+ error-message "Port can be untagged in at most one VLAN.";
+ }
}
-
leaf tagging_mode {
mandatory true;
type stypes:vlan_tagging_mode;
}
}
- /* end of list VLAN_MEMBER_LIST */
+ /* end of list VLAN_MEMBER_LIST */
}
- /* end of container VLAN_MEMBER */
+ /* end of container VLAN_MEMBER */
}
- /* end of container sonic-vlan */
+ /* end of container sonic-vlan */
}
/* end of module sonic-vlan */