早在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 模块有如下的布局:
module <module-name> {
//==== header information ====
yang-version statement
namespace statement
prefix statement
//==== linkage statements ====
import statements
include statements
//==== meta information ====
organization statement
contact statement
description statement
reference statement
//==== revision history ====
revision statements
//==== module definitions ====
other statements
}
对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 :
leaf host-name {
type string;
description "Hostname for this system";
}
NETCONF XML :
<host-name>my.example.com</host-name>
Leaf-List
leaf-list定义一组相同类型的叶节节点,类似于数组,与leaf区别在于leaf只有一个实例,而leaf-list可以有多个实例,其元素的值type必须保持一致,而且不能重复。
YANG :
leaf-list domain-search {
type string;
description "List of domain names to search";
}
NETCONF XML :
<domain-search>a.example.com</domain-search>
<domain-search>b.example.com</domain-search>
<domain-search>c.example.com</domain-search>
list
list描述了一组节点的集合,它像一张数据库表一样,表的每一行用key来标识其主键,有多个实例。
YANG :
list user {
key "name";
leaf name {
type string;
}
leaf sex {
type string;
}
leaf class {
type uint8;
}
}
NETCONF XML :
<user>
<name>zhang</name>
<sex>male</sex>
<class>1</class>
</user>
<user>
<name>wang</name>
<sex>male</sex>
<class>2</class>
</user>
<user>
<name>zhou</name>
<sex>famale</sex>
<class>2</class>
</user>
grouping
grouping定义一个可以重复使用的节点集合,使用时通过use语句,并可通过refine语句进行改进。
container
container主要定义一个schema树的内部节点,它本身没有任何值和意义,只是作为一系列子节点的父亲存在,只有一个实例。
YANG :
container system {
leaf host-name {
type string;
description "Hostname for this system";
}
leaf-list domain-search {
type string;
description "List of domain names to search";
}
container login {
leaf message {
type string;
description
"Message given at start of login session";
}
list user {
key "name";
leaf name {
type string;
}
leaf full-name {
type string;
}
leaf class {
type string;
}
}
}
}
NETCONF XML :
<system>
<host-name>myyang.com</host-name>
<domain-search>high.example.com</domain-search>
<domain-search>low.example.com</domain-search>
<domain-search>everywhere.example.com</domain-search>
<login>
<message>Good Morning</message>
<user>
<name>glocks</name>
<full-name>Goldie Locks</full-name>
<class>intruder</class>
</user>
<user>
<name>snowey</name>
<full-name>Snow White</full-name>
<class>free-loader</class>
</user>
<user>
<name>rzell</name>
<full-name>Rapun Zell</full-name>
<class>tower</class>
</user>
</login>
</system>
choice
choice节点定义了一个可供选择项的集合,每一个选择项都会在某种情况下存在。一个choice由许多分枝,通过case子语句定义。YANG能够使用“choice”和“case”声明分离互不相容,不能同时出现的节点。“choice”声明包含了多个“case”声明,定义了不能同时出现的schema nodes的集合。每个“case”声明都可能包含多个节点,但是每个节点都应该只在一个“case”中出现。当一个case元素被创建,其他所有cases的元素都会被隐式删除。设备要强制执行这个约束,以防止出现配置的不协调。
YANG :
list pet{
choice animal {
case cat {
leaf name {
type empty;
}
}
case dog {
leaf color {
type empty;
}
}
}
}
NETCONF XML :
<pet>
<cat/>
</pet>
<pet>
<cat/>
</pet>
<pet>
<dog/>
</pet>
enum
typedef <type-name> {
type enumeration {
enum "Single" {
value 0;
description "Single Device.";
}
enum "Group" {
value 1;
description "Device Group.";
}
}
}
anyxml
anyxml表示任何未知的数据定义。
augment
yang提供augment语句,扩大一个模块层次,将节点添加到一个已存在的模块或子模块当中。目标结点可以是一个container, list, choice, case, rpc, input, output, notification等。augment可以是条件的,使用when语句,当特定条件满足时,新节点才会出现。
YANG :
//----------- in namespace http://example.com/schema/interfaces ----------------------------
container interfaces {
list ifEntry {
key "ifIndex";
leaf ifIndex {
type uint32;
}
leaf ifDescr {
type string;
}
leaf ifType {
type iana:IfType;
}
leaf ifMtu {
type int32;
}
}
}
//----------- in namespace http://example.com/schema/ds0 ----------------------------
import interface-module {
prefix "if";
}
augment "/if:interfaces/if:ifEntry" {
when "if:ifType='ds0'";
leaf ds0ChannelNumber {
type uint32;
}
}
NETCONF XML :
<interfaces xmlns="http://example.com/schema/interfaces"
xmlns:ds0="http://example.com/schema/ds0">
<ifEntry>
<ifIndex>1</ifIndex>
<ifDescr>Flintstone Inc Ethernet A562</ifDescr>
<ifType>ethernetCsmacd</ifType>
<ifMtu>1500</ifMtu>
</ifEntry>
<ifEntry>
<ifIndex>2</ifIndex>
<ifDescr>Flintstone Inc DS0</ifDescr>
<ifType>ds0</ifType>
<ifMtu>1500</ifMtu>
<ds0:ds0ChannelNumber>1</ds0:ds0ChannelNumber>
</ifEntry>
</interfaces>
notification
notification语句用来定义Notification内容,内容数据的定义同yang数据定义一样。
rpc
rpc语句用来定义NETCONF协议的RPCs,input和output使用yang数据定义语句。
YANG :
rpc activate-software-image {
input {
leaf image-name {
type string;
}
}
output {
leaf status {
type string;
}
}
}
NETCONF XML :
<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<activate-software-image xmlns="http://acme.example.com/system">
<image-name>acmefw-2.3</image-name>
</activate-software-image>
</rpc>
<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<status xmlns="http://acme.example.com/system">
The image acmefw-2.3 is being installed.
</status>
</rpc-reply>
Notification
Notification是一种通告机制,当交换机上出现特性event(事件),交换机会主动发给已经建立netconf连接并订阅了Notification的client。YANG可以定义notification。
YANG :
notification link-failure {
description "A link failure has been detected";
leaf if-name {
type leafref {
path "/interface/name";
}
}
leaf if-admin-status {
type admin-status;
}
leaf if-oper-status {
type oper-status;
}
}
NETCONF XML :
<notification xmlns="urn:ietf:params:netconf:capability:notification:1.0">
<eventTime>2007-09-01T10:00:00Z</eventTime>
<link-failure xmlns="http://acme.example.com/system">
<if-name>so-1/2/3.0</if-name>
<if-admin-status>up</if-admin-status>
<if-oper-status>down</if-oper-status>
</link-failure>
</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 |