ORAN专题系列-17:5G O-RAN FrontHaul前传接口的网络配置管理与Yang数据建模语言

前言:

程序=数据结构+算法,任何程序基本上都是解决这两个问题。

数据结构是指相互之间存在一种或多种特定关系的数据元素的集合,是计算机存储、组织数据元素的方式。

大多数的编程语言,如C, C++, Java,phython都提供了对数据的描述性语法,用于定义特定数据结构的数据。如C/C++语言的基础数据类型、struct结构体数据类型、union联合体数据类型、array数组类型类型,并通过这些预定义的数据类型,表达和定义更加复杂的数据类型,如链表、树、堆栈、hash表。

然后,对于程序而言,这些数据结构都是事先定义好的,当这些数据结构发生改变时,相应的数据处理的程序需要重新编译。

这是一种算法与数据结构是一种强绑定关系的编程语言。

有没有一种编程语言,对数据的描述,可以脱离算法程序,可以单纯的定义或表达数据的结构呢?

Yang数据建模语言,就是这样的一种数据描述性语言,

它通过文本的方式表达和描述数据的数据结构,

通过xml文本的方式来承载对数据结构的表述。

并且能够对Yang建模后的数据结构进行实例化,定义特定的数据类型的数据。

NetConf就是使用Yang语言对内容子层的数据进行约束和建模的。


Table of Contents

第一章 YANG概述

第二章 YANG语言的主要语法要素

2.1 模块和子模块

2.2 树形节点的类型

2.3 数据的配置和状态属性(Configuration and State Data)

2.4 内置的基本数据类型

2.5 派生类型(typedef)(Derived Types (typedef))

2.6 可重复使用的节点组(分组)(Reusable Node Groups (grouping))

2.7 选择(Choices):

2.8 扩展数据模型(扩充)(Extending Data Models (augment))

2.9 “操作”定义

4.10 通知定义

参考:


第一章 YANG概述

YANG是最初设计用于为NETCONF协议的内容子层的数据​​建模

YANG定义了可用于基于NETCONF的操作(包括配置,状态数据,RPC和通知)的数据层次结构。这允许在NETCONF客户端和服务器之间发送的所有数据的完整描述。当然YANG也可以使用除NETCONF以外的协议。

YANG将数据进行模型化结构化,它把某一个系统的所有数据组成为一棵树。

树上的每个节点都有一个名称:其值或者一个叶子节点的数值或一组子节点。YANG提供了对节点的清晰简洁的描述,以及这些节点之间的交互。

为了更加有效的组织大型数据YANG还将整个系统的数据模型,进行了进一步的分解,分解成模块和子模块。

模块可以从其他外部模块导入定义,并可以包含子模块的定义。可以增加层次结构,允许一个模块将数据节点添加到另一个模块中定义的层次结构中。这种增加可以是有条件的,只有在满足某些条件的情况下才会出现新的节点。

类似通过Python编程语言,可以实现逻辑的编程,通过YANG数据建模语言,可以实现对数据的建模或编程。

YANG主要功能包括:

(1)数据结构建模

  • 对一组相关性的数据的数据结构进行描述。C语言中称为定义数据结构,C++中称为定义类Class。
  • 对数据的约束条件进行描述:比如数据值的范围、数据的默认值等。这些约束可以由客户端或服务器强制执行。

(2)实例化数据

  • 定义数据结构的对应的数据的实例,C语言中称为变量定义,C++中称为对象的实例化。

YANG定义了一组内置的类型,通过内置的基础数据类型可以定义更加复杂的数据类型。

YANG是一个可扩展的语言,允许标准组织,供应商和个人对其进行扩展。

总之,

(1)YANG首先是一门编程语言

(2)对数据,而不是程序逻辑进行编程

(3)实现代码逻辑与数据描述的分离


第二章 YANG语言的主要语法要素

2.1 模块和子模块

这是组织大型数据的工程化手段。

YANG数据模型在模块Module中定义,类似Python的模块。一个模块包含相关数据模型定义的集合。

一个模块包含三种类型的语句:

(1)模块头(module header)语句:模块头部语句描述模块并提供关于模块本身的信息,

(2)“修订”(revision)语句:提供关于模块历史的信息

(3)定义(definition)语句:定义语句是定义数据模型的模块的主体。

可以通过import和include包含其他的子模块。


