SONIC标准YANG编写指南

修订

牧师日期作者改变的描述
1.08月22日Praveen Chaudhary初始版本
1.09月11日帕塔·杜塔(Partha Dutta)为SONiC YANG添加额外的步骤
1.12023年12月15日谢Jingwen为 List Keys 添加规则

参考文献。

参考文献。日期/版本链接
RFC 79502016年8月RFC 7950 - The YANG 1.1 Data Modeling Language
管理框架0.9#436

术语和缩写

首字母缩略词描述/扩展
ABNF公司增广巴克斯-诺尔式
XPathXML路径语言
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;
				}
			}
		}
	}
}
  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值