OpenDaylight — YANG
1. 介绍
YANG 是一种用于为 NETCONF 协议建模数据的语言。
YANG 将数据的层次结构建模为一棵树。
2. 节点类型
2.1 leaf
它只有一个特定类型的值,并且没有子节点。
YANG EXAMPLE:
leaf host-name {
type string;
description "Hostname for this system";
}
NETCONF XML Example:
<host-name>my.example.com</host-name>
2.2 leaf-list
就是一系列的 leaf 节点。
YANG EXAMPLE:
leaf-list domain-search {
type string;
description "List of domain names to search";
}
NETCONF XML Example:
<domain-search>high.example.com</domain-search>
<domain-search>low.example.com</domain-search>
<domain-search>everywhere.example.com</domain-search>
2.3 container
将相关的节点组成一棵子树。
它只有子节点,而没有值。
一个 container 节点可以包含任意数量的任意类型的子节点(包括 container)。
YANG EXAMPLE:
container system {
container login {
leaf message {
type string;
description "Message given at start of login session";
}
}
}
NETCONF XML Example:
<system>
<login>
<message>Good morning</message>
</login>
</system>
2.4 list
list 定义了一系列的列表条目。每个条目类似于一个结构实例,并由其 key leaf 的 key 唯一标识。
list 可以定义多个 key leaf,并且可以包含任意数量的任何类型的子节点(包括 list)。
YANG EXAMPLE:
list user {
key "name";
leaf name {
type string;
}
leaf full-name {
type string;
}
leaf class {
type string;
}
}
NETCONF XML Example:
<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>
3. 数据类型
3.1 内建类型
| 类型 | 描述 |
| 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 |
3.1.1 bit和bits
bit 语句用于每个比特位指定一个名字。
bit 语句的 position 子句指定要使用的比特位的位置。
leaf mybits {
type bits {
bit disable-nagle {
position 0;
}
bit auto-sense-speed {
position 1;
}
bit 10-Mb-only {
position 2;
}
}
default "auto-sense-speed";
}
<mybits>disable-nagle 10-Mb-only</mybits>
3.1.2 数字类型和range
使用 decimal64 类型时,必须使用 fraction-digits 来指定要精确到小数点后几位(1~18)。
可以使用 range 语句来限定数字类型有效的取值范围。
typedef my-base-int32-type {
type int32 {
range "1..4 | 10..20";
}
}
typedef my-type1 {
type my-base-int32-type {
range "11..max"; // 11..20
}
}
typedef my-decimal {
type decimal64 {
fraction-digits 2;
range "1 .. 3.14 | 10 | 20..max";
}
}
3.1.3 enum和enumeration
enum 语句用于指定可选的枚举值。
可以使用 enum 语句的 value 子句为枚举值指定一个整数。
leaf myenum {
type enumeration {
enum zero;
enum one;
enum seven {
value 7;
}
}
}
<myenum>seven</myenum>
3.1.4 identity和identityref
identity 语句用于定义一个全局唯一的、抽象的、没有标注类型的 identity。其目的是定义一个名称、语义。
可以使用 base 子句来派生一个已有的 identity:
module crypto-base {
namespace "http://example.com/crypto-base";
prefix "crypto";
identity crypto-alg {
description
"Base identity from which all crypto algorithms are derived.";
}
}
module des {
namespace "http://example.com/des";
prefix "des";
import "crypto-base" {
prefix "crypto";
}
identity des {
base "crypto:crypto-alg";
description "DES crypto algorithm";
}
identity des3 {
base "crypto:crypto-alg";
description "Triple DES crypto algorithm";
}
}
identityref 用于引用一个已经存在的 identify。
该类型有效的值是:任何派生自指定 identity 的 identities。
module my-crypto {
namespace "http://example.com/my-crypto";
prefix mc;
import "crypto-base" {
prefix "crypto";
}
identity aes {
base "crypto:crypto-alg";
}
leaf crypto {
type identityref {
base "crypto:crypto-alg";
}
}
}
<crypto xmlns:des="http://example.com/des">des:des3</crypto>
3.1.5 instance-identifier
用于唯一标识数据树中的某个节点实例。
使用 XPath 语法。

