修订
牧师 | 日期 | 作者 | 改变的描述 |
---|---|---|---|
1.0 | 8月22日 | Praveen Chaudhary | 初始版本 |
1.0 | 9月11日 | 帕塔·杜塔(Partha Dutta) | 为SONiC YANG添加额外的步骤 |
1.1 | 2023年12月15日 | 谢Jingwen | 为 List Keys 添加规则 |
参考文献。
参考文献。 | 日期/版本 | 链接 |
---|---|---|
RFC 7950 | 2016年8月 | RFC 7950 - The YANG 1.1 Data Modeling Language |
管理框架 | 0.9 | #436 |
术语和缩写
首字母缩略词 | 描述/扩展 |
---|---|
ABNF公司 | 增广巴克斯-诺尔式 |
XPath | XML路径语言 |
CVL | 配置验证库 |
概述
本文件列出了用于为SONiC编写YANG模块的指导方针。这些YANG模块(称为SONiC YANG模型)将主要基于或代表SONiC的ABNF.json,并且YANG模型的语法必须遵循RFC 7950(https://tools.ietf.org/html/rfc7950)。ABNF.json格式的配置细节可以在https://github.com/sonic-net/SONiC/wiki/Configuration找到。
这些YANG模型将用于验证SONiC交换机的配置,因此支持SONiC Switch上配置验证的库必须使用这些YANG模型。这些库的列表是:1.)配置验证库。(CVL)。使用这些指南编写的YANG模型也可以用作用户端YANG模型,即北向配置工具或CLI可以提供与这些YANG模型同步的配置数据。例如,SONiC管理框架使用SONiC YANG模型作为北向管理YANG和配置验证目的。
的指导方针
1. 所有与一个特性相关的模式定义应该写在一个单独的YANG模型文件中。YANG模型文件命名为'sonic-{ feature}.yang',例如ACL特性的文件名是sonic-acl.yang。最好根据网络组件对YANG模块进行分类。例如,最好为VLAN、ACL、PORT和IP-ADDRESSES等建立单独的模块。
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>sonic-acl.yang
sonic-interface.yang
sonic-port.yang
sonic-vlan.yang
</code></span></span></span></span>
2. 强制定义一个顶级 YANG 容器,命名为'sonic-{ feature} ',即与 YANG 模型名相同,例如,sonic-acl.yang 应该有'sonic-acl' 作为顶级容器,所有其他定义都应该写在顶级容器内。
例子:
的
module sonic-acl {
container sonic-acl {
.....
.....
}
}
3. 定义命名空间为 "http://github.com/Azure/{ model-name} "。
例子:
的
module sonic-acl {
namespace "http://github.com/Azure/sonic-acl";
.....
.....
}
4. 每当修改YANG模型时,使用“revision”记录修改历史。使用适当的细节更新修订有助于跟踪模型中的更改。
例子:
的
module sonic-acl {
revision 2019-09-02 {
description
"Added must expression for ACL_RULE_LIST."; // Updated with new change details
}
revision 2019-09-01 {
description
"Initial revision.";
}
.....
.....
}
5. ABNF.json的每个主要部分(即ABNF.json中的字典),例如,ABNF.json中的VLAN,VLAN_MEMBER,INTERFACE将映射到YANG模型中的容器。
示例:表VLAN将转换为容器VLAN。
ABNF公司
"VLAN": {
"Vlan100": {
"vlanid": "100"
}
}
将翻译为:
的
--
container VLAN { //"VLAN" mapped to a container
list VLAN_LIST {
key name;
leaf vlanid {
type uint16;
}
}
}
6. YANG模块中的每个叶子都应该与ABNF.json中对应的键字段具有相同的名称(包括大小写)。
叶子名是相同的PACKET_ACTION,IP_TYPE和PRIORITY,这些都是在ABNF中定义的。
ABNF公司
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> "NO-NSW-.....|.....": {
"PACKET_ACTION": "FORWARD",
"IP_TYPE": "IPv6ANY",
"PRIORITY": "955520",
.....
.....
},
</code></span></span></span></span>
的
leaf PACKET_ACTION {
.....
}
leaf IP_TYPE {
.....
}
leaf PRIORITY {
.....
}
7. 如果适用,首先使用 IETF 数据类型(RFC 6021)。只有当 IETF 类型不适用时,才声明新类型(即 SONiC 类型)。所有的 SONiC 类型必须是相同的头文件类型或公共 YANG 模型的一部分。
例子:
的
leaf SRC_IP {
type inet:ipv4-prefix; <<<<
}
leaf DST_IP {
type inet:ipv4-prefix;
}
8. YANG模型中对象的数据节点/对象层次结构将与配置数据库中同一层次结构的所有字段相同。如果创建任何异常,则必须在YANG模型的对象级别下正确地记录注释。要查看注释的示例,请参阅下面标题为“注释所有必须、何时和模式条件”的步骤。
例如:
在YANG模型中,VLAN_INTERFACE的“Family”和ACL_RULE的“IP_TYPE”也应该在同一级别。
ABNF公司
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>"VLAN_INTERFACE": {
"Vlan100|2a04:f547:45:6709::1/64": {
"scope": "global",
"family": "IPv6"
}
}
"ACL_RULE": {
"NO-NSW-PACL-V4|DEFAULT_DENY": {
"PACKET_ACTION": "DROP",
"IP_TYPE": "IPv4ANY",
"PRIORITY": "0"
}
}
</code></span></span></span></span>
的
在YANG中,VLAN_INTERFACE的“Family”和ACL_RULE的“IP_TYPE”在同一级别。
container VLAN_INTERFACE {
description "VLAN_INTERFACE part of config_db.json";
list VLAN_INTERFACE_LIST {
......
......
leaf family {
type sonic-head:ip-family;
}
}
}
container ACL_RULE {
description "ACL_RULE part of config_db.json";
list ACL_RULE_LIST {
......
......
leaf IP_TYPE {
type sonic-head:ip_type;
}
}
}
9. 如果一个对象是ABNF.json中主键的一部分,那么它应该是YANG模型中的一个键。在YANG模型中,ABNF.json中的主键可以表示为容器对象的名称或List对象的关键字段。异常必须在YANG模型中通过object字段中的注释记录。要查看注释的示例,请参阅下面标题为“Comment all must, when and patterns conditions.”的步骤。虽然键名不会存储在Redis DB中,但请使用与ABNF模式中定义的相同的键名。
例如:ABNF.json中的VLAN_MEMBER字典的键有vlan-id和ifname部分,所以YANG模型应该有相同的键。
ABNF公司
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> "VLAN_MEMBER": {
"Vlan100|Ethernet0": { //<<<< KEYS
"tagging_mode": "untagged"
}
}
</code></span></span></span></span>
定义VLAN成员的接口 key = VLAN_MEMBER_TABLE:"Vlan"vlanid:ifname ;
的
container VLAN_MEMBER {
description "VLAN_MEMBER part of config_db.json";
list ..... {
key "vlan-name ifname";//<<<< KEYS
}
}
10. 如果当前表中的任何键引用了其他表,那么键叶定义要使用leafref类型。
例子:
ABNF公司
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>key: ACL_RULE_TABLE:table_name:rule_name
.....
.....
</code></span></span></span></span>
的
.....
container ACL_TABLE {
list ACL_TABLE_LIST {
key table_name;
leaf table_name {
type string;
}
.....
.....
}
}
container ACL_RULE {
list ACL_RULE_LIST {
key "table_name rule_name";
leaf table_name {
type leafref {
path "../../../ACL_TABLE/ACL_TABLE_LIST/aclname"; //Refers to other table 'ACL_TABLE'
}
}
leaf rule_name {
type string;
}
.....
.....
}
}
11. Redis中的映射表是使用嵌套的“list”来定义的。使用“sonic-ext:map-list “true”;”来表示“list”是用于映射表的。外部的“list”用于多个映射实例。内部的“list”用于每个外部列表实例的映射条目。
例子:
ABNF公司
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>; TC to queue map
;SAI mapping - qos_map with SAI_QOS_MAP_ATTR_TYPE == SAI_QOS_MAP_TC_TO_QUEUE. See saiqosmaps.h
key = "TC_TO_QUEUE_MAP_TABLE:"name ;field
tc_num = 1*DIGIT ;values
queue = 1*DIGIT; queue index
</code></span></span></span></span>
的
container TC_TO_QUEUE_MAP {
list TC_TO_QUEUE_MAP_LIST {
key "name";
sonic-ext:map-list "true"; //special annotation for map table
leaf name {
type string;
}
list TC_TO_QUEUE_MAP_LIST { //this is list inside list for storing mapping between two fields
key "tc_num qindex";
leaf tc_num {
type string {
pattern "[0-9]?";
}
}
leaf qindex {
type string {
pattern "[0-9]?";
}
}
}
}
}
12. ABNF 模式中的'ref_hash_key_reference' 使用 'leafref' 来定义引用表。
例子:
ABNF公司
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>; QUEUE table. Defines port queue.
; SAI mapping - port queue.
key = "QUEUE_TABLE:"port_name":queue_index
queue_index = 1*DIGIT
port_name = ifName
queue_reference = ref_hash_key_reference ;field value
scheduler = ref_hash_key_reference; reference to scheduler key
wred_profile = ref_hash_key_reference; reference to wred profile key
</code></span></span></span></span>
的
container sonic-queue {
container QUEUE {
list QUEUE_LIST {
.....
leaf scheduler {
type leafref {
path "/sch:sonic-scheduler/sch:SCHEDULER/sch:name"; //Reference to SCHEDULER table
}
}
leaf wred_profile {
type leafref {
path "/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:name"; // Reference to WRED_PROFILE table
}
}
}
}
}
13. 在多个表之间建立复杂的关系和约束时,使用“must”表达式。定义适当的错误消息,当条件不满足时报告给北向。对于现有的功能,代码逻辑可以作为派生“must”表达式的参考点。
例子:
的
must "(/sonic-ext:operation/sonic-ext:operation != 'DELETE') or " +
"count(../../ACL_TABLE[aclname=current()]/ports) = 0" {
error-message "Ports are already bound to this rule.";
}
14. 在'length', 'pattern', 'range'和'must'语句中定义适当的'error-app-tag'和'error'消息,以便管理应用程序可以使用它进行错误报告。
例子:
的
module sonic-vlan {
....
....
leaf vlanid {
mandatory true;
type uint16 {
range "1..4095" {
error-message "Vlan ID out of range";
error-app-tag vlanid-invalid;
}
}
}
....
....
}
15. 所有的必须、当、模式和枚举约束都可以从.h文件或代码中派生出来。如果代码可能具有一些配置的未知行为,那么我们应该在YANG模型对象中放入一个约束。此外,开发人员可以放入任何额外的约束来阻止无效的配置。对于新功能,约束可以基于低级设计文档派生出来。
例如:枚举IP_TYPE comes for aclorch.h
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>#define IP_TYPE_ANY "ANY"
#define IP_TYPE_IP "IP"
#define IP_TYPE_NON_IP "NON_IP"
#define IP_TYPE_IPv4ANY "IPV4ANY"
#define IP_TYPE_NON_IPv4 "NON_IPv4"
#define IP_TYPE_IPv6ANY "IPV6ANY"
#define IP_TYPE_NON_IPv6 "NON_IPv6"
#define IP_TYPE_ARP "ARP"
#define IP_TYPE_ARP_REQUEST "ARP_REQUEST"
#define IP_TYPE_ARP_REPLY "ARP_REPLY"
</code></span></span></span></span>
当语句的例子:如果输入以下配置,SONiC的Orchagent将有未知的行为,所以YANG必须有一个约束。这里SRC_IP是IPv4,而IP_TYPE是IPv6。
ABNF:
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code> "ACL_RULE": {
"NO-NSW-PACL-V4|Rule_20": {
"PACKET_ACTION": "FORWARD",
"DST_IP": "10.186.72.0/26",
"SRC_IP": "10.176.0.0/15",
"PRIORITY": "999980",
"IP_TYPE": "IPv6"
},
</code></span></span></span></span>
阳:
choice ip_prefix {
case ip4_prefix {
when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV4' or .='IPV4ANY' or .='ARP'])";
leaf SRC_IP {
type inet:ipv4-prefix;
}
leaf DST_IP {
type inet:ipv4-prefix;
}
}
case ip6_prefix {
when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV6' or .='IPV6ANY'])";
leaf SRC_IPV6 {
type inet:ipv6-prefix;
}
leaf DST_IPV6 {
type inet:ipv6-prefix;
}
}
}
模式示例:如果端口范围应该是“<0-65365> - <0-65365>”
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>leaf L4_DST_PORT_RANGE {
type string {
pattern '([0-9]{1,4}|[0-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-2][0-9]{2}|[6][5][3][0-5]{2}|[6][5][3][6][0-5])-([0-9]{1,4}|[0-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-2][0-9]{2}|[6][5][3][0-5]{2}|[6][5][3][6][0-5])';
}
}
</code></span></span></span></span>
16. 注释所有必须、何时和模式条件。参见下面的注释示例。
例子:
的
leaf family {
/* family leaf needed for backward compatibility
Both ip4 and ip6 address are string in IETF RFC 6020,
so must statement can check based on : or ., family
should be IPv4 or IPv6 according.
*/
must "(contains(../ip-prefix, ':') and current()='IPv6') or
(contains(../ip-prefix, '.') and current()='IPv4')";
type sonic-head:ip-family;
}
17. 如果 YANG 模型需要 List 对象来绑定 ABNF.json 中 Table 中的多个条目,但这个 LIST 不是配置数据中的有效条目,那么我们必须将这样的列表定义为 _LIST 。
例如:PORTCHANNEL_INTERFACE表中的以下条目必须是YANG模型中List Object的一部分,因为配置数据中可能存在可变数量的条目,但是配置数据中没有显式的列表。为了支持这一点,应该在YANG模型中添加一个名为PORTCHANNEL_INTERFACE_LIST的列表对象。
ABNF:
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>"PORTCHANNEL_INTERFACE": {
"PortChannel01|10.0.0.56/31": {},
"PortChannel01|FC00::71/126": {},
"PortChannel02|10.0.0.58/31": {},
"PortChannel02|FC00::75/126": {}
...
}
</code></span></span></span></span>
的
container PORTCHANNEL_INTERFACE {
description "PORTCHANNEL_INTERFACE part of config_db.json";
list PORTCHANNEL_INTERFACE_LIST {<<<<<
.....
.....
}
}
18. 在某些情况下,可能需要根据 ABNF 表中存储的数据将 ABNF 表拆分为多个 YANG 表,在这种情况下,确保 List 键是非重叠的、唯一的和明确的至关重要。
确保唯一和无歧义键的策略:利用具有不同数量的键元素的复合键来区分列表。需要指出的是,不同的键名不算作无歧义模型。
ABNF公司
<span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><span style="color:#24292f"><span style="color:var(--fgColor-default, var(--color-fg-default))"><span style="background-color:var(--bgColor-muted, var(--color-canvas-subtle))"><code>"INTERFACE" : {
"Ethernet1" : {
"vrf-name": "vrf1"
}
"Ethernet1|10.184.230.211/31": {
}
}
</code></span></span></span></span>
示例 1:具有不同数量元素的键(复合键 - 允许的大小写)
INTERFACE
表存储了接口所属的 VRF 名称,也存储了每个接口的 IP 地址,因此需要将它们分成两个不同的 YANG 列表。
......
container INTERFACE {
list INTERFACE_LIST { // 1st list
key ifname;
leaf ifname {
type leafref {
......
}
}
leaf vrf-name {
type leafref {
......
}
}
......
}
list INTERFACE_IPADDR_LIST { //2nd list
key "ifname ip_addr"
leaf ifname {
type leafref {
......
}
}
leaf ip_addr {
type inet:ipv4-prefix;
}
......
}
}
......
在上面的例子中,如果配置数据库包含一个INTERFACE表,其中有一个键元素,那么它将与INTERFACE_LIST关联,如果包含两个键元素,那么它将与INTERFACE_IPADDR_LIST关联。
例2:键具有相同数量的相同类型的元素(不允许情况1)
......
container NOT_SUPPORTED_INTERFACE {
list NOT_SUPPORTED_INTERFACE_LIST { // 1st list
key ifname;
leaf ifname {
type string;
}
// ...
}
list NOT_SUPPORTED_INTERFACE_ANOTHER_LIST { // Negative case
key ifname;
leaf ifname {
type string;
}
// ...
}
}
......
在上面的例子中,如果配置数据库包含一个键为Ethernet1的NOT_SUPPORTED_INTERFACE表,那么它将与两个列表匹配,这是一种重叠场景。
例3:键具有相同数量的相同类型的元素(不允许情况2)
......
container NOT_SUPPORTED_TELEMETRY_CLIENT {
list NOT_SUPPORTED_TELEMETRY_CLIENT_DS_LIST { // 1st list
key "prefix name";
leaf prefix {
type string {
pattern "DestinationGroup_" + ".*";
}
}
leaf name {
type string;
}
leaf dst_addr {
type ipv4-port;
}
}
list NOT_SUPPORTED_TELEMETRY_CLIENT_SUB_LIST { // Negative case
key "prefix name";
leaf prefix {
type string {
pattern "Subscription_" + ".*";
}
}
leaf name {
type string;
}
leaf dst_group {
must "(contains(../../TELEMETRY_CLIENT_DS_LIST/prefix, current()))";
type string;
}
}
}
......
在上面的例子中,如果配置数据库包含一个键为“DestinationGroup|HS”的NOT_SUPPORTED_TELEMETRY_CLIENT表,那么它将对应于NOT_SUPPORTED_TELEMETRY_CLIENT_DS_LIST和NOT_SUPPORTED_TELEMETRY_CLIENT_SUB_LIST,这是一个重叠的场景。
例4:键具有相同数量的元素和不同的类型(NOT Allowed case 3)
在给定的示例中,如果配置数据库有一个键为“1234”的 NOT_SUPPORTED_TELEMETRY_CLIENT 表,它将对应于 NOT_SUPPORTED_TELEMETRY_CLIENT_DS_LIST 和 NOT_SUPPORTED_TELEMETRY_CLIENT_SUB_LIST,这是一个重叠的场景。
......
container NOT_SUPPORTED_TELEMETRY_CLIENT {
list NOT_SUPPORTED_TELEMETRY_CLIENT_DS_LIST { // 1st list
key "prefix";
leaf prefix {
type string {
pattern ".*";
}
}
leaf dst_addr {
type ipv4-port;
}
}
list NOT_SUPPORTED_TELEMETRY_CLIENT_SUB_LIST { // Negative case
key "id";
leaf id {
type int32;
}
leaf dst_group {
must "(contains(../../TELEMETRY_CLIENT_DS_LIST/prefix, current()))";
type int32;
}
}
}
......
例5:键具有相同数量的元素和不同的类型(NOT Allowed case 4)
在给定的示例中,如果配置数据库有一个NOT_SUPPORTED_TELEMETRY_CLIENT表,键为“1234|1234”,它将对应于NOT_SUPPORTED_TELEMETRY_CLIENT_DS_LIST和NOT_SUPPORTED_TELEMETRY_CLIENT_SUB_LIST,这是一个重叠的场景。
......
container NOT_SUPPORTED_TELEMETRY_CLIENT {
list NOT_SUPPORTED_TELEMETRY_CLIENT_DS_LIST { // 1st list
key "prefix name";
leaf prefix {
type string;
}
leaf name {
type string;
}
leaf dst_addr {
type ipv4-port;
}
}
list NOT_SUPPORTED_TELEMETRY_CLIENT_SUB_LIST { // Negative case
key "id name";
leaf id {
type int32;
}
leaf name {
type int32;
}
leaf dst_group {
must "(contains(../../TELEMETRY_CLIENT_DS_LIST/prefix, current()))";
type int32;
}
}
}
......
19. 使用'config false'语句为状态数据添加只读节点。为状态数据定义一个单独的顶级容器。如果状态数据定义在其他DB中而不是CONFIG_DB,使用扩展'sonic-ext:db-name'来定义其他Redis DB中的表。表键中使用的默认分隔符是“|”,如果它不同,使用'sonic-ext:key-delim { separator} ;' YANG扩展。当SONiC YANG被用作北向YANG时,此步骤适用。
例子:
的
container ACL_RULE {
list ACL_RULE_LIST {
....
....
container state {
sonic-ext:db-name "APPL_DB"; //For example only
sonic-ext:key-delim ":"; //For example only
config false;
description "State data";
leaf MATCHED_PACKETS {
type yang:counter64;
}
leaf MATCHED_OCTETS {
type yang:counter64;
}
}
}
}
20.。定义自定义RPC来执行命令,如清除、重置等。通过这些RPC不应该改变配置。根据需要定义“input”和“output”,但它们是可选的。当SONiC YANG被用作北向YANG时,此步骤适用。
例子:
的
container sonic-acl {
....
....
rpc clear-stats {
input {
leaf aclname {
type string;
}
leaf rulename {
type string;
}
}
}
}
21. 定义Notification,用于发送系统中产生的事件,例如链接上/下或链接故障事件。此步骤适用于将SONiC YANG用作北向YANG时。
例子:
的
module sonic-port {
....
....
notification link_event {
leaf port {
type leafref {
path "../../PORT/PORT_LIST/ifname";
}
}
}
}
附录
样品:SONiC ACL YANG
module sonic-acl {
namespace "http://github.com/Azure/sonic-acl";
prefix sacl;
yang-version 1.1;
import ietf-yang-types {
prefix yang;
}
import ietf-inet-types {
prefix inet;
}
import sonic-common {
prefix scommon;
}
import sonic-port {
prefix prt;
}
import sonic-portchannel {
prefix spc;
}
import sonic-mirror-session {
prefix sms;
}
import sonic-pf-limits {
prefix spf;
}
organization
"SONiC";
contact
"SONiC";
description
"SONiC YANG ACL";
revision 2019-09-11 {
description
"Initial revision.";
}
container sonic-acl {
container ACL_TABLE {
list ACL_TABLE_LIST {
key "table_name";
leaf table_name {
type string;
}
leaf policy_desc {
type string {
length 1..255 {
error-app-tag policy-desc-invalid-length;
}
}
}
leaf stage {
type enumeration {
enum INGRESS;
enum EGRESS;
}
}
leaf type {
type enumeration {
enum MIRROR;
enum L2;
enum L3;
enum L3V6;
}
}
leaf-list ports {
type union {
type leafref {
path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname";
}
type leafref {
path "/spc:sonic-portchannel/spc:PORTCHANNEL/spc:PORTCHANNEL_LIST/spc:name";
}
}
}
}
}
container ACL_RULE {
list ACL_RULE_LIST {
key "table_name rule_name";
leaf table_name {
type leafref {
path "../../../ACL_TABLE/ACL_TABLE_LIST/table_name";
}
must "(/scommon:operation/scommon:operation != 'DELETE') or " +
"(current()/../../../ACL_TABLE/ACL_TABLE_LIST[table_name=current()]/type = 'L3')" {
error-message "Type not staisfied.";
}
}
leaf rule_name {
type string;
}
leaf PRIORITY {
type uint16 {
range "1..65535"{
error-message "Invalid ACL rule priority.";
}
}
}
leaf RULE_DESCRIPTION {
type string;
}
leaf PACKET_ACTION {
type enumeration {
enum FORWARD;
enum DROP;
enum REDIRECT;
}
}
leaf MIRROR_ACTION {
type leafref {
path "/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:MIRROR_SESSION_LIST/sms:name";
}
}
leaf IP_TYPE {
type enumeration {
enum ANY;
enum IP;
enum IPV4;
enum IPV4ANY;
enum NON_IPV4;
enum IPV6ANY;
enum NON_IPV6;
}
}
leaf IP_PROTOCOL {
type uint8 {
range "1|2|6|17|46|47|51|103|115";
}
}
leaf ETHER_TYPE {
type string {
pattern "(0x88CC)|(0x8100)|(0x8915)|(0x0806)|(0x0800)|(0x86DD)|(0x8847)" {
error-message "Invalid ACL Rule Ether Type";
error-app-tag ether-type-invalid;
}
}
}
choice ip_src_dst {
case ipv4_src_dst {
when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV4' or .='IPV4ANY'])";
leaf SRC_IP {
mandatory true;
type inet:ipv4-prefix;
}
leaf DST_IP {
mandatory true;
type inet:ipv4-prefix;
}
}
case ipv6_src_dst {
when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV6' or .='IPV6ANY'])";
leaf SRC_IPV6 {
mandatory true;
type inet:ipv6-prefix;
}
leaf DST_IPV6 {
mandatory true;
type inet:ipv6-prefix;
}
}
}
choice src_port {
case l4_src_port {
leaf L4_SRC_PORT {
type uint16;
}
}
case l4_src_port_range {
leaf L4_SRC_PORT_RANGE {
type string {
pattern "[0-9]{1,5}(-)[0-9]{1,5}";
}
}
}
}
choice dst_port {
case l4_dst_port {
leaf L4_DST_PORT {
type uint16;
}
}
case l4_dst_port_range {
leaf L4_DST_PORT_RANGE {
type string {
pattern "[0-9]{1,5}(-)[0-9]{1,5}";
}
}
}
}
leaf TCP_FLAGS {
type string {
pattern "0[xX][0-9a-fA-F]{2}[/]0[xX][0-9a-fA-F]{2}";
}
}
leaf DSCP {
type uint8;
}
}
}
}
}