YANG语言标准中文 RFC6020 简书 sdnlab

早在2003年,IETF成立了一个NETCONF工作组,提出一种基于XML的网络配置管理协议,也就是NETCONF(Network Configuration Protocol),因为该协议的配置功能非常强大,同时兼顾监控和故障管理,安全验证和访问控制,所以得到业界的一致认可,所以广泛采用netconfig来配置网络。NETCONF协议分为传输层、RPC层、操作层和内容层。其中,内容层是唯一没有标准化的层,于是一种新的建模语言yang产生了,它的目标是对NETCONF数据模型、操作进行建模,覆盖NETCONF协议的操作层和内容层。

数据节点

module

module是yang的基本单元,是写yang文件的基本框架,包括以下几种类型语句:

  • head语句(yang-version/namespace/prefix)
  • 连接语句(import/include)
  • 元信息(organization/contract)
  • revision语句
  • 定义语句(container/leaf/leaf-list/grouping等等)

yang 模块有如下的布局:

  1. module <module-name> {
  2. //==== header information ====
  3. yang-version statement
  4. namespace statement
  5. prefix statement
  6. //==== linkage statements ====
  7. import statements
  8. include statements
  9. //==== meta information ====
  10. organization statement
  11. contact statement
  12. description statement
  13. reference statement
  14. //==== revision history ====
  15. revision statements
  16. //==== module definitions ====
  17. other statements
  18. }

对YANG module的解读:

  • module的名字是acme-system
  • namespace是用来唯一标识这个YANG模型与其它YANG模型不同
  • prefix是namespace的一种简写
  • organization/contact/description都是用来描述相关信息
  • revison描述版本信息,可以有多个revision(一般记录版本更新的内容)
  • module中包含一个container system
  • container system包含一个leaf(host-name),一个leaf-list(domain-search)和一个container login
  • container login包含一个leaf(message),和一个list(user)

Leaf

leaf定义的节点只有一个值,是一个叶子节点,只能有一个实例。

YANG :

  1. leaf host-name {
  2. type string;
  3. description "Hostname for this system";
  4. }

NETCONF XML :

  1. <host-name>my.example.com</host-name>

Leaf-List

leaf-list定义一组相同类型的叶节节点,类似于数组,与leaf区别在于leaf只有一个实例,而leaf-list可以有多个实例,其元素的值type必须保持一致,而且不能重复。

YANG :

  1. leaf-list domain-search {
  2. type string;
  3. description "List of domain names to search";
  4. }

NETCONF XML :

  1. <domain-search>a.example.com</domain-search>
  2. <domain-search>b.example.com</domain-search>
  3. <domain-search>c.example.com</domain-search>

list

list描述了一组节点的集合,它像一张数据库表一样,表的每一行用key来标识其主键,有多个实例。

YANG :

  1. list user {
  2. key "name";
  3. leaf name {
  4. type string;
  5. }
  6. leaf sex {
  7. type string;
  8. }
  9. leaf class {
  10. type uint8;
  11. }
  12. }

NETCONF XML :

  1. <user>
  2. <name>zhang</name>
  3. <sex>male</sex>
  4. <class>1</class>
  5. </user>
  6. <user>
  7. <name>wang</name>
  8. <sex>male</sex>
  9. <class>2</class>
  10. </user>
  11. <user>
  12. <name>zhou</name>
  13. <sex>famale</sex>
  14. <class>2</class>
  15. </user>

grouping

grouping定义一个可以重复使用的节点集合,使用时通过use语句,并可通过refine语句进行改进。

container

container主要定义一个schema树的内部节点,它本身没有任何值和意义,只是作为一系列子节点的父亲存在,只有一个实例。

YANG :

  1. container system {
  2. leaf host-name {
  3. type string;
  4. description "Hostname for this system";
  5. }
  6. leaf-list domain-search {
  7. type string;
  8. description "List of domain names to search";
  9. }
  10. container login {
  11. leaf message {
  12. type string;
  13. description
  14. "Message given at start of login session";
  15. }
  16. list user {
  17. key "name";
  18. leaf name {
  19. type string;
  20. }
  21. leaf full-name {
  22. type string;
  23. }
  24. leaf class {
  25. type string;
  26. }
  27. }
  28. }
  29. }

NETCONF XML :

  1. <system>
  2. <host-name>myyang.com</host-name>
  3. <domain-search>high.example.com</domain-search>
  4. <domain-search>low.example.com</domain-search>
  5. <domain-search>everywhere.example.com</domain-search>
  6. <login>
  7. <message>Good Morning</message>
  8. <user>
  9. <name>glocks</name>
  10. <full-name>Goldie Locks</full-name>
  11. <class>intruder</class>
  12. </user>
  13. <user>
  14. <name>snowey</name>
  15. <full-name>Snow White</full-name>
  16. <class>free-loader</class>
  17. </user>
  18. <user>
  19. <name>rzell</name>
  20. <full-name>Rapun Zell</full-name>
  21. <class>tower</class>
  22. </user>
  23. </login>
  24. </system>

choice

https://tools.ietf.org/html/rfc6020#section-7.9

choice节点定义了一个可供选择项的集合,每一个选择项都会在某种情况下存在。一个choice由许多分枝,通过case子语句定义。YANG能够使用“choice”和“case”声明分离互不相容,不能同时出现的节点。“choice”声明包含了多个“case”声明,定义了不能同时出现的schema nodes的集合。每个“case”声明都可能包含多个节点,但是每个节点都应该只在一个“case”中出现。当一个case元素被创建,其他所有cases的元素都会被隐式删除。设备要强制执行这个约束,以防止出现配置的不协调。