2.2 树形节点的类型

YANG定义了数据建模的四种主要类型的数据节点

  • 叶子节点(Leaf Nodes)
  • 叶子列表节点(Leaf-List Nodes)
  • 容器节点(Container Nodes)=》目录
  • 列表节点(List Nodes)=》数组

(1)叶节点(Leaf Nodes)

叶子节点包含简单的数据,如整数或字符串。 它只有一个特定类型的值,没有子节点

YANG例子:

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

XML编码示例:

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

(2)叶列表节点(Leaf-List Nodes)

叶列表定义了特定类型的值序列,即可以利用该数据类型定义一个数组。

YANG例如:

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

XML编码示例(数组):

<domain-search>high.example.com</domain-search>
<domain-search>low.example.com</domain-search>
<domain-search>everywhere.example.com</domain-search>

(3)容器节点(Container Nodes)

一个容器用于分组子树中的相关节点。 一个容器只有子节点,没有值。

容器可以包含任何类型、任何数量的子节点(叶子,列表,容器,叶子列表,动作和通知)。

YANG例如:

container system {
  container login {
    leaf message {
      type string;
      description 
            "Message given at start of login session.";
    }
  }
}

XML编码示例:

<system>
  <login>
    <message>Good morning</message>
  </login>
</system>

(4)列表节点(List Nodes)

列表定义了一系列列表条目。

每个条目就像一个容器,如果它定义了任何关键的叶子,它就被其关键叶子的值唯一标识。

列表可以定义多个关键叶子,并且可以包含任何类型的任何数量的子节点(包括树叶,列表,容器等)。

YANG例如:

list user {
  key "name";
  leaf name {
    type string;
  }
  leaf full-name {
    type string;
  }
  leaf class {
    type string;
  }
}

XML编码示例:

<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>

综合代码案例:这些语句被组合来定义模块。

// Contents of "example-system.yang"
module example-system {
    yang-version 1.1;
    namespace "urn:example:system";
    prefix "sys";

    organization "Example Inc.";
    contact "[email protected]";
    description
        "The module for entities implementing the Example system.";

    revision 2007-06-09 {
        description "Initial revision.";
    }

    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;
                }
            }
        }
    }
}

2.3 数据的配置和状态属性(Configuration and State Data)

YANG可以根据“config”语句为状态数据和配置数据建模。实际上是指定数据的读写属性。

当一个节点被标记为“config false”时,其子层被标记为状态数据。为只读数据。

如果标记为“config true”,则其子层被标记为配置数据。

在这个例子中,为每个接口定义了两个叶子,一个配置的速度和一个观察到的速度。

list interface 
{
  key "name";

  leaf name 
  {
    type string;
  }

  leaf speed 
  {
    type enumeration
    {
      enum 10m;
      enum 100m;
      enum auto;
    }
    config true;
  }

  leaf observed-speed 
  {
    type uint32;
    config false;
  }
}

2.4 内置的基本数据类型

类似于大多数编程语言,YANG有一套内置的类型,由于网络管理的特殊要求,有一些不同之处。

名称 描述
binary 任何二进制数据
bits 一组比特(bits)或标志(flags)
boolean "true" 或 "false"
decimal64 64位有符号十进制数字
empty 一个叶子,没有任何值
enumeration 枚举的一组字符串之一
identityref 对抽象身份的引用
int8 8位有符号整数
int16 16位有符号整数
int32 32位有符号整数
int64 64位有符号整数
leafref 对叶子实例的引用
string 一个字符串
uint8 8位无符号整数
uint16 16位无符号整数
uint32 32位无符号整数
uint64 64位无符号整数
union 成员类型的选择

下面是原始内置类型总结表

+---------------------+-------------------------------------+
| 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         | One of an enumerated set of strings |
| identityref         | A reference to an abstract identity |
| instance-identifier | A reference to 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              | A character 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              |
+---------------------+-------------------------------------+

2.5 派生类型(typedef)(Derived Types (typedef))

YANG可以使用“typedef”语句从基本类型定义派生类型。 基本类型可以是内置类型或派生类型,允许派生类型的层次结构。

派生类型可以用作“类型”语句的参数。

ANG示例:

typedef percent {
  type uint8 {
    range "0 .. 100";
  }
}

leaf completed {
  type percent;
}