module example {
namespace "ii:example";
prefix "ex";
container system {
description "Contains various system parameters";
container services {
description "Configure externally available services";
container "ssh" {
leaf port {
type uint16;
}
leaf-list cipher {
type string;
ordered-by user;
description "A list of ciphers";
}
}
}
list server {
key "name";
unique "ip port";
leaf name {
type string;
}
leaf ip {
type inet:ip-address;
}
leaf port {
type inet:port-number;
}
}
list user {
key "name";
config true;
description "This is a list of users in the system.";
leaf name {
type string;
}
leaf type {
type string;
}
leaf full-name {
type string;
}
}
container stats {
list ports {
leaf port-number {
type uint16;
}
leaf port-status {
type uint16;
}
}
}
}
}
/* instance-identifier for a container */
/ex:system/ex:services/ex:ssh /* instance-identifier for a leaf */
/ex:system/ex:services/ex:ssh/ex:port /* instance-identifier for a list entry */
/ex:system/ex:user[ex:name='fred'] /* instance-identifier for a leaf in a list entry */
/ex:system/ex:user[ex:name='fred']/ex:type /* instance-identifier for a list entry with two keys */
/ex:system/ex:server[ex:ip='192.0.2.1'][ex:port='80'] /* instance-identifier for a leaf-list entry */
/ex:system/ex:services/ex:ssh/ex:cipher[.='blowfish-cbc'] /* instance-identifier for a list entry without keys */
/ex:stats/ex:port[3]
3.1.6 leafref
用于引用数据树中的某个 leaf 实例。
使用 type 语句的 path 子句指定要引用哪个 leaf。
list interface {
key "name";
leaf name {
type string;
}
leaf admin-status {
type admin-status;
}
list address {
key "ip";
leaf ip {
type yang:ip-address;
}
}
}
leaf mgmt-interface {
type leafref {
path "../interface/name";
}
}
3.1.7 string
可以使用 length 子句来限定字符串的字符个数。
typedef my-base-str-type {
type string {
length "1..255";
}
}
type my-base-str-type {
// legal length refinement
length "11 | 42..max"; // 11 | 42..255
}
可以使用 pattern 子句来限定字符串必须匹配的模式。
type string {
length "0..4";
pattern "[0-9a-fA-F]*";
}
3.1.8 union
类似于 C 语言中的 union,一次只有一个成员有效。
type union {
type int32;
type enumeration {
enum "unbounded";
}
}
3.2 派生类型
从基类型派生出新的类型。基类型可以是内建类型,也可以是另一个派生类型。
派生类型使用 typedef 语句定义;typedef 的 type 子句定义了该派生类型的基类型,default 子句定义了该类型的默认值。
YANG EXAMPLE:
typedef percent {
type uint8 {
range "0 .. 100";
}
default 0;
description "Percentage";
}
leaf completed {
type percent;
}
NETCONF XML Example:
<completed>20</completed>
4. 重用节点
使用 grouping 定义一个节点组,使用 use 实例化节点。
YANG EXAMPLE:
grouping target {
leaf address {
type inet:ip-address;
description "Target IP address";
}
leaf port {
type inet:port-number;
description "Target port number";
}
}
container peer {
container destination {
uses target;
}
}
NETCONF XML Example:
<peer>
<destination>
<address>192.0.2.1</address>
<port>830</port>
</destination>
</peer>
在 use 节点组的时候,可以对节点进行 refine:
container connection {
container source {
uses target {
refine "address" {
description "Source IP address";
}
refine "port" {
description "Source port number";
}
}
}
container destination {
uses target {
refine "address" {
description "Destination IP address";
}
refine "port" {
description "Destination port number";
}
}
}
}
5. choice...case
一个 choice 语句包含多个 case 子句。
当某个 case 被选中时,其他 case 中的节点将被移除。
YANG EXAMPLE:
container food {
choice snack {
case sports-arena {
leaf pretzel {
type empty;
}
leaf beer {
type empty;
}
}
case late-night {
leaf chocolate {
type enumeration {
enum dark;
enum milk;
enum first-available;
}
}
}
}
}
NETCONF XML Example:
<food>
<pretzel/>
<beer/>
</food>
6. 状态数据和配置数据
当一个节点包含 config false 语句时,其子层级结构将被标记为状态数据。
状态数据不可编辑。
list interface {
key "name";
leaf name {
type string;
}
leaf speed {
type enumeration {
enum 10m;
enum 100m;
enum auto;
}
}
leaf observed-speed {
type uint32;
config false;
}
}
7. 扩展数据模型
augment 定义了在数据模型层级结构的哪个地方插入新节点;
when 定义了新节点在什么条件下有效。
YANG EXAMPLE:
augment /system/login/user {
when "class != 'wheel'";
leaf uid {
type uint16 {
range "1000 .. 30000";
}
}
}
NETCONF XML Example:
<user>
<name>alicew</name>
<full-name>Alice N. Wonderland</full-name>
<class>drop-out</class>
<other:uid>1024</other:uid>
</user>
8. RPC 定义
定义操作名称、输入参数和输出参数。
YANG EXAMPLE:
rpc activate-software-image {
input {
leaf image-name {
type string;
}
}
output {
leaf status {
type string;
}
}
}
NETCONF XML Example:
<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>
9. 通知定义
YANG EXAMPLE:
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 Example:
<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>
10. 模块和子模块
一个 module 定义了一个数据模型。一个 module 可以包含多个 submodule,一个 submodule 必须属于某个 module。
一个 module/submodule 可以使用 include 语句包含其他 submodule,使用 import 语句引用外部 module。
import 和 include 的另一个区别如下:
- module A import 了 module B,当 B 更新时,A 不受影响;
- module A include 了 submodule SB,当 SB 更新时,A 也会相应地更新。
module 的 prefix 语句定义了访问该 module 所使用的前缀:prefix:module。
import 语句的 prefix 子句指定了使用导入模块时所需使用的前缀。
module acme-system {
namespace "http://acme.example.com/system";
prefix "acme";
import ietf-yang-types {
prefix "yang";
}
include acme-types;
organization "ACME Inc.";
contact
"Joe L. User
ACME, Inc.
42 Anywhere Drive
Nowhere, CA 95134
USA
Phone: +1 800 555 0100
EMail: joe@acme.example.com";
description
"The module for entities implementing the ACME protocol.";
revision "2007-06-09" {
description "Initial revision.";
}
// definitions follow...
}
submodule 使用 belongs-to 语句来说明该 submodule 属于哪个 module。belongs-to 语句的 prefix 子句指定了使用该 submodule 时所需使用的前缀。
submodule acme-types {
belongs-to "acme-system" {
prefix "acme";
}
import ietf-yang-types {
prefix "yang";
}
organization "ACME Inc.";
contact
"Joe L. User
ACME, Inc.
42 Anywhere Drive
Nowhere, CA 95134
USA
Phone: +1 800 555 0100
EMail: joe@acme.example.com";
description "This submodule defines common ACME types.";
revision "2007-06-09" {
description "Initial revision.";
}
// definitions follows...
}
参考资料
https://tools.ietf.org/html/rfc6020
OpenDaylight — YANG的更多相关文章
- OpenDayLight——HelloWorld
OpenDayLight——HelloWorld 既然学习OpenDayLight编程这个鬼,就得像学语言一样来一个HelloWorld来试试水,经过几天的折腾,总算成功输出HelloWorld了,这 ...
- OpenDaylight开发hello-world项目之功能实现
OpenDaylight开发hello-world项目之开发环境搭建 OpenDaylight开发hello-world项目之开发工具安装 OpenDaylight开发hello-world项目之代码 ...
- 在OpenDaylight controller上开发App
安装环境:Ubuntu18.04 一.安装依赖 1. 安装JDK: sudo apt update sudo apt install openjdk-8-jdk-headless 选择默认的 JDK: ...
- YangTools从YANG生成Java类(Maven)
1.说明 ODL提供了Yang Tools工具从YANG文件生成Java类, 本文介绍使用Maven插件的方式生成, 基于yang-maven-plugin这个插件. 2.创建Maven工程 Ecli ...
- 在odl中怎样实现rpc
opendaylight作为sdn主要开源项目,採用osgi框架.已经得到非常多厂商的支持.氦版本号也公布在即. 以下介绍一下在odl中怎样实现rpc. odl使用yang作为model模型定义文件. ...
- 基于OpenDaylight和Mininet的试验床平台搭建
##########################################平台架构######################################### 一.虚拟机安装和镜像加载 ...
- OpenDaylight即将迈入“七年之痒”?
前段时间看到一篇文章,叫<OpenStack已死?>,讲述了OpenStack自2010年提出之后的9年间各方利益牵扯导致的一系列问题,尽管最终作者的结论是OpenStack现在只是进入了 ...
- OpenDaylight开发hello-world项目之代码框架搭建
OpenDaylight开发hello-world项目之开发环境搭建 OpenDaylight开发hello-world项目之开发工具安装 OpenDaylight开发hello-world项目之代码 ...
- OpenDayLight Beryllium版本 下发流表实现hardtimeout
1. 实验拓扑 2. 创建拓扑 from mininet.topo import Topo class MyTopo(Topo): def __init__(self): # initilaize t ...
随机推荐
- C++libcurl的使用
一.libcurl描述: 在curl的官方网站 **http://curl.haxx.se/download.html** 提供编译好libcurl包, 最后写一个demod工程,演示下libcur ...
- [实用指南]如何使您的旧代码库(遗留代码)符合MISRA C 2012编码规范?
重用旧代码是现实,但是在安全关键型软件项目中重用旧代码并实现MISRA C 2012的完全合规性是艰巨的任务. 最初的MISRA原则是为了在开发代码时应用而创建的,即使文档本身也有警告: " ...
- HttpApplication执行顺序
类的实例(Global继承自该类)是在 ASP.NET 基础结构中创建的,而不是由用户直接创建的.HttpApplication 类的一个实例在其生存期内被用于处理多个请求,但它一次只能处理一个请求. ...
- 机器学习-决策树之ID3算法
概述 决策树(Decision Tree)是一种非参数的有监督学习方法,它是一种树形结构,所以叫决策树.它能够从一系列有特征和标签的数据中总结出决策规则,并用树状图的结构来呈现这些规则,以解决分类和回 ...
- linux不同环境变量文件的比较,如/etc/profile和/etc/environment
/etc/profile 为系统的每个用户设置环境信息和启动程序,当用户第一次登录时,该文件被执行,其配置对所有登录的用户都有效. 当被修改时,必须重启才会生效.英文描述:"System w ...
- 解决 Idea 下 Lombok 无法使用
解决: 第一步,项目导入 Lombok 依赖 <dependency> <groupId>org.projectlombok</groupId> <ar ...
- CentOS Linux SVN服务器 配置用户目录访问 权限 Authorization failed
SVN 修改 aurhz 文件设置用户目录访问权限格式: [/code] user=rw user 用户对code目录拥有读和写的权限. 但是访问 svn://192.168.1.59 的时候却提示A ...
- 什么是Redis?
Remote Dictionary Server(Redis)是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value 数据库,并提供多种语言的API.它通常被 ...
- python 虾米停服了...用python爬取虾米最近播放的1000首歌
1. 虾米关服 在这里插入图片描述 用了5年多的音乐软件就这么说关就关了,确实让人心里不好受 ,虽然再去一个新的app里,让它们的算法熟悉你的喜好也不是很困难,可我还是习惯虾米的界面.虾米现在可以支持 ...
- python函数----名称空间和作用域
一 名称空间 名称空间即存放名字与对象映射/绑定关系的地方. 对于x=3,Python会申请内存空间存放对象3,然后将名字x与3的绑定关系存放于名称空间中,del x表示清除该绑定关系. 在程序执行 ...