YANG :

  1. list pet{
  2. choice animal {
  3. case cat {
  4. leaf name {
  5. type empty;
  6. }
  7. }
  8. case dog {
  9. leaf color {
  10. type empty;
  11. }
  12. }
  13. }
  14. }

NETCONF XML :

  1. <pet>
  2. <cat/>
  3. </pet>
  4. <pet>
  5. <cat/>
  6. </pet>
  7. <pet>
  8. <dog/>
  9. </pet>

enum

  1. typedef <type-name> {
  2. type enumeration {
  3. enum "Single" {
  4. value 0;
  5. description "Single Device.";
  6. }
  7. enum "Group" {
  8. value 1;
  9. description "Device Group.";
  10. }
  11. }
  12. }

anyxml

anyxml表示任何未知的数据定义。

augment

https://tools.ietf.org/html/rfc6020#section-7.15

yang提供augment语句,扩大一个模块层次,将节点添加到一个已存在的模块或子模块当中。目标结点可以是一个container, list, choice, case, rpc, input, output, notification等。augment可以是条件的,使用when语句,当特定条件满足时,新节点才会出现。

YANG :

  1. //----------- in namespace http://example.com/schema/interfaces ----------------------------
  2. container interfaces {
  3. list ifEntry {
  4. key "ifIndex";
  5. leaf ifIndex {
  6. type uint32;
  7. }
  8. leaf ifDescr {
  9. type string;
  10. }
  11. leaf ifType {
  12. type iana:IfType;
  13. }
  14. leaf ifMtu {
  15. type int32;
  16. }
  17. }
  18. }
  19. //----------- in namespace http://example.com/schema/ds0 ----------------------------
  20. import interface-module {
  21. prefix "if";
  22. }
  23. augment "/if:interfaces/if:ifEntry" {
  24. when "if:ifType='ds0'";
  25. leaf ds0ChannelNumber {
  26. type uint32;
  27. }
  28. }

NETCONF XML :

  1. <interfaces xmlns="http://example.com/schema/interfaces"
  2. xmlns:ds0="http://example.com/schema/ds0">
  3. <ifEntry>
  4. <ifIndex>1</ifIndex>
  5. <ifDescr>Flintstone Inc Ethernet A562</ifDescr>
  6. <ifType>ethernetCsmacd</ifType>
  7. <ifMtu>1500</ifMtu>
  8. </ifEntry>
  9. <ifEntry>
  10. <ifIndex>2</ifIndex>
  11. <ifDescr>Flintstone Inc DS0</ifDescr>
  12. <ifType>ds0</ifType>
  13. <ifMtu>1500</ifMtu>
  14. <ds0:ds0ChannelNumber>1</ds0:ds0ChannelNumber>
  15. </ifEntry>
  16. </interfaces>

notification

notification语句用来定义Notification内容,内容数据的定义同yang数据定义一样。

rpc

rpc语句用来定义NETCONF协议的RPCs,input和output使用yang数据定义语句。

YANG :

  1. rpc activate-software-image {
  2. input {
  3. leaf image-name {
  4. type string;
  5. }
  6. }
  7. output {
  8. leaf status {
  9. type string;
  10. }
  11. }
  12. }

NETCONF XML :

  1. <rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  2. <activate-software-image xmlns="http://acme.example.com/system">
  3. <image-name>acmefw-2.3</image-name>
  4. </activate-software-image>
  5. </rpc>
  6. <rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  7. <status xmlns="http://acme.example.com/system">
  8. The image acmefw-2.3 is being installed.
  9. </status>
  10. </rpc-reply>

Notification

Notification是一种通告机制,当交换机上出现特性event(事件),交换机会主动发给已经建立netconf连接并订阅了Notification的client。YANG可以定义notification。

YANG :

  1. notification link-failure {
  2. description "A link failure has been detected";
  3. leaf if-name {
  4. type leafref {
  5. path "/interface/name";
  6. }
  7. }
  8. leaf if-admin-status {
  9. type admin-status;
  10. }
  11. leaf if-oper-status {
  12. type oper-status;
  13. }
  14. }

NETCONF XML :

  1. <notification xmlns="urn:ietf:params:netconf:capability:notification:1.0">
  2. <eventTime>2007-09-01T10:00:00Z</eventTime>
  3. <link-failure xmlns="http://acme.example.com/system">
  4. <if-name>so-1/2/3.0</if-name>
  5. <if-admin-status>up</if-admin-status>
  6. <if-oper-status>down</if-oper-status>
  7. </link-failure>
  8. </notification>

这样无论是接口的admin状态(shutdown或是no shutdonw),还是链路状态(down/up)发送改变的时候,都可以发送notification给client,并且带上了当前的状态信息。

数据类型

Name Description
binary Any binary data
bits A set of bits or flags
boolean “true” or “false”
decimal64 64-bit signed decimal number
empty A leaf that does not have any value
enumeration Enumerated strings
identityref A reference to an abstract identity
instance-identifier References a data tree node
int8 8-bit signed integer
int16 16-bit signed integer
int32 32-bit signed integer
int64 64-bit signed integer
leafref A reference to a leaf instance
string Human-readable string
uint8 8-bit unsigned integer
uint16 16-bit unsigned integer
uint32 32-bit unsigned integer
uint64 64-bit unsigned integer
union Choice of member types