XML编码示例:

<completed>20</completed>

2.6 可重复使用的节点组(分组)(Reusable Node Groups (grouping))

可以使用“grouping”语句将多个子节点数据描述,组合成一个综合的数据描述,有点类似其他编程语言的“子函数”的功能。

并使用“uses”语句来使用该组合后的数据描述,有点类似其他编程语言的“函数调用”

YANG示例:

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;
  }
}

XML编码示例:

<peer>
  <destination>
    <address>2001:db8::2</address>
    <port>830</port>
  </destination>
</peer>

分组可以根据使用情况进行重新定义或细化,从而允许某些语句被覆盖。 类似C++语言中的重载。

在这个例子中,描述被细化:

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.";
      }
    }
  }
}

2.7 选择(Choices):

YANG允许数据模型使用“choice”和“case”语句将不兼容的节点分隔为不同的选项。类似与C语言的Union数据类型。

choice”语句包含一组“case”语句,用于定义不能一起出现的模式节点集合。

每个“case”可能包含多个节点,但每个节点可能只出现在“choice”下的一个“case”中。

choicecase节点仅出现在模式树(schema tree)中,而不出现在数据树中。

概念模式之外不需要额外的层次结构。 一个case的存在是由一个或多个节点的存在表示。

由于只有一个选择的情况在任何时候都是有效的,所以当在数据树中创建一个节点时,所有其他情况下的所有节点都被隐式删除。 服务器处理约束的执行,防止配置中存在不兼容。

YANG示例:

 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;
         }
       }
     }
   }
 }

XML编码示例:

<food>
  <pretzel/>
  <beer/>
</food>

2.8 扩展数据模型(扩充)(Extending Data Models (augment))

YANG允许模块将其他节点插入数据模型,包括当前模块(及其子模块)和外部模块。 例如,这对于供应商以可互操作的方式向标准数据模型添加供应商特定的参数非常有用。

augment”语句定义插入新节点的数据模型层次结构中的位置,“when”语句定义新节点有效时的条件。

当服务器实现一个包含“augment”语句的模块时,这意味着扩充模块的服务器实现包含附加节点。

YANG示例:

augment /system/login/user {
  when "class != 'wheel'";
  leaf uid {
    type uint16 {
      range "1000 .. 30000";
    }
  }
}

这个例子定义了一个“uid”节点,只有当用户的“class”不是“wheel”时才有效。

如果模块扩充另一个模块,则添加到编码中的XML元素位于扩充模块的命名空间中。 例如,如果上面的扩充是在一个前缀为“other”的模块中,那么XML将如下所示:

XML编码示例:

<user>
  <name>alicew</name>
  <full-name>Alice N. Wonderland</full-name>
  <class>drop-out</class>
  <other:uid>1024</other:uid>
</user>

2.9 “操作”定义

YANG允许定义的操作。 使用YANG数据定义语句对操作名称,输入参数和输出参数进行建模。 模块顶层的操作用“rpc”语句定义。 操作也可以绑定到容器或列表数据节点。 这些操作用“操作”语句来定义。

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://example.com/system">
    <image-name>example-fw-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://example.com/system">
    The image example-fw-2.3 is being installed.
  </status>
</rpc-reply>

YANG绑定到列表数据节点的操作示例:

list interface {
  key "name";

  leaf name {
    type string;
  }

  action ping {
    input {
      leaf destination {
        type inet:ip-address;
      }
    }
    output {
      leaf packet-loss {
        type uint8;
      }
    }
  }
}

NETCONF XML示例:

<rpc message-id="102"
     xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <action xmlns="urn:ietf:params:xml:ns:yang:1">
    <interface xmlns="http://example.com/system">
      <name>eth1</name>
      <ping>
        <destination>192.0.2.1</destination>
      </ping>
    </interface>
  </action>
</rpc>

<rpc-reply message-id="102"
           xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
           xmlns:sys="http://example.com/system">
  <sys:packet-loss>60</sys:packet-loss>
</rpc-reply>

4.10 通知定义

YANG允许定义通知。 YANG数据定义语句用于模拟通知的内容。

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="urn:example: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>

参考:

RFC7950 (The YANG 1.1 Data Modeling Language) 中文翻译版本

猜你喜欢

转载自blog.csdn.net/HiWangWenBing/article/details/108427581