yang標準翻譯

. 關鍵詞

The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, 
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and 
“OPTIONAL” in this document are to be interpreted as described in BCP 
14, [RFC2119].

3. 術語

  • anyxml —— 一種數據節點,能夠包含未知的XML格式的數據塊。
  • augment —— 向之前定義的schema node增加新的schema nodes。
  • base type —— 可以被用來繼承的數據類型,可以使built-in類型,也可以是派生的類型。
  • built-in type —— YANG語言定義的YANG數據類型,比如uint32 或者 string
  • choice —— 一個schema node,其值是多個可選項中的一個。
  • configuration data —— 可寫入的數據的集合,被用來轉變系統的狀態【RFC4741】。
  • conformance(一致性) —— 一種評估實際上設備在多大程度上服從數據模型的方法。
  • container —— 一種內建的數據節點,在data tree中,最多隻能有一個實例存在。一個container沒有值,不過會包含一些子節點。
  • data definition statement —— 一種定義新的數據節點的聲明(statement)。可以是container,leaf,leaf-list,list,choice,case,augment,uses,以及anyxml中的一個。
  • data model —— 一種表述數據如何展現和訪問的數據模型。
  • data node(數據節點) —— schema tree中的一個節點,能夠在data tree中實例化。可以是container,leaf,leaf-list,list,以及anyxml中的一個。
  • data tree —— 由一個設備上的配置和狀態數據實例化的樹。
  • derived type(派生類型) —— 一種從內建數據類型,或者其他派生類型中派生出來的類型。
  • device deviation(設備偏差) —— 如實反映設備在實現YANG模塊時候的失敗情況。
  • extension —— 使用非YANG語義聲明的擴展。擴展聲明定義了新的statement表示這些語義。
  • feature —— 一種可選的能夠標記模型的某一部分的機制。可以使用feature名作爲標籤,不過該標籤僅僅在支持該feature的設備上纔有效。
  • grouping —— 一種可重用的schema nodes的集合。該集合可能在定義處的module中被使用,也可能在包含它的modules中使用,還可能在導入它的modules中被使用。grouping聲明不是一種數據定義聲明,它不會在schema node中定義任何節點。
  • identifier —— 通過名字,被用來識別不同種類的YANG items。
  • instance identifier —— 在data tree中被用來標記特定的一個節點。
  • interior node —— 分層結構中,非leaf node的節點。
  • leaf —— 一種數據節點,在data tree中最多隻能有一個實例存在。一個leaf節點只能有一個值,並且不能有子節點。
  • leaf-list —— 和leaf節點相似,但是定義了一集合的可唯一識別的節點,而非一個節點。其中每一個節點都有值,但是都沒有子節點。
  • list —— 一種內部的數據節點,在data tree中可能會有多個實例存在。一個list沒有值,但是會有一些子節點。
  • module —— 一個YANG module定義了一個具有垂直層級結構的節點集,這些節點能夠被用於基於NETCONF的operations。如果有一個module的定義,以及該module依賴的其他module的定義,則這個module是自足的,以及“可編譯的(compilable)”。
  • RPC —— 遠程過程調用,在NETCONF協議中使用的。
  • RPC operation —— 一種特定的遠程過程調用,在NETCONF協議中使用的。也被成爲協議操作(protocol operation)。
  • schema node —— 在schema tree中的節點。是container,leaf,leaf-list,list,choice,case,rpc,input,output,notification,以及anyxml中的一種。
  • schema tree —— module中的特定垂直結構定義(The definition hierarchy specified within a module.)。
  • state data(狀態數據) —— 系統中的配置數據之外的其他額外數據,比如只讀的狀態信息,數據統計信息【RFC4741】。
  • submodule —— 一種局部的module定義。submodule爲所在的module提供了derived types,groupings,data nodes,RPCs,以及notifications。一個YANG module可以由多個submodules組成。
  • top-level data node —— 一個數據節點,在該節點和module/submodule聲明之間,沒有其他的數據節點存在。
  • uses —— 這個“uses”聲明被用來實例化在grouping聲明中定義的schema nodes。這些實例化的節點可能會被擴展以滿足特定的需求。

搞不明白feature的具體用法。不知道data tree和schema tree的區別。

3.1 Mandatory Nodes(必須出現的節點)

一個mandatory node是以下中的:

  • “mandatory”聲明爲“true”的一個leaf,choice,或者anyxml節點。
  • “min-elements”聲明爲大於0的數的一個list,或者leaf-list節點。
  • 沒有“presence”聲明的container節點,它裏面至少要包含一個mandatory node的子節點。

4. YANG總

4.1 功能總覽

YANG是一種被用來爲NETCONF協議建模的語言。一個YANG module定義了具有垂直結構的數據,這些數據可以被用做基於NETCONF的operations,比如configuration,state date,RPCs,以及notifications。它使得NETCONF的client和server之間能有完整的數據描述。

YANG建模得到的數據具備樹形結構。其中每一個節點都有一個名字,都有一個值或者一些子節點。YANG爲這些節點,以及節點之間的交互提供明確清晰的描述。

YANG使用modules和submodule進行數據建模。一個module能夠從其他外部的modules中導入數據,也可以從submodules中包含數據。YANG定義的垂直結構可以擴展,使得一個module能夠增加數據節點給另一個module。這種擴展是有條件的,只有特定條件滿足,新的數據節點纔會出現。

YANG模型還能描述數據之上增加的約束,基於垂直結構中其他節點的出現與否,值爲多少等等來限制一些節點的出現與賦值。這些約束可以被client或者server強制執行。不過如果要使得內容有效,MUST 雙方都要遵守特定的約定。

YANG定義了一系列的內建數據類型,也有定義新數據類型的類型命名機制。派生數據類型可以通過像range,pattern這樣的聲明限制其原生數據類型的取值範圍,這樣的聲明在client或者server端都可以執行。它們還能爲派生數據類型定義常用用法,比如定義一個string-based類型,包含主機名。

YANG允許對可重用的grouping中節點的定義。這些groupings中的實例能夠通過特定的增強以滿足特殊的需求。派生類型以及groupings能夠定義在一個module或者submodule中,能夠被本地,其他module/submodule導入和使用。

YANG的垂直數據結構包括了對list的定義。list中包含的每一項都有唯一的key以區分彼此。這樣的lists有可能被用戶自定義排序或者由系統進行默認排序。對於用戶自定義排序的lists來說,operations是爲了對列表項進行排序定義的。

YANG modules可以被轉換爲等價的XML格式,稱爲YANG Independent Notation(YIN)(Section 11),這使得相關的應用可以通過XML解析器或者XSLT腳本進行操作。從YANG到YIN的轉換是無損的,因此也可以從YIN格式轉換爲YANG文件。

YANG試圖在高層的數據建模和底層的比特數據編碼(bits-on-the-wire encoding)之間追求平衡。YANG module的reader可以查看數據模型的高層視圖,同時也能理解在NETCONF operations中,這些數據如何編碼。

YANG是一種可擴展語言,允許標準制定者,設備商,以及個人定義新的聲明(statement)。聲明的語法使得這些擴展能夠以一種自然的方式和標準的YANG 聲明共存,同時使得reader能夠有效得認知這些新擴展。

YANG resists the tendency to solve all possible problems, limiting the problem space to allow expression of NETCONF data models, not arbitrary XML documents or arbitrary data models. The data models described by YANG are designed to be easily operated upon by NETCONF operations.

爲了擴大使用範圍,YANG和SNMP協議的SMIv2(Structure of Management Information,RFC2578RFC2579)保持了兼容。基於SMIv2的MIB modules能夠以只讀的方式自動轉換爲YANG modules。然而,YANG並不關心如何從YANG轉換爲SMIv2。

和NETCONF相似,YANG致力於和設備本身自帶的管理機制進行平滑集成。這就使得需要利用設備當前的訪問控制機制去保護/暴露數據模型的相應元素。

4.2 語言總覽

本小節引入了YANG語言中的一些重要結構,這些在後面的章節中,對於理解語言細節能夠提供一些幫助。這種方法解決了難以理解的相互聯繫的YANG概念和聲明的複雜關係問題。關於YANG的聲明(statement)和語法(syntax)的細節描述可見Section 7。

4.2.1 Modules和Submodules

一個module包含了三種類型的聲明:

  • module-header statement(模塊頭聲明) —— 描述了該module,給出了module相關的信息。
  • revision statement(版本聲明)—— 描述了該module的歷史信息。
  • definition statement(定義聲明) —— 定義了數據模型的內容部分。

一個NETCONF Server可能會實現多個modules,擁有相同設備數據的多個視圖,或者互不相交的多個子集的多個視圖。這種情況下,Server可能會選擇僅僅實現定義了所有可用數據的一個module。(A NETCONF server may implement a number of modules, allowing multiple views of the same data, or multiple views of disjoint subsections of the device’s data. Alternatively, the server may implement only one module that defines all available data.)

根據需求,一個module可以被分爲多個submodules。而對外來說,依然是單個module,無論內部擁有多少個submodules。

“include”聲明允許一個module或者submodule引用submodules中定義的數據;“import”聲明允許引用其他modules中定義的數據。

4.2.2 數據建模基礎(Data Modeling Basics)

YANG定義了四種用於數據建模的節點類型。在下面的每一個小節中,都有例子展示了YANG語法以及相應的NETCONF XML表達。

4.2.2.1 Leaf Nodes

一個leaf node包含了像integer或者string這樣的簡單數據。它有且僅有一個特定類型的值,並且沒有子節點。

YANG 示例:

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

NETCONF XML 示例:

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

“leaf”的聲明可以在Section 7.6 中找到。

4.2.2.2 Leaf-List Nodes

一個leaf-list是一系列的leaf nodes,每個leaf都有特定類型的值。

YANG 示例:

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

NETCONF XML 示例:

 <domain-search>high.example.com</domain-search>
 <domain-search>low.example.com</domain-search>
 <domain-search>everywhere.example.com</domain-search>
  • 1
  • 2
  • 3
  • 4

“leaf-list”的聲明可以在Section 7.7 中找到。

4.2.2.3 Container Nodes

一個container node用來將相關的節點歸總到一個subtree中。一個container node只有子節點,沒有值。一個container可能會包含任何類型的任何數量的子節點(包括leafs,lists,leaf-lists以及containers)。

YANG 示例:

 container system {
     container login {
         leaf message {
             type string;
             description
                 "Message given at start of login session";
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

NETCONF XML 示例:

 <system>
   <login>
     <message>Good morning</message>
   </login>
 </system>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

“container”的聲明可以在Section 7.5 中找到。

4.2.2.4 List Nodes

一個List定義了一系列的列表項(list entries)。每個列表項都像是一個structure或者一個record instance,通過名爲“key”的leaf的值唯一確定。一個list能定義多種key leafs,能夠包含任意類型的任意數目的子節點(包括leafs,lists,containers)。

YANG 示例:

 list user {
     key "name";
     leaf name {
         type string;
     }
     leaf full-name {
         type string;
     }
     leaf class {
         type string;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

NETCONF 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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

“list”的聲明可以在Section 7.8 中找到。

4.2.2.5 Module示例

上述的那些聲明組合起來能夠定義一個簡單的module:

 // Contents of "acme-system.yang"
 module acme-system {
     namespace "http://acme.example.com/system";
     prefix "acme";

     organization "ACME Inc.";
     contact "[email protected]";
     description
         "The module for entities implementing the ACME 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;
                 }
             }
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

4.2.3 State Data

YANG 能夠通過“config”聲明對state data和configuration data進行建模。當一個節點打上了“config false”的標籤,它的子結構就打上了state data的標籤,會通過NETCONF的操作,而不是操作。作爲其父節點的containers,lists,以及key leafs也會上報,以給這個state data明確的上下文環境。

不清楚爲什麼還會有key leafs。

在下面的例子中,每個interface都定義了兩個leafs,一個是configured speed(配置速率),另一個是observed speed(觀察速率)。觀察速率是不可配置的,所以它能通過NETCONF的操作獲取,但是不能通過操作獲取,也不能通過操作操作。

 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;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

4.2.4 Built-in Types

和一些編程語言類似,YANG也有一系列的內置類型。下面的表格就總結了在Section 9描述的內置數據類型:

   +---------------------+-------------------------------------+
   | 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              |
   +---------------------+-------------------------------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

“type”的聲明可以在Section 7.4 中找到。

4.2.5 Derived Types(typedef)

YANG能夠使用“typedef”聲明從基本類型中定義派生類型。一個基本類型可以是內置類型或者派生類型。

YANG 示例:

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

 leaf completed {
     type percent;
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

NETCONF XML 示例:

 <completed>20</completed>
  • 1
  • 2

“typedef”的聲明可以在Section 7.3 中找到。

4.2.6 可重用的節點組(grouping)

可以使用“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;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

NETCONF XML 示例:

 <peer>
   <destination>
     <address>192.0.2.1</address>
     <port>830</port>
   </destination>
 </peer>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

grouping可以根據它被調用時候的用途進行優化,重寫特定的聲明來覆蓋原來grouping的定義。在下面的例子中,description被重定義了:

 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";
             }
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

“grouping”的聲明可以在Section 7.11 中找到。

4.2.7 choice

YANG能夠使用“choice”和“case”聲明分離互不相容,不能同時出現的節點。“choice”聲明包含了多個“case”聲明,定義了不能同時出現的schema nodes的集合。每個“case”聲明都可能包含多個節點,但是每個節點都應該只在一個“case”中出現。

當一個case元素被創建,其他所有cases的元素都會被隱式刪除。設備要強制執行這個約束,以防止出現配置的不協調。

“choice”和“case”節點只會出現在schema tree中,不能出現在data tree或者NETCONF message

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;
               }
           }
       }
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

NETCONF XML 示例:

 <food>
   <pretzel/>
   <beer/>
 </food>
  • 1
  • 2
  • 3
  • 4
  • 5

“choice”的聲明可以在Section 7.9 中找到。

4.2.8 擴展數據模型(augment)

YANG允許一個模塊將額外的節點插入到數據模型中,包括當前的module(以及它的submodule)或者一個外部的module。這一點是很有用的,比如對於設備商來說,需要在標準數據模型中插入設備商指定的參數。

“augment”聲明定義了在數據模型樹形結構中,新的節點插入的位置。“when”聲明瞭新節點生效的時間。

YANG 示例:

 augment /system/login/user {
     when "class != 'wheel'";
     leaf uid {
         type uint16 {
             range "1000 .. 30000";
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

這個例子定義了一個“uid”的leaf node,該node僅在user的class不等於wheel的時候纔有效。

如果一個module增強了另一個module,則數據的XML表示將會影響增強它的module的前綴。比如,如果上一個例子的augment是放在一個“other”前綴的module中,則其XML看起來應該是這樣的:

NETCONF XML 示例:

 <user>
   <name>alicew</name>
   <full-name>Alice N. Wonderland</full-name>
   <class>drop-out</class>
   <other:uid>1024</other:uid>
 </user>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

“augment”的聲明可以在Section 7.15中找到。

4.2.9 RPC定義

YANG也能定義NETCONF中的RPCs。RPC中的operations’ name,輸入參數,和輸出參數都可以通過YANG的數據定義聲明進行建模。

YANG 示例:

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

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

“rpc”的聲明可以在Section 7.13中找到。

4.2.10 Notification定義。

YANG的notification定義和NETCONF適配。YANG的數據定義聲明被用來爲notification的內容建模。

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;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

notification和rpc都是NETCONF中的定義,雖然大概明白什麼意思,但是具體就不清楚了,需要去NETCONF的標準中去查看定義。

“notification”的聲明可以在Section 7.14中找到。

5. 語言概念

5.1 modules和submodules

在YANG語言中,module是基本單位。每個module都定義一個數據模型。一個module能夠定義一個完整的模型,或者對當前數據模型做額外擴展。

submodules是module的一部分,能夠爲一個module提供相關定義。一個module能包含任意數量的submodules,但是每個submodule只能屬於一個module。

所有標準的modules和submodules的名字都 MUST 是唯一的。我們 RECOMMEND 企業級modules的開發者選擇和標準模型以及其他企業modules不衝突的名字,比如說,使用企業或組織名字作爲module名字的前綴。

一個module使用“include”聲明包含它的submodules,使用“import”聲明引入外部的modules。相似的,一個submodule會使用“include”聲明引用同一個module中的其他submodules,使用“import”聲明引用其他modules。一個module或submodule MUST NOT 包含其他modules中的submodules,一個submodule MUST NOT 導入它自己所在的module。

導入(import)和包含(include)聲明使用如下:

  • 如果一個module或submodule需要引用來自外部的module,外部的module MUST 被imported。
  • 如果一個module需要引用其內部的某個submodule,這個module MUST include這個submodule。
  • 如果一個submodule需要引用同一個module內部的其他submodule,則這個submodule MUST include另一個submodule。

在modules/submodules的imports和includes中,MUST NOT 形成環形調用鏈。比如,如果submodule “a”包含了submodule “b”,則“b”就不能包含submodule “a”了。

當在一個外部module的定義被引用時, MUST 使用局部定義的前綴,後面跟着冒號“:”,然後是具體使用的外部module的id。對本地module定義的引用可以使用前綴,也可以不使用。由於built-in類型不屬於任何module,所以對built-in類型的引用不能使用任何前綴。

5.1.1 Import and Include by Revision

隨着時間的推移,已經發布的modules會慢慢演進出新的版本。爲了支持這樣的正常演進過程,modules在被其他module import時需要使用其revisions。當一個module完成時,它會基於當前時間使用可用的帶有特定revisions的其他modules。如果後來,被imported的modules更新了,該module不會受到影響。當這個module的作者準備將“import”的module更新到最新版本,只需要修改“revision”字段就可以了。

對於submodule來說,方案相似不過更加簡單。一個module或者submodule,在包含其他的submodule的時候都要指定被包含submodules的revision。如果一個submodule改變了,任何包含它的其他module或者submodules都需要被更新。

比如,module “b” 導入了module “a”:

 module a {
     revision 2008-01-01 { ... }
     grouping a {
         leaf eh { .... }
     }
 }

 module b {
     import a {
         prefix p;
         revision-date 2008-01-01;
     }

     container bee {
         uses p:a;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

當module “a” 的作者發佈了一個新的revision,新版本的更改可能不爲“b”所接受。如果“b”接受,則需要更新其導入“a”的import語句中的revision版本。

5.1.2 Module分層

YANG能支持數據模型的多層次劃分,在該劃分中,數據可能有不止一個top-level(頂級)的節點。擁有多個top-level節點的數據模型有時候是更加方便的。

NETCONF協議能夠在<config><data>元素中包含任何XML內容作爲載荷。YANG模型中的頂級結點在上述兩種元素中以任意順序,作爲子節點存在。在這些子節點中,要保證NETCONF消息已經封裝成正確的XML格式了。

比如:

 module my-config {
     namespace "http://example.com/schema/config";
     prefix "co";

     container system { ... }
     container routing { ... }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在NETCONF中被封裝爲:

 <rpc message-id="101"
      xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
      xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
   <edit-config>
     <target>
       <running/>
     </target>
     <config>
       <system xmlns="http://example.com/schema/config">
         <!-- system data here -->
       </system>
       <routing xmlns="http://example.com/schema/config">
         <!-- routing data here -->
       </routing>
     </config>
   </edit-config>
 </rpc>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

除了YANG定義之外的rpc,message-id什麼的都搞不懂。還需要看一下NETCONF啊。

5.2 文件格式

YANG modules和submodules通常都會以文件的形式存儲,每個module或者submodule一個文件。文件的命名格式 SHOULD 是這種格式:

module-or-submodule-name ['@' revision-date] ( '.yang' / '.yin' )
  • 1
  • 2

YANG編譯器能夠通過文件名找到導入的modules和包含的submodules。當使用YANG語言定義modules的時候,出於性能和manageability的考慮,編譯器可能會分別編譯每一個submodules。在submodules的編譯期間,errors和warnings不能被檢測到。直到將submodules併入module的時候,纔會發現錯誤和警告。

5.3 XML Namespace

所有的YANG定義都包含在YANG module中,每個YANG module都會和特定的XML namespace XML NAMES綁定,該命名空間是全局唯一的URI RFC3986。NETCONF的客戶端和服務端在封裝數據的時候,使用這個命名空間。

modules的Namespace發佈在rfc4844中, MUST 由IANA分配,可見Section 14。

私有module的namespace分配由擁有該module的組織分配。Namespace URIs的分配必須保證不能與標準的modules衝突,不能與其他私有的modules衝突,可以在namespace中使用組織/公司名字以避免明明衝突。

“namespace”聲明可以在Section 7.1.3見到。

5.3.1 YANG XML Namespace

YANG 爲NETCONF的 <edit-config> 和<error-info>內容定義了XML namespace。這個namespace的名字是“urn:ietf:params:xml:ns:yang:1”。

5.4 解析Grouping,Type,和Identify名

Gouping,Type,和Identify的名字是在它們被定義的地方被解析的,而不是在它們被使用的地方被解析的。groupings, typedefs,identifies的使用者並不被強制要求導入modules或者包含submodules,以滿足原始定義的引用要求。這種特性類似於傳統編程語言中的靜態變量作用域。

比如,如果一個module定義了一個grouping,在其中引用了一個type。當這個grouping在另一個module中被引用的時候,該type在原來的module的上下文中被解析,而不是在第二個module中被解析。如此一來就不用擔心多個module共同定義同一個type時候引起的衝突問題了。

5.5. Nested Typedefs和Groupings

在很多YANG statements中,typedefs和groupings都可能出現嵌套的情況。在層級結構中,它們在語義上侷限於被定義的層級(也就是說解析的時候不會波及到其他層級)。這使得types和groupings可以定義在和被使用的地方接近的地方,而不是放到層級結構的頂級。這種使用處定義的特性增強了可讀性。(Typedefs and groupings may appear nested under many YANG statements, allowing these to be lexically scoped by the hierarchy under which they appear. This allows types and groupings to be defined near where they are used, rather than placing them at the top level of the hierarchy. The close proximity increases readability.

作用域(scoping)的作用使得在不同submodules定義的types可以出現命名衝突,因爲它們的作用域沒有交集。

最後,作用域使得module的作者能夠使得他們定義的types和groupings能夠只對他們的module或submodule有效,防止了其他人的重用。由於只有頂級的types和groupings能夠在module/submodule外部被使用,開發者能夠有更多的控制能力,控制module的哪些部分要對外開放,哪些部分要在內部保持私有。

作用域的定義 MUST NOT 覆蓋更高級別的作用域的定義。當在schema層級結構中,當更高級別中已經定義了,則更低級別中不能再定義相同的“types”和“groupings”了。

對於沒有前綴的type或grouping的引用,或者使用當前module名作爲前綴的引用,會被解析爲和type或grouping聲明最匹配的結構。(A reference to an unprefixed type or grouping, or one which uses the prefix of the current module, is resolved by locating the closest matching “typedef” or “grouping” statement among the immediate substatements of each ancestor statement.

5.6 一致性

一致性(conformance)是衡量一個設備實際上與model契合的程度。通常來說,設備需要如實完全實現model的定義,這樣一來上層應用才能按照model的定義來看待下面的設備。設備與model的差異會降低model的可用性,同時使得使用該model的application更加脆弱。

YANG針對一致性有三種檢查機制:

  • model的基礎行爲檢查
  • model可選特性的檢查
  • 和model之間的偏差

接下來我們會挨個討論每一種機制。

5.6.1 基礎行爲

model定義了NETCONF的client和server之間的constract(協議),這使得通信雙方能夠互相理解對方發送的模型化數據背後蘊含的語法和語義。YANG的優點就是constract的優點。

5.6.2 可選特性

在很多models中,作者會允許models中的某些部分在有一定先決條件的情況下才會出現/禁止出現。設備可以決定,是否支持model中定義的可選功能。

比如,一個syslog data model可能會選擇支持本地存儲日誌的能力,但是model作者知道,在實際設備中,只有當這個設備有本地存儲器的時候纔有可能支持該功能。如果設備上沒有本地存儲器,則application就不能通知設備去存儲日誌。

YANG通過名爲“feature”的結構支持這種可選特性的機制。features使得模型作者能夠讓設備根據實際情況有選擇實現一些可選的特性。這樣一來,在model中就能表現一些只有部分設備支持的特性。這些特性被包含在model的定義中,能夠使得不同設備的模型儘可能保持一致性,讓application能夠獲知哪些特性被支持,並在此基礎上對設備進行操作。

一個module可以聲明任意數量的features,這些特性用字符串id做識別。如果一個設備支持某個feature,則module中對應的部分對該設備來說就是可用的;反之亦然。

features是用“feature”聲明定義的。如果該feature是有條件的(conditional),則需要使用“if-feature”聲明。

更多細節可見Section 7.18.1

還是不太明白feature的應用實例。

5.6.3 偏差(deviations)

在理想情況下,所有的設備都應該完全實現model的定義,不會和model出現任何偏差。但是實際情況下,設備總會和model有各種各樣的差異存在。爲了讓YANG能夠支持針對實際存在的偏差的自動處理,設備上必須有一種機制能夠通知applications它和model之間的偏差。

比如,一個BGP module能支持任意多的BGP peers,但是一個特定的設備可能最多隻能支持16個peers。任何application發送的第17個peer的連接請求都會失敗。相比較於設備用錯誤消息通知application,更好的解決方法是application從一開始就知道16個peers的限制,並且能夠避免用戶申請註定失敗的第17個peer連接。

設備的deviations使用“deviation”聲明,它使用在schema tree中表示一個節點的字符串作爲參數。The contents of the statement details the manner in which the device implementation deviates from the contract as defined in the module.

更多細節可見Section 7.18.3

5.6.4 在消息中宣告一致性(Conformance)信息

命名空間URI MUST 作爲一種能力(capability),在NETCONF的消息中向外通告,表示NETCONF服務器支持YANG module。該URI的格式 MUST 如下:

 capability-string   = namespace-uri [ parameter-list ]
 parameter-list      = "?" parameter *( "&" parameter )
 parameter           = revision-parameter /
                       module-parameter /
                       feature-parameter /
                       deviation-parameter
 revision-parameter  = "revision=" revision-date
 module-parameter    = "module=" module-name
 feature-parameter   = "features=" feature *( "," feature )
 deviation-parameter = "deviations=" deviation *( "," deviation )
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • “revision-date”表示NETCONF服務器實現的module的revision
  • “module-name”表示module的名字,如同“module”聲明一樣
  • “namespace-uri”表示這個module的namespace URI,如同在“namespace”聲明中出現的一樣
  • “feature”表示設備實現的可選的feature
  • “eviation”表示定義了設備的偏差的module的名字

在以上的參數列表中,每個參數 MUST 出現一次。

5.6.4.1 Modules

服務器通過消息通告它所支持的modules的名字。Module的namespaces是在capability字符串中作爲基礎URI編碼的,mdule的名字被編碼爲“module”參數放到基礎URI中。

一個服務器 MUST 聲明它所實現的所有modules的所有revisions。

比如,下面的消息聲明瞭一個module “syslog”。

    <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
      <capability>
        http://example.com/syslog?module=syslog&amp;revision=2008-04-01
      </capability>
    </hello>
  • 1
  • 2
  • 3
  • 4
  • 5
5.6.4.2 Features

服務器通過消息通告它所支持的features的名字。在消息中,features作爲包含在URI中的“features”參數編碼的。這個參數的值是以逗號爲分隔符的feature名的列表。

比如,下面的消息聲明瞭一個module,“syslog”,並告訴客戶端它所支持的名爲“local-storage”的feature。

<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <capability>
    http://example.com/syslog?module=syslog&amp;features=local-storage
  </capability>
</hello>
  • 1
  • 2
  • 3
  • 4
  • 5
5.6.4.3 偏差(Deviations)

設備的偏差是通過“deviations”參數聲明的。“deviations”參數的值是以逗號爲分隔符的包含deviations的modules的列表。

比如,下面的消息通告了兩個modules,告訴客戶端它偏離module “syslog”的程度,這個程度具體是通過module “my-devs”聲明出來的。

   <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
       <capability>
         http://example.com/syslog?module=syslog&amp;deviations=my-devs
       </capability>
       <capability>
         http://example.com/my-deviations?module=my-devs
       </capability>
     </hello>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

但是這個偏差具體怎麼描述也沒有個說明,它的內容和“syslog”有怎樣的關係?

5.7 Data Store Modification

Data models可能允許服務器選擇不同的configuration data store的實現,而不僅僅是直接明確地通過NETCONF協議消息完成。比如,一個data model可能定義了一些系統生成的分配的值作爲leafs,但是客戶端可能並不支持。一種指定環境變量的通用機制(前提是這些環境變量允許修改)超出了本文檔的討論範圍。

6 YANG Syntax

YANG語法類似於【RFC3780】定義的SMIng,以及編程語言C和C++。這種語法之所以和C相似,主要是爲了可讀性。since YANG values the time and effort of the readers of models above those of modules writers and YANG tool-chain developers. This section introduces the YANG syntax.

YANG modules使用【RFC3629】定義的UTF-8作爲字符編碼格式。

6.1 詞彙的令牌化(Lexical Tokenization)

YANG modules在解析時會被分爲多個tokens。本小節詳細解釋解析這些tokens的規則。YANG的令牌化規則是簡單而強大的。簡單之處在於其力圖保持解析器的實現簡單,強大之處在於模型設計者能夠以一種易讀的格式表現他們設計的models。

6.1.1 註釋(Comments)

Comments是C++風格的。單行註釋開始於“//”,結束於本行。塊註釋開始於“/*”,結束於“*/”。

6.1.2 Tokens

YANG中的一個token是一個keyword,string,semicolon(“;”),或者braces( “{” 或 “}” )。一個string可以是quoted或unquoted的。一個keyword可以是本文檔中定義的YANG的關鍵詞,或者是後面跟着冒號“:”,冒號後面跟着語言擴展關鍵詞的前綴id。keywords是大小寫敏感的。id的正式定義可見section 6.2。

什麼是quoted和unquoted?意思是引號包括的和不用引號包括的。

6.1.3 引號包裹(Quoting)

如果一個string包含任何空格,製表符,分號(“;”),大括號( “{” 或 “}”),註釋符號(“//”,“/*”,或“*/”),則它 MUST 用雙引號或者單引號包括。

如果一個用雙引號包括的string中包含一個換行符,換行符後面跟着的是空格或者製表符,該空格或製表符通常用來控制YANG文件中的文本佈局。這些用於增強文本顯示效果的留白在解析時會被從string中刪掉,一直到第一個非空白字符爲止。在該處理流程中,一個製表符被認爲是8個空格符。

如果這個用雙引號包括的string中在換行符前包含了空格或者製表符,這種行尾空格也會被從string中刪掉。

一個單括號包裹的string(“””)則會保留單括號內的每一個字符。單括號字符不能出現在單括號包括的string中,即便使用反斜槓(“\”)做了轉義也不可以。

在一個雙括號包括的string理,使用轉義字符(也就是反斜槓)會引入一個特殊字符,這取決於該轉義字符後面跟着的是哪個字符:

\n      new line
\t      a tab character
\"      a double quote
\\      a single backslash
  • 1
  • 2
  • 3
  • 4
  • 5

如果一個括號包裹的string後面跟着一個加號(“+”),然後跟着另一個括號包裹的string,則這兩個strings會被首尾銜接在一起,合併爲一個string。在雙括號包括的strings進行合併之前,該string要先完成空白字符的刪除,以及轉義字符的替換。

6.1.3.1 Quoting例子

下面的strings是等價的:

     hello
     "hello"
     'hello'
     "hel" + "lo"
     'hel' + "lo"
  • 1
  • 2
  • 3
  • 4
  • 5

下面的例子展示了一些特殊字符:

 "\""  - string containing a double quote
 '"'   - string containing a double quote
 "\n"  - string containing a new line character
 '\n'  - string containing a backslash followed
         by the character n
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

下面的例子展示了一些非法的字符串:

 ''''  - a single-quoted string cannot contain single quotes
 """   - a double quote must be escaped in a double-quoted string
  • 1
  • 2
  • 3

下面的字符串是等價的:

     "first line
        second line"

 "first line\n" + "  second line"          
  • 1
  • 2
  • 3
  • 4
  • 5

6.2 Identifiers

6.1.2中提到的id。

Identifiers被用來標識不同類型的YANG items。每個identifier都開始於一個大寫,小寫的ASCII字幕,或者是一個下劃線,後面跟着0個或多個ASCII字幕,數字,下劃線,連字符以及點。具體的實現 MUST 支持64個字符的長度。Identifiers是大小寫敏感的。其語法規則的正式定義可見Section 12。Identifiers能被指定爲quoted或unquoted strings。

其實看了也不明白這個identifier的具體用途在哪裏

6.2.1 Identifiers和它們的Namespaces

每個identifier在一個namespace中都是有效的,而namespace取決於YANG item被定義的類型。所有的定義在一個namespace中的identifiers都必須是唯一的。

  • 所有的module和submodule的名字都共享同一個全局的module identifier namespace。
  • 在module以及它的submodules中定義的所有擴展名都共享同一個extension identifier namespace。
  • 所有定義在module以及它的submodules的identity names都共享同一個identity identifier namespace。
  • 所有定義在module以及它的submodules的父節點或者頂級節點的派生類型的名字(derived type names)都共享同一個type identifier namespace。這個namespace對於該父節點或者module的所有下行節點都有效。這意味着任何下行節點都有可能使用typedef,並且 MUST NOT 定義和其它type名相同的名字。
  • 所有定義在module以及它的submodules的父節點或者頂級節點的grouping names都共享同一個grouping identifier namespace。這個namespace對於該父節點或者module的所有下行節點都有效。這意味着任何下行節點都有可能使用grouping,並且 MUST NOT 定義和其它grouping名相同的名字。
  • 所有定義在module以及它的submodules的父節點或者頂級節點的leafs,leaf-lists,lists,containers,choices,rpcs,notifications以及anyxmls(直接或者通過“use”聲明定義的 )都共享同一個identifier namespace。這個namespace對於該父節點或者module都有效,除非父節點是一個case node。在那種情況下,這個namespace對於非case或choice節點的最近的祖先節點。
  • 所有在包含在“choice”中的“case”都共享同一個case identifier namespace。這個namespace在父choice node中有效。

這裏還是有問題啊,第六項中,這個namespace對於該父節點或者module有效,而不是對該父節點或者module的所有下行節點都有效。這裏是不是有錯誤啊? 
另外,頂級節點的作用範圍是不是就對應着整個module啊。

YANG語言中允許前向引用(Forward references)。

6.3 聲明(Statements)

一個YANG module包含了一系列的statements。每個statement開始於一個keyword,後面跟着0個或一個參數,然後或者跟着一個分號表示結束,或者跟着用大括號包裹的substatements塊:

 statement = keyword [argument] (";" / "{" *statement "}")
  • 1
  • 2

如果Section 6.1.2的定義,這個參數是一個string。

6.3.1 語言擴展(Language Extensions)

在一個module中,可以使用“extension”關鍵詞(見Section 7.17)引入YANG extensions。擴展也可以被其它modules使用“import”聲明導入(見Section 7.1.5)。當一個被導入的擴展被使用時,該擴展的關鍵詞 MUST 使用該擴展被定義的module的名字作爲前綴以示區別。如果擴展在它被定義的module中使用,則其關鍵詞也 MUST 使用module的前綴。由於submodules不能包括其parent module,因此,所有需要在submodules中用到的擴展都 MUST 定義在submodule中。然後其它的submodules能夠通過包含該submodule使用該擴展。

複習一下,submodule叫include,module叫import。

如果一個YANG編譯器不支持特定的擴展,具體表現爲在一個YANG module中出現未知的statement(見Section 12),則整個未知的statement包含的內容 MAY 被編譯器忽略。

6.4 XPath Evaluations

XPath的簡介可見http://www.w3school.com.cn/xpath/xpath_intro.asp

XPath 是一門在 XML 文檔中查找信息的語言。XPath 用於在 XML 文檔中通過元素和屬性進行導航。XPath 使用路徑表達式來選取 XML 文檔中的節點或者節點集。這些路徑表達式和我們在常規的電腦文件系統中看到的表達式非常相似。在 XPath 中,有七種類型的節點:元素、屬性、文本、命名空間、處理指令、註釋以及文檔節點(或稱爲根節點)。

YANG依賴XML Path Language(XPath) 1.0,將其作爲標記表達節點之間的引用和依賴關係。NETCONF的客戶端和服務端並不強制要求實現XPath解釋器,但是 MUST 確保data model中編碼的requirements是強制執行的。執行的方式由實際實現決定。XPath表達式 MUST 在語法結構上保證正確無誤,所有使用的前綴 MUST在當前的XPath context中是現成可用的(見Section 6.4.1)。有種實現會選擇手動實現這些,而不是直接使用XPath表達式。

什麼叫確保data model中編碼的requirements是強制的。原文是

NETCONF clients and servers are not required to implement an XPath interpreter, but MUST ensure that the requirements encoded in the data model are enforced. The manner of enforcement is an implementation decision.

The data model used in the XPath expressions is the same as that used 
in XPath 1.0 [XPATH], with the same extension for root node children 
as used by XSLT 1.0 [XSLT] (Section 3.1). Specifically, it means 
that the root node may have any number of element nodes as its 
children.

6.4.1 XPath Context

所有的YANG XPath表達式都共享下面的XPath context定義:

  • The set of namespace declarations is the set of all “import” statements’ prefix and namespace pairs in the module where the XPath expression is specified, and the “prefix” statement’s prefix for the “namespace” statement’s URI.
  • Names without a namespace prefix belong to the same namespace as the identifier of the current node. Inside a grouping, that namespace is affected by where the grouping is used (see Section 7.12).
  • The function library is the core function library defined in [XPATH], and a function “current()” that returns a node set with the initial context node.
  • The set of variable bindings is empty.

The mechanism for handling unprefixed names is adopted from XPath 2.0 [XPATH2.0], and helps simplify XPath expressions in YANG. No ambiguity may ever arise because YANG node identifiers are always qualified names with a non-null namespace URI.

The context node varies with the YANG XPath expression, and is specified where the YANG statement with the XPath expression is defined.

6.5 Schema Node Identifier

這一塊可是重中之重啊,在ODL的YANGTools中,首先要做的就是解析參數爲SchemaNodeIdentifier。

一個schema node identifier是一個string,表明了schema tree中的一個節點。它有兩種表達形式,“absolute”(絕對路徑)和“descendant”(相對路徑),其規則分別由Section 12中的“absolute-schema-nodeid”和“descendant-schema-nodeid”制定。一個shema node identifier是由用斜槓(“/”)分隔的不同id組合而成的path組成的。在一個absolute schema node identifier中,第一個斜槓後面的第一個identifier是本module或所有其它被導入的modules的頂級schema node。

定義在外部modules的對identifiers的引用 MUST 使用合適的前綴描述,在當前module以及它的submodules中引用的identifiers MSY 使用前綴。

比如,爲了表示在頂級節點“a”下的子節點“b”,可以使用字符串“/a/b”。

7 YANG Statements

接下來的小節描述了所有的YANG statements。

需要明確一點,即便是在YANG中沒有定義任何substatements的statement也能有設備商制定的擴展作爲substatements。比如,“description”聲明在YANG定義中沒有任何substatements,但是下面的寫法是合法的:

 description "some text" {
     acme:documentation-flag 5;
 }
  • 1
  • 2
  • 3
  • 4

7.1 Module Statement

“module”聲明定義了module的名字,將所有屬於該module的聲明都集中在一起。“module”聲明的參數就是該module的名字,後面跟着一塊substatements,其中包含了該module具體的信息。module的名字服從Section 6.2中針對identifiers的規則。

在RFC streams 【RFC 
4844
】中發佈的modules的名字 MUST 由IANA分配,可見Section 14。

私有的module的名字是由擁有該module的組織分配的。 RECOMMENDED 私有module的名字和標準中的modules以及其它組織的module沒有命名衝突。

一個module的典型佈局如下:

 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>
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

7.1.1 module的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | augment      | 7.15    | 0..n        |
             | choice       | 7.9     | 0..n        |
             | contact      | 7.1.8   | 0..1        |
             | container    | 7.5     | 0..n        |
             | description  | 7.19.3  | 0..1        |
             | deviation    | 7.18.3  | 0..n        |
             | extension    | 7.17    | 0..n        |
             | feature      | 7.18.1  | 0..n        |
             | grouping     | 7.11    | 0..n        |
             | identity     | 7.16    | 0..n        |
             | import       | 7.1.5   | 0..n        |
             | include      | 7.1.6   | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | namespace    | 7.1.3   | 1           |
             | notification | 7.14    | 0..n        |
             | organization | 7.1.7   | 0..1        |
             | prefix       | 7.1.4   | 1           |
             | reference    | 7.19.4  | 0..1        |
             | revision     | 7.1.9   | 0..n        |
             | rpc          | 7.13    | 0..n        |
             | typedef      | 7.3     | 0..n        |
             | uses         | 7.12    | 0..n        |
             | yang-version | 7.1.2   | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

上面的0..1,表示可以出現0次到1次,0..n表示可以出現任意次數,1表示能且僅能出現一次。

7.1.2 yang-version聲明

“yang-version”是可選的,指定了本module使用的YANG語言的版本號。這個聲明的參數是一個字符串。如果出現,它必須包含值“1”,這是YANG語言目前的版本號,也是默認的版本號。

version 1.1已經有了。不過還不知道是哪個RFC。

對於值非“1”的“yang-version”的處理超出了本文檔的討論範圍。任何定義更高版本的文檔都需要保持版本向前兼容。

7.1.3 namespace聲明

“namespace”聲明定義了module中所有的identifiers所屬的XML namespace,除了定義在一個grouping中的data node identifiers以外(見Section 7.12)。它的參數是這個namespace的URI。

詳情可減Section 5.3。

7.1.4 prefix聲明

“prefix”聲明唄用來定義和module以及它的namespace相關聯的前綴。“prefix”聲明的參數是一個前綴字符串。這個字符串 MAY 指向包含在本module中的定義,比如“if:ifName”。prefix遵循和identifier相同的規則(見Section 6.2)。

當在“module”聲明中使用它時,“prefix”聲明定義了當該module被其它module導入時需要使用的前綴。爲了提高NETCONF XML的可讀性,一個使用該前綴生成XML或者XPath的NETCONF的客戶端或者服務端 SHOULD 使用這個前綴,除非出現了衝突。(To improve readability of the NETCONF XML, a NETCONF client or server that generates XML or XPath that use prefixes SHOULD use the prefix defined by the module, unless there is a conflict.

當在“import”聲明中使用它時,“prefix”聲明定義了訪問被導入module中的定義時需要使用的前綴。當需要引用一個被導入module的identifier時,被導入module的前綴字符串會被放在identifier前面,用冒號隔開,比如“if:ifIndex”。爲了提高YANG modules的可讀性,module中定義的prefix SHOULD 在該module被導入時使用,除非出現了prefix conflict。如果出現了衝突,比如兩個擁有同樣prefix名的不同的modules同時被導入,則至少有一個 MUST 改變其prefix。

所有的prefixes,包括module自己本身的prefix,都 MUST 在該module或者submodule內部保持唯一。

這裏用了module或者submodule內部保持唯一。

7.1.5 import聲明

“import”聲明使得一個module的定義能夠在另一個module或submodule內部被使用。它的參數是被導入的module的名字,其後跟着一塊包含具體導入信息的substatements。當一個module被導入時,導入它的module可能:

  • 使用被導入module或者它的submodules中的任何grouping和typedef。
  • 使用被導入module或者它的submodules中的任何extension,feature,以及identity。
  • 使用被導入module的schema tree中的“must”,“path”,以及“when”聲明中的任何node,或者作爲“augment”和“deviation”聲明的target node。

The mandatory “prefix” substatement assigns a prefix for the imported module that is scoped to the importing module or submodule. Multiple “import” statements may be specified to import from different modules.

當可選的“revision-date” substatement在“import”聲明中出現時,任何本地module的定義中引用的typedef,grouping,extension,feature以及identity都是從指定revision的module中導入的。如果指定的revision不存在,則會出現錯誤。如果沒有“revision-date”出現,則導入的module的revision不確定。

對於同一個module的多個revisions的導入是 MUST NOT 的。

                    The import's Substatements

             +---------------+---------+-------------+
             | substatement  | section | cardinality |
             +---------------+---------+-------------+
             | prefix        | 7.1.4   | 1           |
             | revision-date | 7.1.5.1 | 0..1        |
             +---------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
7.1.5.1 import的revision-date聲明

“revision-date”聲明用來指定module的具體版本號。其值 MUST 和被導入module的“revision”聲明的值匹配。

7.1.6 include聲明

“include”聲明被用來將某個submodule的內容對於其父module,或者父module之下的其他submodule可用。其參數是一個identifier,表示被包含的submodule的名字。modules只能包含屬於它的用“belongs-to”聲明定義的submodules,submodules只能包含和它屬於同一個module的其他submodule。

當一個module包含了一個submodule,它就會將這個submodule的內容組合進本module的node hierarchy中。當一個submodule包含了另一個submodule,則另一個submodule的定義對於當前的submodule就是可用的。

當可選的“revision-date” substatement出現,指定revision的submodule會被包含到module中。如果指定revision的submodule不存在,則會出現錯誤。如果沒有“revision-date” substatement出現,則沒有定義哪個revision的submodule會被包含。

對於同一個submodule的多個revisions的導入是 MUST NOT 的。

                   The includes's Substatements

             +---------------+---------+-------------+
             | substatement  | section | cardinality |
             +---------------+---------+-------------+
             | revision-date | 7.1.5.1 | 0..1        |
             +---------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

7.1.7 organization聲明

“organization”聲明定義了對該module負責的團體名。其參數是特定組織的文本描述的字符串。

7.1.8 contact聲明

“contact”聲明提供了該module的相關聯繫信息。該參數是一個字符串,包含了指定聯繫人的名字,郵件地址,電話號碼,電子郵箱等信息,技術相關的疑問都可以諮詢他。

7.1.9 revision聲明

“revision”聲明指定了該module的編輯版本歷史,包括最初的一版。一系列的revision聲明能夠詳細描述該module定義上發生的改變細節。其參數是一個日期字符串,格式爲“YYYY-MM-DD”,後面跟着一塊包含詳細revision信息的substatements。一個module SHOULD 至少有一個初始的“revision”聲明。對於每次發佈的修改,都 SHOULD 增加一個revision。

7.1.9.1 revision的substatement
             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | description  | 7.19.3  | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

7.1.10 使用用例

 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: [email protected]";

     description
         "The module for entities implementing the ACME protocol.";

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

     // definitions follow...
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

7.2 submodule聲明

YANG中最基本的單位是module,一個YANG module本身能夠由多個submodules構成。submodules的存在使得module設計者能夠將一個複雜的model分割成多個共用同一個namespace的submodules,而namespace是由module定義的。

“submodule”聲明定義了submodule的名字,將屬於該submodule的所有聲明都整合到了一起。其參數是submodule的名字,後面跟着相關的詳細substatements信息。submodule名字遵從identifiers的規則,可見Section 6.2。

在RFC streams 【RFC4844】中發佈的submodules的名字都 MUST 由IANA分配,可見Section 14。

Private submodule names are assigned by the organization owning the 
submodule without a central registry. It is RECOMMENDED to choose 
submodule names that will have a low probability of colliding with 
standard or other enterprise modules and submodules, e.g., by using 
the enterprise or organization name as a prefix for the submodule 
name.

一個經典的submodule的文本佈局如下:

 submodule <module-name> {

     <yang-version statement>

     // module identification
     <belongs-to 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>
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

7.2.1 submodule的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | augment      | 7.15    | 0..n        |
           * | belongs-to   | 7.2.2   | 1           | 
             | choice       | 7.9     | 0..n        |
             | contact      | 7.1.8   | 0..1        |
             | container    | 7.5     | 0..n        |
             | description  | 7.19.3  | 0..1        |
             | deviation    | 7.18.3  | 0..n        |
             | extension    | 7.17    | 0..n        |
             | feature      | 7.18.1  | 0..n        |
             | grouping     | 7.11    | 0..n        |
             | identity     | 7.16    | 0..n        |
             | import       | 7.1.5   | 0..n        |
             | include      | 7.1.6   | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | notification | 7.14    | 0..n        |
             | organization | 7.1.7   | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | revision     | 7.1.9   | 0..n        |
             | rpc          | 7.13    | 0..n        |
             | typedef      | 7.3     | 0..n        |
             | uses         | 7.12    | 0..n        |
             | yang-version | 7.1.2   | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

和module相比,多了一個belongs-to,少了一個prefix。

7.2.2 belongs-to聲明

“belongs-to”聲明指定了submodule所屬的module。其參數是module名字。

一個submodule MUST 只能被它所屬的module,或者被它所屬的module的其它submodules包含。

“belongs-to”聲明有一個必須出現的“prefix”聲明,該聲明指定了所屬的module的prefix。在本地submodule中的所有定義,以及它所包含的submodules都能通過這個prefix訪問。

                  The belongs-to's Substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | prefix       | 7.1.4   | 1           |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

7.2.3 使用用例

 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: [email protected]";

     description
         "This submodule defines common ACME types.";

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

     // definitions follows...
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

7.3 typedef聲明

根據Section 5.5中的規則,“typedef”聲明定義了一個新的type,能夠在module內部,包含該module的modules或submodules,以及導入該module的其它modules使用。新的type稱爲“derived type”(派生類型),被派生的類型稱爲“base type”(基本類型)。所有的派生類型都能最重追溯到YANG的內置類型。

“typedef”聲明的參數是一個identifier,該id就是新定義的類型的名字,其後面 MUST 跟着包含typedef詳細信息的一塊substatements。

這個type的名字 MUST NOT 是YANG的內置類型。如果typedef定義在YANG module或submodule的top level,則其名字 MUST 在整個module中保持唯一。

7.3.1 typedef的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | default      | 7.3.4   | 0..1        |
             | description  | 7.19.3  | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | type         | 7.3.2   | 1           |
             | units        | 7.3.3   | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

7.3.2 typedef的type聲明

“type”聲明 MSUT 出現在typedef中,定義了新定義type所派生的基本類型。可見Section 7.4。

7.3.3 units聲明

“units”聲明是可選的,其內容是一個字符串,包含了和這個type相關的units的文本定義。

7.3.4 typedef的default聲明

“default”聲明的參數是新的type的默認值。

“default”聲明的值 MUST 是有效的。

如果base type有一個默認值,新的派生類型沒有指定新的默認值,則base type的默認值也是新的派生類型的默認值。

如果這個type的默認值,在派生類型或者leaf的定義中,根據相關restrictions,是無效的,則派生類型或leaf定義就 MUST 指定一個新的默認值,以匹配restrictions。

7.3.5 使用用例

 typedef listen-ipv4-address {
     type inet:ipv4-address;
     default "0.0.0.0";
 }
  • 1
  • 2
  • 3
  • 4
  • 5

7.4 type聲明

“type”聲明的參數是YANG的內置類型(見Section 9)或者派生類型(見Section 7.3),後面跟着可選的一塊substatements,用於進一步對該type施加限制(restrictions)。

所有內置類型能夠使用的restriction聲明取決於被限定的類型。

7.4.1 type的substatements

           +------------------+---------+-------------+
           | substatement     | section | cardinality |
           +------------------+---------+-------------+
           | bit              | 9.7.4   | 0..n        |
           | enum             | 9.6.4   | 0..n        |
           | length           | 9.4.4   | 0..1        |
           | path             | 9.9.2   | 0..1        |
           | pattern          | 9.4.6   | 0..n        |
           | range            | 9.2.4   | 0..1        |
           | require-instance | 9.13.2  | 0..1        |
           | type             | 7.4     | 0..n        |
           +------------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

沒清楚這裏使用type有什麼意義?需要例子。

7.5 constainer聲明

“container”聲明被用來定義一個schema tree中包含的內部數據節點(interior data node)。它有一個參數,是一個identifier,後面跟着一塊描述進詳細信息的substatements。

一個container節點沒有一個值,但是在data tree中有一個列表的子節點。子節點都定義在container的substatements中。

7.5.1 Containers with Presence

YANG支持兩種風格的containers,一種僅僅用於組織data nodes的垂直結構,一種出現在configuration中,有明確的意義。

第一種風格中,container本身沒有任何意義,它的存在僅僅是爲了包含子節點。這是默認的風格。

比如,同步光網絡(SONET)的scrambling options的集合能被放到一個名爲“scrambling”的container中,以增強配置結構的層次化,將這些節點整合到一起。這個“scrambling”節點本身沒有意義,所以在它變成空的的時候可以移除該節點。

在第二種風格中,container本身就是配置型數據(configuration)data,表示配置型數據的一個簡單bit。The container acts as both a configuration knob and a means of organizing related configuration. 這些containers的創建和刪除操作都必須是明確無誤的。

YANG稱這種風格的container爲一個“presence container”,這表示要使用“presence”聲明,作爲它的

比如,一個“ssh”的container可能會啓動使用ssh方式將日誌寫進設備的能力,不過也能包含任何和ssh相關的configuration knobs,比如連接速率和重試次數限制。

“presence”聲明(見Section 7.5.5)用來在data tree中給container的存在以語義。

說這麼多,都不如一個demo來的實在。真的是沒看懂啊。

7.5.2 container的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | choice       | 7.9     | 0..n        |
             | config       | 7.19.1  | 0..1        |
             | container    | 7.5     | 0..n        |
             | description  | 7.19.3  | 0..1        |
             | grouping     | 7.11    | 0..n        |
             | if-feature   | 7.18.2  | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | must         | 7.5.3   | 0..n        |
             | presence     | 7.5.5   | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | typedef      | 7.3     | 0..n        |
             | uses         | 7.12    | 0..n        |
             | when         | 7.19.5  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

7.5.3 must聲明

“must”聲明是可選的,其參數是一個字符串包含了一個XPath表達式(見Section 6.4)。它被用來正式聲明有效數據上的約束。約束根據Section 8的規則執行。

當一個datastore可用時,所有的“must”約束都會對data tree中的每個data node,對於使用默認值的所有leafs(見Section 7.6.1)進行概念上的評估。如果一個data node在data tree中並不存在,並且沒有一個默認值,則它的“must”聲明不會被評估。(When a datastore is validated, all “must” constraints are conceptually evaluated once for each data node in the data tree, and for all leafs with default values in use (see Section 7.6.1). If a data node does not exist in the data tree, and it does not have a default value, its “must” statements are not evaluated.

所有這樣的約束 MUST 評估爲true,這樣data纔是有效的。

XPath表達式在下述的上下文,以及Section 6.4.1的定義中也要進行概念上的評估(conceptually evaluated):

  • The context node is the node in the data tree for which the “must” statement is defined.
  • The accessible tree is made up of all nodes in the data tree, and all leafs with default values in use (see Section 7.6.1).

可訪問的tree取決於context node:

  • If the context node represents configuration, the tree is the data in the NETCONF datastore where the context node exists. The XPath root node has all top-level configuration data nodes in all modules as children.
  • If the context node represents state data, the tree is all state data on the device, and the datastore. The XPath root node has all top-level data nodes in all modules as children.
  • If the context node represents notification content, the tree is the notification XML instance document. The XPath root node has the element representing the notification being defined as the only child.
  • If the context node represents RPC input parameters, the tree is the RPC XML instance document The XPath root node has the element representing the RPC operation being defined as the only child.
  • If the context node represents RPC output parameters, the tree is the RPC reply instance document. The XPath root node has the elements representing the RPC output parameters as children.

使用標準的XPath規則評估的XPath表達式的結果會被轉化爲一個boolean值。

Note that since all leaf values in the data tree are conceptually stored in their canonical form (see Sections 7.6 and 7.7), any XPath comparisons are done on the canonical value.

Also note that the XPath expression is conceptually evaluated. This means that an implementation does not have to use an XPath evaluator on the device. How the evaluation is done in practice is an implementation decision.

7.5.4 must的substatements

             +---------------+---------+-------------+
             | substatement  | section | cardinality |
             +---------------+---------+-------------+
             | description   | 7.19.3  | 0..1        |
             | error-app-tag | 7.5.4.2 | 0..1        |
             | error-message | 7.5.4.1 | 0..1        |
             | reference     | 7.19.4  | 0..1        |
             +---------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
7.5.4.1 error-message聲明

“error-message”聲明是可選的,其參數是一個字符串。如果約束的評估結果爲false,這個字符串會被放在的中。

7.5.4.2 error-app-tag聲明

“error-app-tag”聲明是可選的,其參數是一個字符串。如果約束的評估結果爲false,這個字符串會被放在的中。

7.5.4.3 must和error-message的使用用例
 container interface {
     leaf ifType {
         type enumeration {
             enum ethernet;
             enum atm;
         }
     }
     leaf ifMTU {
         type uint32;
     }
     must "ifType != 'ethernet' or " +
          "(ifType = 'ethernet' and ifMTU = 1500)" {
         error-message "An ethernet MTU must be 1500";
     }
     must "ifType != 'atm' or " +
          "(ifType = 'atm' and ifMTU <= 17966 and ifMTU >= 64)" {
         error-message "An atm MTU must be  64 .. 17966";
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

7.5.5 presence聲明

“presence”聲明指定了在data tree中一個container的presence的含義。它的參數是一個字符串,包含了node的presence means的文本描述。

如果一個container有“presence”聲明,則存在於data tree中的該container就是有意義的。否則,該container就是第一類型的container,僅僅用於將數據結構化,本身並不攜帶任何意義。

更多信息可見Section 7.5.1。

簡單來說,這個聲明存在的意義就是用來判別container是第一類還是第二類的。不過沒有見到哪個文檔裏有具體的實現啊。

7.5.6 container的child node聲明

在一個container中,child nodes可以是“container”,“leaf”,“list”,“leaf-list”,“uses”,“choice”,以及“anyxml”聲明。

7.5.7 XML 映射規則

一個container節點被編碼爲一個XML element。這個element的local name就是container的identifier,它的namespace就是module的XML namespace(見Section 7.1.3)。

container的child nodes被編碼爲container element的subelements。如果container定義了RPC input或output參數,這些subelements被編碼的順序和它們在“container”聲明中定義的順序一致。否則,subelements的編碼順序隨意。

一個NETCONF服務端在回覆一個或請求的時候,如果container node沒有“presence”聲明並且沒有child nodes存在,則 MAY 不會發送這個container element作爲回覆。因此,一個發送或後獲得回覆的客戶端,必須能夠處理一種情況,那就是在XML中沒有不包含“presence”聲明的container node。

涉及到NETCONF的時候就一臉蒙逼。

7.5.8 NETCONF 操作

containers可以通過在中使用“operation”屬性(見【RFC4741】 Section 7.2)被創建,刪除,替換和修改。

如果一個container沒有包含“presence”聲明,並且最後一個child node都被刪除了,則NETCONF服務端 MAY 刪除這個container。當一個NETCONF服務端處理一個請求的時候,container node的處理流程如下:

  • 如果operation是“merge”或者“replace”,當該node不存在時則會被創建。
  • 如果operation是“create”,當該node不存在時會被創建。如果該node已經存在了,則會返回一個“data-exists”錯誤。
  • 如果operation是“delete”,當該node存在時會被哦刪除。如果該node不存在,則會返回“data-missing”錯誤。

7.5.9 使用用例

給出下面的container的定義:

 container system {
     description "Contains various system parameters";
     container services {
         description "Configure externally available services";
         container "ssh" {
             presence "Enables SSH";
             description "SSH service specific configuration";
             // more leafs, containers and stuff here...
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

對應的XML實例爲:

 <system>
   <services>
     <ssh/>
   </services>
 </system>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

由於 element出現了,所以ssh是enabled的。

使用刪除一個container:

 <rpc message-id="101"
      xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
      xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
   <edit-config>
     <target>
       <running/>
     </target>
     <config>
       <system xmlns="http://example.com/schema/config">
         <services>
           <ssh nc:operation="delete"/>
         </services>
       </system>
     </config>
   </edit-config>
 </rpc>     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

7.6 leaf聲明

“leaf”聲明被用來在schema tree中定義一個leaf node。它只有一個參數,是identifier,後面跟着詳細描述該leaf信息的一塊substatements。

一個leaf node有一個值,但是在data tree中沒有child nodes。概念上將,data tree中的值總是以canonical form存在的(見Section 9.1)。

在data tree中存在0個或者1個leaf node。

“leaf”聲明被用來定義一個特定類型的標量變量。

7.6.1 leaf的默認值(default value)

一個leaf的默認值是當在data tree中沒有該leaf存在時,服務端採用的值。默認值的採用取決於schema tree中離該leaf最近的帶有“presence” 的container的祖先節點:

  • 如果在schema tree中沒有這樣的祖先節點,則默認值 MUST 被使用
  • 否則,如果這個祖先節點是一個case node,則如果data tree中有任何該case的node存在,或者這個case node就是choice的默認case,並且data tree中沒有任何其它的case存在,這樣一來就必須使用默認值。
  • 再否則,如果在data tree中有這樣的祖先節點存在,則默認值 MUST 被使用。

表示完全看不懂上面說了些啥?並且不明白爲什麼這麼設置。

在這些例子中,默認值都要被使用。

當默認值被使用的時候,服務端 MUST 表現得好像這個值爲默認值的這個leaf node就存在於data tree中一樣。

如果一個leaf有一個“default”聲明,則該leaf的默認值就是“default”聲明指定的值。否則,如果leaf的type有一個默認的值,並且該leaf不是強制出現(mandatory)的,則該leaf的默認值就是該type的默認值。在所有其它情況下,這個leaf沒有一個默認值。

7.6.2 leaf的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | config       | 7.19.1  | 0..1        |
             | default      | 7.6.4   | 0..1        |
             | description  | 7.19.3  | 0..1        |
             | if-feature   | 7.18.2  | 0..n        |
             | mandatory    | 7.6.5   | 0..1        |
             | must         | 7.5.3   | 0..n        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | type         | 7.6.3   | 1           |
             | units        | 7.3.3   | 0..1        |
             | when         | 7.19.5  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

7.6.3 leaf的type聲明

“type”聲明, MUST要出現,有一個參數,是當前已有的內置或者佩聲類型。在這個type上有可選的substatements指定了相關的restrictions。可見Section 7.4。

7.6.4 leaf的default聲明

“default”聲明,是可選的,其參數是一個字符串,包含了leaf的默認值。

“default”聲明的值 MUST是有效可用的,不能違背對應type的規則。

如果“mantory”爲true,則“default”聲明 MUST NOT 不能出現在nodes中。

7.6.5 leaf的mandatory聲明

The “mandatory” statement, which is optional, takes as an argument 
the string “true” or “false”, and puts a constraint on valid data. 
If not specified, the default is “false”.

If “mandatory” is “true”, the behavior of the constraint depends on 
the type of the leaf’s closest ancestor node in the schema tree that 
is not a non-presence container (see Section 7.5.1):

o If no such ancestor exists in the schema tree, the leaf MUST 
exist.

o Otherwise, if this ancestor is a case node, the leaf MUST exist if 
any node from the case exists in the data tree.

o Otherwise, the leaf MUST exist if the ancestor node exists in the 
data tree.

This constraint is enforced according to the rules in Section 8.

7.6.6 XML映射規則

  A leaf node is encoded as an XML element.  The element's local name
  • 1
  • 2

is the leaf’s identifier, and its namespace is the module’s XML 
namespace (see Section 7.1.3).

The value of the leaf node is encoded to XML according to the type, 
and sent as character data in the element.

A NETCONF server that replies to a or request MAY 
choose not to send the leaf element if its value is the default 
value. Thus, a client that receives an for a or 
request, MUST be prepared to handle the case that a leaf 
node with a default value is not present in the XML. In this case, 
the value used by the server is known to be the default value.

See Section 7.6.8 for an example.

7.6.7 NETCONF Operations

When a NETCONF server processes an request, the 
elements of procedure for the leaf node are:

  If the operation is "merge" or "replace", the node is created if
  it does not exist, and its value is set to the value found in the
  XML RPC data.

  If the operation is "create", the node is created if it does not
  exist.  If the node already exists, a "data-exists" error is
  returned.

  If the operation is "delete", the node is deleted if it exists.
  If the node does not exist, a "data-missing" error is returned.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

7.6.8 使用實例

給定下面的“leaf”聲明,放到之前定義的 “ssh”的container中(可見Section 7.5.9):

 leaf port {
     type inet:port-number;
     default 22;
     description "The port to which the SSH server listens"
 }      
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

對應的XML實例爲:

 <port>2022</port>
  • 1
  • 2

在中設置該leaf的值:

 <rpc message-id="101"
      xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
      xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
   <edit-config>
     <target>
       <running/>
     </target>
     <config>
       <system xmlns="http://example.com/schema/config">
         <services>
           <ssh>
             <port>2022</port>
           </ssh>
         </services>
       </system>
     </config>
   </edit-config>
 </rpc>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

7.7 leaf-list聲明

“leaf”聲明是被用來定義一個簡單的特定類型的標量變量,而“leaf-list”聲明被用來定義特定類型的一個數組。“leaf-list”聲明有一個參數,是一個identifier,後面跟着描述具體內容的一塊substatements。

“leaf-list”的值 MUST 是唯一的。

概念上來講,data tree中的值總是以canonical form存在的(見Section 9.1)。

如果“leaf-list”引用的type有默認值,默認值對leaf-list產生什麼影響(If the type referenced by the leaf-list has a default value, it has no effect in the leaf-list.)。

7.7.1 排序

對於“list”和“leaf-list”聲明,YANG支持兩種風格的排序方式。在很多lists中,爲了使被排列的列表項不影響列表配置的具體實現,設備能夠以任何合理的順序給list的列表項進行排序。不過在“description”中可能會有關於排序的建議。YANG稱這種風格爲“system ordered”,這種排序的聲明爲“ordered-by system”。

比如,有時候爲了對到來的流量進行過濾,防火牆的過濾條件列表項的順序就變得有用。用戶可能需要決定丟棄所有TCP流量的過濾項是放在允許信任接口流量通過的過濾項之前還是之後。這時候對於列表的排序就至關重要了。

YANG爲NETCONF的操作提供了豐富的特性集以便列表能夠以用戶規定的方式進行排序。列表項可能會被插入,或重新排列到列表的第一項或最後一項,或者放到某一個特定列表項的前面或者後面。

“ordered-by”聲明在Section 7.7.5 中有所包含。

7.7.2 leaf-list的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | config       | 7.19.1  | 0..1        |
             | description  | 7.19.3  | 0..1        |
             | if-feature   | 7.18.2  | 0..n        |
             | max-elements | 7.7.4   | 0..1        |
             | min-elements | 7.7.3   | 0..1        |
             | must         | 7.5.3   | 0..n        |
             | ordered-by   | 7.7.5   | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | type         | 7.4     | 1           |
             | units        | 7.3.3   | 0..1        |
             | when         | 7.19.5  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

7.7.3 min-elements聲明

“min-elements”聲明,是可選的,取值爲一個非負的整型,是對有效列表項的一個約束。一個可用的“leaf-list”或者“list” MUST 至少有min-elements個列表項。

如果該聲明不存在,則默認爲0。

The behavior of the constraint depends on the type of the leaf-list’s 
or list’s closest ancestor node in the schema tree that is not a non- 
presence container (see Section 7.5.1):

o If this ancestor is a case node, the constraint is enforced if any 
other node from the case exists.

o Otherwise, it is enforced if the ancestor node exists.

The constraint is further enforced according to the rules in 
Section 8.

7.7.4 max-elements聲明

The “max-elements” statement, which is optional, takes as an argument 
a positive integer or the string “unbounded”, which puts a constraint 
on valid list entries. A valid leaf-list or list always has at most 
max-elements entries.

If no “max-elements” statement is present, it defaults to 
“unbounded”.

The “max-elements” constraint is enforced according to the rules in 
Section 8.

7.7.5 ordered-by聲明

“ordered-by”聲明定義了列表中列表項的順序是用戶定義還是系統自定義。其參數是“system”和“user”中的一個。如果該聲明沒有出現,默認值是“system”。

如果列表表達的是state date,RPC output parameters,或者notification content,則這個聲明會被忽略,因爲對以上三種數據,都沒有排序的必要。

更多信息可見Section 7.7.1

7.7.5.1 ordered-by system

The entries in the list are sorted according to an unspecified order. 
Thus, an implementation is free to sort the entries in the most 
appropriate order. An implementation SHOULD use the same order for 
the same data, regardless of how the data were created. Using a 
deterministic order will make comparisons possible using simple tools 
like “diff”.

This is the default order.

7.7.5.2 ordered-by user

列表項的排序是用戶通過中的特殊XML屬性控制的。可見Section 7.7.7

7.7.6 XML映射規則

A leaf-list node is encoded as a series of XML elements. Each 
element’s local name is the leaf-list’s identifier, and its namespace 
is the module’s XML namespace (see Section 7.1.3).

The value of each leaf-list entry is encoded to XML according to the 
type, and sent as character data in the element.

The XML elements representing leaf-list entries MUST appear in the 
order specified by the user if the leaf-list is “ordered-by user”; 
otherwise, the order is implementation-dependent. The XML elements 
representing leaf-list entries MAY be interleaved with other sibling 
elements, unless the leaf-list defines RPC input or output 
parameters.

See Section 7.7.8 for an example.

7.7.7 NETCONF 操作

Leaf-list entries can be created and deleted, but not modified, 
through , by using the “operation” attribute in the 
leaf-list entry’s XML element.

In an “ordered-by user” leaf-list, the attributes “insert” and 
“value” in the YANG XML namespace (Section 5.3.1) can be used to 
control where in the leaf-list the entry is inserted. These can be 
used during “create” operations to insert a new leaf-list entry, or 
during “merge” or “replace” operations to insert a new leaf-list 
entry or move an existing one.

The “insert” attribute can take the values “first”, “last”, “before”, 
and “after”. If the value is “before” or “after”, the “value” 
attribute MUST also be used to specify an existing entry in the leaf- 
list.

If no “insert” attribute is present in the “create” operation, it 
defaults to “last”.

If several entries in an “ordered-by user” leaf-list are modified in 
the same request, the entries are modified one at the 
time, in the order of the XML elements in the request.

In a , or an with a “replace” operation 
that covers the entire leaf-list, the leaf-list order is the same as 
the order of the XML elements in the request.

When a NETCONF server processes an request, the 
elements of procedure for a leaf-list node are:

  If the operation is "merge" or "replace", the leaf-list entry is
  created if it does not exist.

  If the operation is "create", the leaf-list entry is created if it
  does not exist.  If the leaf-list entry already exists, a
  "data-exists" error is returned.

  If the operation is "delete", the entry is deleted from the leaf-
  list if it exists.  If the leaf-list entry does not exist, a
  "data-missing" error is returned.   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

7.7.8 使用用例

 leaf-list allow-user  {
     type string;
     description "A list of user name patterns to allow";
 }
  • 1
  • 2
  • 3
  • 4
  • 5

對應的XML實例:

 <allow-user>alice</allow-user>
 <allow-user>bob</allow-user>
  • 1
  • 2
  • 3

爲了在列表中增加一個新元素,使用中的操作“merge”:

 <rpc message-id="101"
      xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
      xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
   <edit-config>
     <target>
       <running/>
     </target>
     <config>
       <system xmlns="http://example.com/schema/config">
         <services>
           <ssh>
             <allow-user>eric</allow-user>
           </ssh>
         </services>
       </system>
     </config>
   </edit-config>
 </rpc>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

給定下面的用戶排序的例子:

 leaf-list cipher  {
     type string;
     ordered-by user;
     description "A list of ciphers";
 }                
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

下面的語句是要在“3des-cbc”後面插入一條新的cipher “blowfish-cbc”:

 <rpc message-id="101"
      xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
      xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
      xmlns:yang="urn:ietf:params:xml:ns:yang:1">
   <edit-config>
     <target>
       <running/>
     </target>
     <config>
       <system xmlns="http://example.com/schema/config">
         <services>
           <ssh>
             <cipher nc:operation="create"
                     yang:insert="after"
                     yang:value="3des-cbc">blowfish-cbc</cipher>
           </ssh>
         </services>
       </system>
     </config>
   </edit-config>
 </rpc>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

7.8 list聲明

“list”聲明被用來定義一個schema tree中的內部數據節點(interior data node)。一個list node在data tree中可能有多個實例存在。每個這樣的實例都被認爲是一個列表項。“list”聲明有一個參數,是identifier,後面跟着描述更詳細信息的一塊substatements。

一個列表項是由該列表的keys的值唯一指定的,前提是keys存在。

7.8.1 list的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | choice       | 7.9     | 0..n        |
             | config       | 7.19.1  | 0..1        |
             | container    | 7.5     | 0..n        |
             | description  | 7.19.3  | 0..1        |
             | grouping     | 7.11    | 0..n        |
             | if-feature   | 7.18.2  | 0..n        |
             | key          | 7.8.2   | 0..1        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | max-elements | 7.7.4   | 0..1        |
             | min-elements | 7.7.3   | 0..1        |
             | must         | 7.5.3   | 0..n        |
             | ordered-by   | 7.7.5   | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | typedef      | 7.3     | 0..n        |
             | unique       | 7.8.3   | 0..n        |
             | uses         | 7.12    | 0..n        |
             | when         | 7.19.5  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

7.8.2 list的key聲明

“key”聲明,如果該list表示的是configuration信息,則 MUST 存在;其他情況下,則MAY 存在。有一個字符串的參數,該字符串是一個用空格符作爲分隔符的這個list中的leaf的identifiers的列表。在key中,一個leaf的identifier MUST NOT 出現超過一次。每個這樣的leaf identifier MUST 是該list的child leaf中的一個。這個leafs能直接在list的substatements中定義,也可以在list中的groupings裏使用。

在key中指定的所有leafs的值的組合唯一確定了一個列表項(感覺有點類似於數據庫中的聯合主鍵)。當一個列表項被創建時,所有的key leafs都 MUST 被賦值。這樣一來,在key leafs中的任何默認值都會被忽略。key leafs中的任何mandatory statement都會被忽略。

不太明白啥意思。附上原文:Thus, any default values in the key leafs or their types are ignored. It also implies that any mandatory statement in the key leafs are ignored.

作爲key的一部分的一個leaf能夠是任何內置類型或者派生類型,但是 MUST NOT 是內置類型“empty”。

All key leafs in a list MUST have the same value for their “config” as the list itself.

key的字符串的語法是Section 12中的“key-arg”規則定義的。

7.8.3 list的unique聲明

“unique”聲明被用來對有效的列表項施加約束的。它有一個參數,是一個字符串。該字符串中包含了schema node identifiers的以空格爲分隔符的列表,這些ids MUST 是descendant form的形式(見Section 12中的“descendant-schema-nodeid”規則)。每個這樣的schema node identifier MUST 指向一個leaf。

如果被引用的leafs中有一個是configuration data,則所有被引用的leafs都 MUST 表示configuration data。

“unique”約束指定:所有在參數字符串中指定的leafs的實例的值,包括那些使用默認值的leafs,都 MUST 在所有列表項實例中保證唯一。這個約束根據Section 8的規則強制執行。

“unique”字符串語法由Section 12中的“unique-arg”語法正式定義。

7.8.3.1 使用用例

假設有下面的list定義:

 list server {
     key "name";
     unique "ip port";
     leaf name {
         type string;
     }
     leaf ip {
         type inet:ip-address;
     }
     leaf port {
         type inet:port-number;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

則下面兩個configuration是無效的:

 <server>
   <name>smtp</name>
   <ip>192.0.2.1</ip>
   <port>25</port>
 </server>

 <server>
   <name>http</name>
   <ip>192.0.2.1</ip>
   <port>25</port>
 </server>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

下面的configuration是有效的,因爲“http”和“ftp”的list表項沒有實現所有被unique引用的leafs,因此在“unique”約束執行檢查的時候不會被約束掉:

 <server>
   <name>smtp</name>
   <ip>192.0.2.1</ip>
   <port>25</port>
 </server>

 <server>
   <name>http</name>
   <ip>192.0.2.1</ip>
 </server>

 <server>
   <name>ftp</name>
   <ip>192.0.2.1</ip>
 </server>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

7.8.4 list的child node statements

list的child nodes可以是”container”, “leaf”, “list”, “leaf-list”, “uses”, 
“choice”, 以及 “anyxml”。

7.8.5 XML映射規則

A list is encoded as a series of XML elements, one for each entry in 
the list. Each element’s local name is the list’s identifier, and 
its namespace is the module’s XML namespace (see Section 7.1.3).

The list’s key nodes are encoded as subelements to the list’s 
identifier element, in the same order as they are defined within the 
“key” statement.

The rest of the list’s child nodes are encoded as subelements to the 
list element, after the keys. If the list defines RPC input or 
output parameters, the subelements are encoded in the same order as 
they are defined within the “list” statement. Otherwise, the 
subelements are encoded in any order.

The XML elements representing list entries MUST appear in the order 
specified by the user if the list is “ordered-by user”, otherwise the 
order is implementation-dependent. The XML elements representing 
list entries MAY be interleaved with other sibling elements, unless 
the list defines RPC input or output parameters.

7.8.6 NETCONF 操作

List entries can be created, deleted, replaced, and modified through 
, by using the “operation” attribute in the list’s XML 
element. In each case, the values of all keys are used to uniquely 
identify a list entry. If all keys are not specified for a list 
entry, a “missing-element” error is returned.

In an “ordered-by user” list, the attributes “insert” and “key” in 
the YANG XML namespace (Section 5.3.1) can be used to control where 
in the list the entry is inserted. These can be used during “create” 
operations to insert a new list entry, or during “merge” or “replace” 
operations to insert a new list entry or move an existing one.

The “insert” attribute can take the values “first”, “last”, “before”, 
and “after”. If the value is “before” or “after”, the “key” 
attribute MUST also be used, to specify an existing element in the 
list. The value of the “key” attribute is the key predicates of the 
full instance identifier (see Section 9.13) for the list entry.

If no “insert” attribute is present in the “create” operation, it 
defaults to “last”.

If several entries in an “ordered-by user” list are modified in the 
same request, the entries are modified one at the time, 
in the order of the XML elements in the request.

In a , or an with a “replace” operation 
that covers the entire list, the list entry order is the same as the 
order of the XML elements in the request.

When a NETCONF server processes an request, the 
elements of procedure for a list node are:

  If the operation is "merge" or "replace", the list entry is
  created if it does not exist.  If the list entry already exists
  and the "insert" and "key" attributes are present, the list entry
  is moved according to the values of the "insert" and "key"
  attributes.  If the list entry exists and the "insert" and "key"
  attributes are not present, the list entry is not moved.

  If the operation is "create", the list entry is created if it does
  not exist.  If the list entry already exists, a "data-exists"
  error is returned.

  If the operation is "delete", the entry is deleted from the list
  if it exists.  If the list entry does not exist, a "data-missing"
  error is returned.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

7.8.7 使用用例

給定下面的一個list:

 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;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

對應的XML實例:

 <user>
   <name>fred</name>
   <type>admin</type>
   <full-name>Fred Flintstone</full-name>
 </user>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

創建一個新用戶“barney”:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <user nc:operation="create">
               <name>barney</name>
               <type>admin</type>
               <full-name>Barney Rubble</full-name>
             </user>
           </system>
         </config>
       </edit-config>
     </rpc>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

改變“fred”的類型爲“superuser”:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <user>
               <name>fred</name>
               <type>superuser</type>
             </user>
           </system>
         </config>
       </edit-config>
     </rpc>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

給定下面的ordered-by user list:

 list user {
     description "This is a list of users in the system.";
     ordered-by user;
     config true;

     key "name";

     leaf name {
         type string;
     }
     leaf type {
         type string;
     }
     leaf full-name {
         type string;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

下面的xml表示在用戶“fred”後面插入一個新用戶“barney”:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:yang="urn:ietf:params:xml:ns:yang:1">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config"
                xmlns:ex="http://example.com/schema/config">
             <user nc:operation="create"
                   yang:insert="after"
                   yang:key="[ex:name='fred']">
               <name>barney</name>
               <type>admin</type>
               <full-name>Barney Rubble</full-name>
             </user>
           </system>
         </config>
       </edit-config>
     </rpc>     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

下面的語句是將用戶“barney”移到用戶“fred”前面:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:yang="urn:ietf:params:xml:ns:yang:1">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config"
                xmlns:ex="http://example.com/schema/config">
             <user nc:operation="merge"
                   yang:insert="before"
                   yang:key="[ex:name='fred']">
               <name>barney</name>
             </user>
           </system>
         </config>
       </edit-config>
     </rpc>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

7.9 choice聲明

“choice”聲明定義了可選項的一個集合,同時只能有其中的一個存在。其參數是一個identifier,後面跟着描述具體信息的一塊substatements。這個identifier被用來在schema tree中標識這個choice node。choice node不會在data tree中存在。

一個choice由多個branches組成,這些branches是用“case” substatement定義的。每個branch都包含多個child nodes。在這些branches中同時最多隻能有其中一個branch的nodes能夠存在。

更多信息可見Section 8.3.2

7.9.1 choice的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | case         | 7.9.2   | 0..n        |
             | config       | 7.19.1  | 0..1        |
             | container    | 7.5     | 0..n        |
             | default      | 7.9.3   | 0..1        |
             | description  | 7.19.3  | 0..1        |
             | if-feature   | 7.18.2  | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | mandatory    | 7.9.4   | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | when         | 7.19.5  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

7.9.2 choice的case聲明

“case”聲明被用來定義choice的branches。它有一個參數,是identifier,後面跟着描述詳細信息的一塊substatements。

這個identifier被用來在schema tree中標識這個case node。在data tree中不存在case node。

在一個“case”聲明中,其child nodes可以用“anyxml”,“choice”, “container”,“leaf”, “list”,“leaf-list”,以及“uses”聲明。所有child nodes的identifiers都 MUST 在該choice的所有cases中保持唯一。例如,下面的定義就是非法的:

 choice interface-type {     // This example is illegal YANG
     case a {
         leaf ethernet { ... }
     }
     case b {
         container ethernet { ...}
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

YANG中有一種簡略的寫法,當branch中包含單個的“anyxml”,“container”,“leaf”,“list”或者“leaf-list”聲明的時候,“case”聲明可以省略。這種情況下,這個case的identifier和其中的聲明的identifier一樣。下面是一個例子:

 choice interface-type {
     container ethernet { ... }
 }
  • 1
  • 2
  • 3
  • 4

等價於:

 choice interface-type {
     case ethernet {
         container ethernet { ... }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在一個choice中,case identifier MUST 是唯一的。

7.9.2.1 case的substatements
             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | choice       | 7.9     | 0..n        |
             | container    | 7.5     | 0..n        |
             | description  | 7.19.3  | 0..1        |
             | if-feature   | 7.18.2  | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | uses         | 7.12    | 0..n        |
             | when         | 7.19.5  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

7.9.3 choice的default聲明

The “default” statement indicates if a case should be considered as 
the default if no child nodes from any of the choice’s cases exist. 
The argument is the identifier of the “case” statement. If the 
“default” statement is missing, there is no default case.

當“mandatory”的值爲true時,“default”聲明 MUST 不能出現。

The default case is only important when considering the default 
values of nodes under the cases. The default values for nodes under 
the default case are used if none of the nodes under any of the cases 
are present.

There MUST NOT be any mandatory nodes (Section 3.1) directly under 
the default case.

Default values for child nodes under a case are only used if one of 
the nodes under that case is present, or if that case is the default 
case. If none of the nodes under a case are present and the case is 
not the default case, the default values of the cases’ child nodes 
are ignored.

In this example, the choice defaults to “interval”, and the default 
value will be used if none of “daily”, “time-of-day”, or “manual” are 
present. If “daily” is present, the default value for “time-of-day” 
will be used.

 container transfer {
     choice how {
         default interval;
         case interval {
             leaf interval {
                 type uint16;
                 default 30;
                 units minutes;
             }
         }
         case daily {
             leaf daily {
                 type empty;
             }
             leaf time-of-day {
                 type string;
                 units 24-hour-clock;
                 default 1am;
             }
         }
         case manual {
             leaf manual {
                 type empty;
             }
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

7.9.4 choice的mandatory聲明

“mandatory”聲明,是可選的,其參數是值爲“true”或“false”的string,作用是對有效的數據施加一種約束。如果取值爲“true”,則說明choice的case branches中特定的某個branch中的至少一個node MUST 存在。

如果沒有指定,默認值是“false”。

The behavior of the constraint depends on the type of the choice’s 
closest ancestor node in the schema tree which is not a non-presence 
container (see Section 7.5.1):

o If this ancestor is a case node, the constraint is enforced if any 
other node from the case exists.

o Otherwise, it is enforced if the ancestor node exists.

The constraint is further enforced according to the rules in 
Section 8.

7.9.5 XML映射規則

choice和case nodes在XML中不可見。

The child nodes of the selected “case” statement MUST be encoded in 
the same order as they are defined in the “case” statement if they 
are part of an RPC input or output parameter definition. Otherwise, 
the subelements are encoded in any order.

7.9.6 NETCONF 操作

Since only one of the choice’s cases can be valid at any time, the 
creation of a node from one case implicitly deletes all nodes from 
all other cases. If an operation creates a node from a 
case, the NETCONF server will delete any existing nodes that are 
defined in other cases inside the choice.

7.9.7 使用用例

給定下面的choice:

 container protocol {
     choice name {
         case a {
             leaf udp {
                 type empty;
             }
         }
         case b {
             leaf tcp {
                type empty;
             }
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

對應的XML實例可以是:

 <protocol>
   <tcp/>
 </protocol>
  • 1
  • 2
  • 3
  • 4

將protocol從tcp改成udp:

     <rpc message-id="101"
          xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
          xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
       <edit-config>
         <target>
           <running/>
         </target>
         <config>
           <system xmlns="http://example.com/schema/config">
             <protocol>
               <udp nc:operation="create"/>
             </protocol>
           </system>
         </config>
       </edit-config>
     </rpc>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

7.10 anyxml聲明

“anyxml”聲明定義了schema tree的一個內部節點(interior node)。它有一個參數,是一個identifier,後面跟着描述詳細信息的一塊substatements。

“anyxml”聲明被用來標識XML中未知的文本塊。在XML上沒有施加任何restrictions。這是相當有用的一點,比如說,在RPC的replies中。給出一個例子,在操作中的參數。

一個anyxml節點不能被擴展(augmented),可見Section 7.15。

由於對“anyxml”的使用會限制對內容的操控,所以 RECOMMENDED “anyxml”聲明不要被用來表示configuration data。

在data tree中,一個anyxml node只能存在於0個或1個實例中。

上面這句話沒明白,是說在data tree中,只能有一個anyxml的實現嗎?原文如下:_An anyxml node exists in zero or one instances in the data tree. 
_

7.10.1 anyxml的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | config       | 7.19.1  | 0..1        |
             | description  | 7.19.3  | 0..1        |
             | if-feature   | 7.18.2  | 0..n        |
             | mandatory    | 7.6.5   | 0..1        |
             | must         | 7.5.3   | 0..n        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | when         | 7.19.5  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

7.10.2 XML映射規則

一個anyxml node會被編碼爲一個XML element。這個element的local name就是這個anyxml的identifier,它的namespace就是module的XML namespace。anyxml node的值會被編碼爲這個element的XML內容。

需要明白,在編碼中使用到的任何前綴對於每個實例來說都是本地有效的。這意味着,在不同的實現中,同一個XML會被編碼爲不同的東西。(Note that any prefixes used in the encoding are local to each instance encoding. This means that the same XML may be encoded differently by different implementations.

7.10.3 NETCONF 操作

一個anyxml node被認爲是一塊不透明的數據塊(因爲不知道里面什麼內容,無法解析)。這個數據塊只能整個被替換。

在anyxml node的subelements中出現的任何“operation”屬性都會被NETCONF服務端忽略,不作處理。

When a NETCONF server processes an request, the 
elements of procedure for the anyxml node are:

  If the operation is "merge" or "replace", the node is created if
  it does not exist, and its value is set to the XML content of the
  anyxml node found in the XML RPC data.

  If the operation is "create", the node is created if it does not
  exist, and its value is set to the XML content of the anyxml node
  found in the XML RPC data.  If the node already exists, a
  "data-exists" error is returned.

  If the operation is "delete", the node is deleted if it exists.
  If the node does not exist, a "data-missing" error is returned.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

7.10.4 使用用例

給定下面的“anyxml”聲明:

 anyxml data;
  • 1
  • 2

下面是同一個anyxml值的兩種不同的編碼:

 <data xmlns:if="http://example.com/ns/interface">
   <if:interface>
     <if:ifIndex>1</if:ifIndex>
   </if:interface>
 </data>

 <data>
   <interface xmlns="http://example.com/ns/interface">
     <ifIndex>1</ifIndex>
   </interface>
 </data>          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

7.11 grouping聲明

“grouping”聲明被用來定義可重用的block of nodes,可能會在module內部被使用,在包含它的modules中使用,或者導入它的其它modules中被使用。它有一個參數,是一個identifier,後面跟着描述更詳細信息的一塊substatements。

“grouping”聲明不是一個data 定義的聲明,在schema tree中不會定義任何nodes。

一個grouping類似於常見編程語言中的“structure”或者“record”。

一旦一個grouping被定義,它就能通過“uses”聲明被引用(見Section 7.12)。一個grouping MUST NOT引用它自己,也不能間接通過其它的groupings的引用鏈引用到自己。

如果grouping定義在YANG module或submodule的top level,grouping的identifier就MUST 在module內是唯一的。

grouping的作用不僅僅是一種文本替換機制,而且將某些nodes整合到了一個集合中。grouping中的identifiers會放到grouping定義的地方進行範圍的界定,而不是放到其被使用的地方。而prefix mappings,type names,grouping names,以及extension usage會在“grouping”聲明出現的垂直結構中進行評估。以extensions爲例,這意味着extensions會被應用到grouping node,而不是uses node。

沒想明白爲什麼會放到grouping定義的地方進行scope的界定,如果這樣的話,被引用的地方就有可能出現identifiers的衝突了吧?

7.11.1 grouping的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | choice       | 7.9     | 0..n        |
             | container    | 7.5     | 0..n        |
             | description  | 7.19.3  | 0..1        |
             | grouping     | 7.11    | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | typedef      | 7.3     | 0..n        |
             | uses         | 7.12    | 0..n        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

7.11.2 使用用例

 import ietf-inet-types {
     prefix "inet";
 }

 grouping endpoint {
     description "A reusable endpoint group.";
     leaf ip {
         type inet:ip-address;
     }
     leaf port {
         type inet:port-number;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

7.12 uses聲明

“uses”聲明被用來引用一個“grouping”定義。它有一個參數,就是所引用的grouping的名字。

“uses”的作用就是它所引用的grouping所包含的nodes會被複制到當前的schema tree中,並且後面會根據“refine”和“augment”聲明而更新。

暫時還不知道refine和augment是啥?

在grouping中定義的identifiers不回綁定到一個在“grouping”聲明內部沒有出現的namespace,除非這個grouping的內容通過“uses”聲明被增加到對應的schema tree中,這種情況下,它們就會被綁定到當前的module中。

以防誤解,附上原文:The identifiers defined in the grouping are not bound to a namespace until the contents of the grouping are added to the schema tree via a “uses” statement that does not appear inside a “grouping” statement, at which point they are bound to the namespace of the current module.

7.12.1 uses的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | augment      | 7.15    | 0..1        |
             | description  | 7.19.3  | 0..1        |
             | if-feature   | 7.18.2  | 0..n        |
             | refine       | 7.12.2  | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | when         | 7.19.5  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

7.12.2 refine聲明

在grouping中的每個node的某些屬性都能通過“refine”聲明refined。其參數是grouping中的某個node的identifier。這個node被稱爲這個refine的target node。如果grouping中的一個node在“refine”聲明中沒有作爲target node出現,它就不會被refined,因此被引用的時候就按照它在grouping中定義的那樣被引用。

參數字符串是一個descendant schema node identifier(見Section 6.5)。

可以進行下面的refinements:

  • 一個leaf或choice node可能通過“refine”獲得一個默認值,或者本來就有一個默認值,被新的默認值替代了。
  • 任何node都能通過它獲得應用場景下的“description”字符串。
  • 任何node都能通過它獲得應用場景下的“reference”字符串。
  • 任何node都能通過它獲得一個不同的“config”聲明。
  • 一個leaf,anyxml,或者choice node都能通過它獲得一個不同的“mandatory”聲明。
  • 一個container node能通過它獲得一個“presence”聲明。表示一個container是否有實際意義
  • 一個leaf,leaf-list,list,container或anyxml node能通過它獲得額外的“must”表達式。
  • 一個leaf-list或list node能通過它獲得一個不同的“min-elements”或“max-elements”聲明。

refined這個詞在詞典中的意思是“精煉的”。不過給我的感覺更像是redefined或者modified。是爲了適應grouping的使用場景對其做的一些修改。

7.12.3 XML 映射規則

在grouping中的每個node在編碼時表現就像它是被內聯進去的,即便它是其它XML namespace的另一個module中導入的。(簡單來說,就按照C++裏面的inline關鍵詞理解就行了

7.12.4 使用用例

爲了在其它module中定義的HTTP server中使用Section 7.11.2中定義的“endpoint” grouping,我們可以這麼寫:

 import acme-system {
     prefix "acme";
 }

 container http-server {
     leaf name {
         type string;
     }
     uses acme:endpoint;
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

對應的XML實例例子有:

     <http-server>
       <name>extern-web</name>
       <ip>192.0.2.1</ip>
       <port>80</port>
     </http-server>
  • 1
  • 2
  • 3
  • 4
  • 5

如果端口80應該是HTTP Server的默認端口,則可以這麼寫:

 container http-server {
     leaf name {
         type string;
     }
     uses acme:endpoint {
         refine port {
             default 80;
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如果我們要定義一個servers的list,其中每個server都將ip和port作爲keys,我們可以這麼寫:

 list server {
     key "ip port";
     leaf name {
         type string;
     }
     uses acme:endpoint;
 }   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

下面是一個錯誤用例:

 container http-server {
     uses acme:endpoint;
     leaf ip {          // illegal - same identifier "ip" used twice
         type string;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

7.13 rpc聲明

“rpc”聲明被用來定義一個NETCONF RPC操作。它有一個參數,是一個identifier,後面跟着描述詳細信息的一塊substatements。這個參數是RPC的名字,在XML中作爲 element的element名字,as designated by the substitution group “rpcOperation” in RFC4741

“rpc”聲明在schema tree中定義了一個rpc node。在這個rpc node之下,也會定義兩個schema node,一個名字叫“input”,一個叫“output”。node “input”和“output”都是定義在module的namespace中的。

7.13.1 rpc的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | description  | 7.19.3  | 0..1        |
             | grouping     | 7.11    | 0..n        |
             | if-feature   | 7.18.2  | 0..n        |
             | input        | 7.13.2  | 0..1        |
             | output       | 7.13.3  | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | typedef      | 7.3     | 0..n        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

7.13.2 input聲明

“input”聲明,是可選的,被用來定義RPC操作的輸入參數。它沒有參數。“input”的substatements直接定義在input node之下。

如果在input tree中的一個leaf的“mandatory”聲明的值爲“true”,這個leaf MUST 在NETCONF RPC調用時出現,否則,服務端 MUST 返回一個“missing-element”的錯誤。

如果一個在input tree中的leaf有默認值,則NETCONF服務器 MUST 在和如Section 7.6.1 相同的場景下使用這個值。在這些場景下,服務器 MUST 表現得好像在NETCONF RPC 調用中這個leaf本身就存在,並且其值爲默認值。

如果一個“config”聲明出現在input tree中的任何node中,它都不會被處理。

如果任何node的“when”聲明的約束都被評估爲false,則這個node MUST NOT 出現在input tree中。

7.13.2.1 input的substatements
             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | choice       | 7.9     | 0..n        |
             | container    | 7.5     | 0..n        |
             | grouping     | 7.11    | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | typedef      | 7.3     | 0..n        |
             | uses         | 7.12    | 0..n        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

7.13.3 output聲明

“output”聲明,是可選的,被用來定義RPC操作中的輸出參數。它沒有參數。“output”的substatements直接定義在其後。

如果output tree中的一個leaf的“mandatory”聲明的值爲“true”,則這個leaf MUST 出現在NETCONF RPC reply中。

如果output tree中的一個leaf有一個默認值,則NETCONF 客戶端 MUST 在和Section 7.6.1描述的場景相同的情況下使用這個值。在這些情況下,客戶端 MUST 表現得好像NETCONF RPC reply中本來就有這個leaf,並且其值就是默認值一樣。

如果一個“config”聲明出現在output tree中的任何node中,則這個“config”聲明不會被處理,會被忽略。

如果任何node中有一個“when”聲明約束,並且評估結果爲false,則這個node MUST NOT 出現在output tree中。

7.13.3.1 output的substatements
             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | choice       | 7.9     | 0..n        |
             | container    | 7.5     | 0..n        |
             | grouping     | 7.11    | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | typedef      | 7.3     | 0..n        |
             | uses         | 7.12    | 0..n        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

7.13.4 XML映射規則

一個rpc node會被編碼爲【RFC4741】中定義的 element的child XML element。這個element的local name就是rpc的identifier,它的namespace就是rpc node所在module的XML namespace。

input參數會被編碼爲rpc node的XML element的child XML elements,其排列順序和“input” statement中定義的順序一致。

如果RPC 操作的調用成功,並且沒有output參數返回,則會僅僅包含一個簡單的 element。如果output參數有返回,它們會被編碼爲 element的child elements,其順序和“output”聲明中定義的順序一致。

7.13.5 使用用例

下面的例子定義了一個RPC操作:

 module rock {
     namespace "http://example.net/rock";
     prefix "rock";

     rpc rock-the-house {
         input {
             leaf zip-code {
                 type string;
             }
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

對應的完整的rpc和rpc-reply的XML實例爲:

 <rpc message-id="101"
      xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
   <rock-the-house xmlns="http://example.net/rock">
     <zip-code>27606-0100</zip-code>
   </rock-the-house>
 </rpc>

 <rpc-reply message-id="101"
            xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
   <ok/>
 </rpc-reply>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

7.14 notification聲明

“notification”聲明被用來定義NETCONF的notification。它有一個參數,是一個identifier,後面跟着描述更詳細信息的一塊substatements。“notification”聲明在schema tree中定義了一個notification node。

如果notification tree中的一個leaf有值爲true的“mandatory”聲明,這個leaf MUST 在NETCONF的notification中出現。

如果notification tree中的一個leaf有默認值,則NETCONF 客戶端 MUST 在和Section 7.6.1描述的場景相同的情況下使用這個值。在這些情況下,客戶端 MUST 表現得好像NETCONF notification中本來就有這個leaf,並且其值就是默認值一樣。

如果“config”聲明出現在notification tree中的任何一個node中,則該聲明會被忽略。

7.14.1 notification的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | choice       | 7.9     | 0..n        |
             | container    | 7.5     | 0..n        |
             | description  | 7.19.3  | 0..1        |
             | grouping     | 7.11    | 0..n        |
             | if-feature   | 7.18.2  | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | typedef      | 7.3     | 0..n        |
             | uses         | 7.12    | 0..n        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

7.14.2 XML映射規則

一個notification node會作爲【RFC5277】中定義的NETCONF Event Notifications對應的 element的child XML element存在。這個element的local name就是notification的identifier,它的namespace就是notification所在的module的XML namespace。

7.14.3 使用用例

下面的例子定義了一個notification:

 module event {

     namespace "http://example.com/event";
     prefix "ev";

     notification event {
         leaf event-class {
             type string;
         }
         anyxml reporting-entity;
         leaf severity {
             type string;
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

完整的notification的對應的XML實例爲:

 <notification
   xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
   <eventTime>2008-07-08T00:01:00Z</eventTime>
   <event xmlns="http://example.com/event">
     <event-class>fault</event-class>
     <reporting-entity>
       <card>Ethernet0</card>
     </reporting-entity>
     <severity>major</severity>
   </event>
 </notification>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

7.15 augment聲明

“augment”聲明允許將一個module或submodule增加到另外一個module定義的schema tree中,或者增加到當前module以及它的submodules,或者增加到使用“uses”聲明定義的grouping所引用的nodes中去。其參數是一個string,標識了一個node在schema tree中的位置。這個節點稱爲augment的target node。這個target node MUST container,list,choice,case,input,output或者notification node的一種。在該聲明的substatements中定義的nodes會被augmented到target node中去。

augment的參數字符串是一個schema node identifier(見Section 6.5)。如果“augment”聲明是module或submodule的一個top level的node, MUST 在schema node identifier中使用absolute form(見Section 12中的“absolute-schema-nodeid”)。如果“augment”聲明是“uses”聲明的一個substatement,則 MUST 使用descendant form(見Section 12的“descendant-schema-nodeid”)。

如果target node是一個containet,list,case,input,output或者notification node,則“container”,“leaf”,“list”,“leaf-list”,“uses”以及“choice”聲明可以被用在“augment”聲明中。

如果target node是一個choice node, 則“case”聲明,或者一個case的簡寫版的聲明(見Section 7.9.2)可以被用在“augment”聲明中。

如果target node在另外一個module中,則由augmentation增加的nodes MUST NOT 是mandatory nodes(可見Section 3.1).(If the target node is in another module, then nodes added by the augmentation MUST NOT be mandatory nodes (see Section 3.1).

The “augment” statement MUST NOT add multiple nodes with the same name from the same module to the target node.

7.15.1 augment的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | anyxml       | 7.10    | 0..n        |
             | case         | 7.9.2   | 0..n        |
             | choice       | 7.9     | 0..n        |
             | container    | 7.5     | 0..n        |
             | description  | 7.19.3  | 0..1        |
             | if-feature   | 7.18.2  | 0..n        |
             | leaf         | 7.6     | 0..n        |
             | leaf-list    | 7.7     | 0..n        |
             | list         | 7.8     | 0..n        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             | uses         | 7.12    | 0..n        |
             | when         | 7.19.5  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

status這個聲明貌似還沒見過呢。

7.15.2 XML映射規則

所有“augment”聲明中定義的data nodes都會編碼成“augment”被指定的那個module對應的XML namespace的XML elements。

當一個node被augmented的時候,augmenting child nodes會被編碼爲augmented node的subelements,順序任意。

7.15.3 使用用例

在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;
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

這裏的ifType的類型爲 “iana:IfType”。

然後,在namespace “http://example.com/schema/ds0”中,我們有:

 import interface-module {
     prefix "if";
 }
 augment "/if:interfaces/if:ifEntry" {
     when "if:ifType='ds0'";
     leaf ds0ChannelNumber {
         type ChannelNumber;
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

對應的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>
         <!-- 類型爲ds0的時候,增加了ds0ChannelNumber -->
         <ds0:ds0ChannelNumber>1</ds0:ds0ChannelNumber>
       </ifEntry>
     </interfaces>     
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

另外一個例子中,我們假設有一個在Section 7.9.7中定義的choice。下面的結構能被用來擴展其中的protocol的定義:

 augment /ex:system/ex:protocol/ex:name {
     case c {
         leaf smtp {
             type empty;
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

對應的XML實例爲:

     <ex:system>
       <ex:protocol>
         <ex:tcp/>
       </ex:protocol>
     </ex:system>
  • 1
  • 2
  • 3
  • 4
  • 5

或者:

     <ex:system>
       <ex:protocol>
         <other:smtp/>
       </ex:protocol>
     </ex:system>
  • 1
  • 2
  • 3
  • 4
  • 5

7.16 identity聲明

“identity”聲明被用來定義一個新的,全局唯一的,抽象的,沒有特定類型的identity。它的唯一目的就是對外宣示它的名字,語義以及存在。一個identity既能夠從頭開始定義,也能夠從一個base identity處繼承。identity的參數是一個identifier,就是這個identity的名字。後面跟着描述更具體信息的一塊substatements。

內置的數據類型“identityref”(見Section 9.10)能夠在一個data model內部被用來引用identities。

7.16.1 identity的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | base         | 7.16.2  | 0..1        |
             | description  | 7.19.3  | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

7.16.2 base聲明

“base”聲明是可選的,其參數是一個已存在的identity的名字,本次定義的identity就是從它那裏繼承來的。如果“base”聲明沒有出現,則這個identity的定義就是從零開始的。

如果在base的名字中有前綴,該前綴會指向定義這個identity的module,或者,如果該前綴正好是local module的前綴,則就指向本module。否則,MUST 指向當前的module或者一個被包含的submodule。

local module 和 current module是有區別的,我日啊,之前一直以爲是同樣的東西。local表示本地,本地不一定只有current這一個module啊,也可以有其它module。

由於submodules不能包含其父module,所以任何在module中定義的identities,如果需要被submodules引用,則 MUST 定義到某個submodule中去。submodules能夠接着引用這個submodule去獲取這個identity的定義。

一個identity MUST NOT 引用自己,無論是直接的還是通過其它的identities形成的引用鏈進行的間接引用。

7.1。3 使用用例

 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";
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

按照上面的描述來說,identity在schema tree中存在,在data tree中不存在了?

7.17 extension聲明

“extension”聲明允許在YANG語言中定義新的聲明。這個新的聲明的定義可以被其它modules導入和使用。

該聲明的參數是一個identifier,表示擴展的新keyword,後面必須跟一塊描述詳細擴展信息的substatements。“extension”聲明的目標就是定義一個keyword,這樣它才能被其它modules導入和使用。

extension能像普通的YANG聲明一樣被使用,聲明後面跟一個參數,後面還有可選的一塊substatements。新聲明的名字是該extension所在的module的前綴,跟上冒號(“:”),再跟上keyword,中間沒有空白。extension的substatements是由extension定義的,使用了本標準以外的某些機制。在語法構成上,substatements MUST 是YANG聲明,或者也是用“extension”聲明定義的新聲明。在extensions中使用的YANG聲明 MUST 遵循Section 12中定義的語法上的規則。

7.17.1 extension的substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | argument     | 7.17.2  | 0..1        |
             | description  | 7.19.3  | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             | status       | 7.19.2  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

7.17.2 argument聲明

“argument”聲明,是可選的,是一個字符串,表示keyword的參數的名字。如果沒有argument聲明,則keyword在被使用的時候沒有參數。

argument的name在YIN mapping中被使用,在那裏作爲XML attribute或者element name,具體要取決於argument的“yin-element”聲明。

7.17.2.1 argument的substatements
             +--------------+----------+-------------+
             | substatement | section  | cardinality |
             +--------------+----------+-------------+
             | yin-element  | 7.17.2.2 | 0..1        |
             +--------------+----------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
7.17.2.2 yin-element聲明

“yin-element”聲明,是可選的,其參數爲“true”或者“false”的字符串。這個聲明說明了是否將argument映射到YIN中的一個XML element,或者一個XML attribute(見Section 11)。

如果該聲明沒有出現,默認值是“false”。

7.17.3 使用用例

首先,定義一個extension:

 module my-extensions {
   ...

   extension c-define {
     description
       "Takes as argument a name string.
       Makes the code generator use the given name in the
       #define.";
     argument "name";
   }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

接着,使用這個extension:

 module my-interfaces {
   ...
   import my-extensions {
     prefix "myext";
   }
   ...

   container interfaces {
     ...
     myext:c-define "MY_INTERFACES";
   }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

7.18 conformance-related聲明

這個小姐定義了和一致性(conformance)相關的聲明,如Section 5.6中描述的一樣。

7.18.1 feature聲明

The “feature” statement is used to define a mechanism by which 
portions of the schema are marked as conditional. A feature name is 
defined that can later be referenced using the “if-feature” statement 
(see Section 7.18.2). Schema nodes tagged with a feature are ignored 
by the device unless the device supports the given feature. This 
allows portions of the YANG module to be conditional based on 
conditions on the device. The model can represent the abilities of 
the device within the model, giving a richer model that allows for 
differing device abilities and roles.

The argument to the “feature” statement is the name of the new 
feature, and follows the rules for identifiers in Section 6.2. This 
name is used by the “if-feature” statement to tie the schema nodes to 
the feature.

In this example, a feature called “local-storage” represents the 
ability for a device to store syslog messages on local storage of 
some sort. This feature is used to make the “local-storage-limit” 
leaf conditional on the presence of some sort of local storage. If 
the device does not report that it supports this feature, the 
“local-storage-limit” node is not supported.

 module syslog {
     ...
     feature local-storage {
         description
             "This feature means the device supports local
              storage (memory, flash or disk) that can be used to
              store syslog messages.";
     }

     container syslog {
         leaf local-storage-limit {
             if-feature local-storage;
             type uint64;
             units "kilobyte";
             config false;
             description
                 "The amount of local storage that can be
                  used to hold syslog messages.";
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

The “if-feature” statement can be used in many places within the YANG 
syntax. Definitions tagged with “if-feature” are ignored when the 
device does not support that feature.

A feature MUST NOT reference itself, neither directly nor indirectly 
through a chain of other features.

In order for a device to implement a feature that is dependent on any 
other features (i.e., the feature has one or more “if-feature” sub- 
statements), the device MUST also implement all the dependant 
features.

7.18.1.1 feature的substatements
             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | description  | 7.19.3  | 0..1        |
             | if-feature   | 7.18.2  | 0..n        |
             | status       | 7.19.2  | 0..1        |
             | reference    | 7.19.4  | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

7.18.2 if-feature聲明

The “if-feature” statement makes its parent statement conditional. 
The argument is the name of a feature, as defined by a “feature” 
statement. The parent statement is implemented by servers that 
support this feature. If a prefix is present on the feature name, it 
refers to a feature defined in the module that was imported with that 
prefix, or the local module if the prefix matches the local module’s 
prefix. Otherwise, a feature with the matching name MUST be defined 
in the current module or an included submodule.

Since submodules cannot include the parent module, any features in 
the module that need to be exposed to submodules MUST be defined in a 
submodule. Submodules can then include this submodule to find the 
definition of the feature.

7.18.3 deviation聲明

The “deviation” statement defines a hierarchy of a module that the 
device does not implement faithfully. The argument is a string that 
identifies the node in the schema tree where a deviation from the 
module occurs. This node is called the deviation’s target node. The 
contents of the “deviation” statement give details about the 
deviation.

The argument string is an absolute schema node identifier (see 
Section 6.5).

Deviations define the way a device or class of devices deviate from a 
standard. This means that deviations MUST never be part of a 
published standard, since they are the mechanism for learning how 
implementations vary from the standards.

Device deviations are strongly discouraged and MUST only be used as a 
last resort. Telling the application how a device fails to follow a 
standard is no substitute for implementing the standard correctly. A 
device that deviates from a module is not fully compliant with the 
module.

However, in some cases, a particular device may not have the hardware 
or software ability to support parts of a standard module. When this 
occurs, the device makes a choice either to treat attempts to 
configure unsupported parts of the module as an error that is 
reported back to the unsuspecting application or ignore those 
incoming requests. Neither choice is acceptable.

Instead, YANG allows devices to document portions of a base module 
that are not supported or supported but with different syntax, by 
using the “deviation” statement.

7.18.3.1 deviation的substatements
             +--------------+----------+-------------+
             | substatement | section  | cardinality |
             +--------------+----------+-------------+
             | description  | 7.19.3   | 0..1        |
             | deviate      | 7.18.3.2 | 1..n        |
             | reference    | 7.19.4   | 0..1        |
             +--------------+----------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
7.18.3.2 divate聲明

The “deviate” statement defines how the device’s implementation of 
the target node deviates from its original definition. The argument 
is one of the strings “not-supported”, “add”, “replace”, or “delete”.

The argument “not-supported” indicates that the target node is not 
implemented by this device.

The argument “add” adds properties to the target node. The 
properties to add are identified by substatements to the “deviate” 
statement. If a property can only appear once, the property MUST NOT 
exist in the target node.

The argument “replace” replaces properties of the target node. The 
properties to replace are identified by substatements to the 
“deviate” statement. The properties to replace MUST exist in the 
target node.

The argument “delete” deletes properties from the target node. The 
properties to delete are identified by substatements to the “delete” 
statement. The substatement’s keyword MUST match a corresponding 
keyword in the target node, and the argument’s string MUST be equal 
to the corresponding keyword’s argument string in the target node.

                   The deviates's Substatements

             +--------------+---------+-------------+
             | substatement | section | cardinality |
             +--------------+---------+-------------+
             | config       | 7.19.1  | 0..1        |
             | default      | 7.6.4   | 0..1        |
             | mandatory    | 7.6.5   | 0..1        |
             | max-elements | 7.7.4   | 0..1        |
             | min-elements | 7.7.3   | 0..1        |
             | must         | 7.5.3   | 0..n        |
             | type         | 7.4     | 0..1        |
             | unique       | 7.8.3   | 0..n        |
             | units        | 7.3.3   | 0..1        |
             +--------------+---------+-------------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
7.18.3.3 使用用例

In this example, the device is informing client applications that it 
does not support the “daytime” service in the style of RFC 867.

 deviation /base:system/base:daytime {
     deviate not-supported;
 }
  • 1
  • 2
  • 3
  • 4

The following example sets a device-specific default value to a leaf 
that does not have a default value defined:

 deviation /base:system/base:user/base:type {
     deviate add {
         default "admin"; // new users are 'admin' by default
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

In this example, the device limits the number of name servers to 3:

 deviation /base:system/base:name-server {
     deviate replace {
         max-elements 3;
     }
 }                 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

If the original definition is:

 container system {
     must "daytime or time";
     ...
 }
  • 1
  • 2
  • 3
  • 4
  • 5

a device might remove this must constraint by doing:

 deviation "/base:system" {
     deviate delete {
         must "daytime or time";
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

7.19 通用的聲明

本小節定義了一些對其他聲明來說都可以用的substatements。

7.19.1 config聲明

“config”聲明有一個參數,取值爲“true”或者“false”。如果值爲“true”,則表示本定義表示的是configuration。定義configuration的data nodes會是 request的迴應的一部分,能夠放在或者 request中發送出去。

如果值爲“false”,則表示本定義表示的是state data。定義state data的data nodes會是對 request的迴應的一部分,單不會迴應 request,並且不能放到或者 request中。

如果沒有指定“config”,則默認值和其parent schema node的“config”的值一樣。如果parent node是一個“case” node,則這個值就和“case”node的parent “choice” noce相同。

如果top node沒有指定“config”聲明,則默認值爲“true”。

如果一個node的“config”設置爲“false”,則該節點的所有子節點都不能將“config”設置爲“true”。

7.19.2 status聲明

“status”聲明的參數是一個字符串,是“current”,“deprecated”或者“obsolete”中的一個。

  • “current”意味着該定義在當前是有效的。
  • “deprecated”表示該定義已經被廢棄,不過保證在暫時在後續的實現中支持該定義,以保證向前兼容。
  • “obsolete”意味着這個定義已經被廢棄,並且 SHOULD NOT 被實現。

如果沒有指定status,則默認值爲“current”。

如果一個定義是“current”,則它 MUST NOT 在同一個module中引用“deprecated”或“obsolete”定義。

如果一個定義是“deprecated”,則它 MUST NOT 在同一個module中引用“obsolete”定義。

比如說,下面的例子就是非法的:

 typedef my-type {
   status deprecated;
   type int32;
 }

 leaf my-leaf {
   status current;
   type my-type; // illegal, since my-type is deprecated
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

7.19.3 description聲明

The “description” statement takes as an argument a string that 
contains a human-readable textual description of this definition. 
The text is provided in a language (or languages) chosen by the 
module developer; for the sake of interoperability, it is RECOMMENDED 
to choose a language that is widely understood among the community of 
network administrators who will use the module.

7.19.4 reference聲明

“reference”聲明有一個參數,是字符串,該參數被用來指定一個到外部文檔的交叉引用,既可以是定義了相關管理信息的另一個module,也可以是能對本定義提供相關額外信息的一個文檔。

比如,定義了名爲“uri” 的一個typedef,可以這麼寫:

 typedef uri {
   type string;
   reference
     "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax";
   ...
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

7.19.5 when聲明

“when”聲明可以使它的parent data 定義聲明變成有條件的。由其parent data定義聲明所定義的node僅當該“when”聲明提供的要求(condition)得到滿足時纔有可能是有效的。該聲明的參數是一個XPath表達式(見Section 6.4),該表達式被用來精確描述這個條件(condition)。如果XPath表達式針對特定的實例被評估爲“true”的話,則該parent data定義聲明所定義的node就是有效的,反之亦然。

更多信息可見Section 8.3.2。

The XPath expression is conceptually evaluated in the following 
context, in addition to the definition in Section 6.4.1:

o If the “when” statement is a child of an “augment” statement, then 
the context node is the augment’s target node in the data tree, if 
the target node is a data node. Otherwise, the context node is 
the closest ancestor node to the target node that is also a data 
node.

o If the “when” statement is a child of a “uses”, “choice”, or 
“case” statement, then the context node is the closest ancestor 
node to the “uses”, “choice”, or “case” node that is also a data 
node.

o If the “when” statement is a child of any other data definition 
statement, the context node is the data definition’s node in the 
data tree.

o The accessible tree is made up of all nodes in the data tree, and 
all leafs with default values in use (see Section 7.6.1).

The accessible tree depends on the context node:

o If the context node represents configuration, the tree is the data 
in the NETCONF datastore where the context node exists. The XPath 
root node has all top-level configuration data nodes in all 
modules as children.

o If the context node represents state data, the tree is all state 
data on the device, and the datastore. The XPath root 
node has all top-level data nodes in all modules as children.

o If the context node represents notification content, the tree is 
the notification XML instance document. The XPath root node has 
the element representing the notification being defined as the 
only child.

o If the context node represents RPC input parameters, the tree is 
the RPC XML instance document. The XPath root node has the 
element representing the RPC operation being defined as the only 
child.

o If the context node represents RPC output parameters, the tree is 
the RPC reply instance document. The XPath root node has the 
elements representing the RPC output parameters as children.

The result of the XPath expression is converted to a boolean value 
using the standard XPath rules.

Note that the XPath expression is conceptually evaluated. This means 
that an implementation does not have to use an XPath evaluator on the 
device. The “when” statement can very well be implemented with 
specially written code.

8 constraints

第八章僅僅給出目錄,具體內容感覺暫時不需要看。

8.1 constraints on data

8.2. Hierarchy of Constraints

8.3. Constraint Enforcement Model

8.3.1. Payload Parsing

8.3.2. NETCONF Processing

8.3.3. Validation

9 內置類型

這一章暫時沒有必要看。稍微對編程語言有點了解,就能把這裏的內置類型理解個差不多。遇到問題的時候再回頭翻原文吧。

10 更新module

這一章內容比較少,不過又不是自己寫module,所以暫時也沒必要看。

11 YIN

好像完全沒有見過YIN的應用。

一個YANG module能被轉換爲一種可選的基於XML語法的格式,稱爲YIN。被轉換的module稱爲YIN module。本小節描述了這YANG和YIN這兩種格式之間的映射關係。

YANG和YIN格式使用不同的符號包含了同樣的信息。YIN的符號使得開發者能夠在XML中表示YANG的data models,因此能夠使用基於XML的工具對數據做過濾,驗證,代碼和文檔的自動生成以及其它的工作。想XSLT或XML 驗證器這樣的工具就能用到了。

YANG和YIN之間的映射不會改變model本身的內容。comments和whitespace不會被保留。

11.1 正規的YIN定義

在YANG的keywords和YIN的elements之間有一對一的雙射。一個YIN element的local name等同於對應的yANG的keyword。這意味着,YIN文檔中的文檔元素(root)總是和YANG中的或對應。

對應到YANG keywords的YIN elements的namespace是“urn:ietf:params:xml:ns:yang:yin:1”。

對應到YANG的extension keywords的YIN elements屬於extension關鍵詞通過“extension”聲明宣告的YANG module的namespace。

所有的YIN elements的名字 MUST 上述指定的namespaces相匹配,也就是要使用標準的[XML-NAMES]機制,比如:“xmlns”以及“xmlns:xxx”屬性。

YANG聲明的參數在YIN中是作爲XML attribute或者keyword element的subelement而存在。Table 1定義了YANG keywords到YIN的映射關係。對於extensions來說,參數映射是在“extension”聲明中指定的(見Section 7.17)。對於參數,有下面的規則:

  • 如果參數被映射爲一個attribute,則該attribute沒有namespace。
  • 如果參數被映射爲一個element,則其namespace和其parent keyword element一樣。
  • 如果參數被映射爲一個element,則它 MUST 是keyword element的第一個子節點。

YANG聲明的substatements會被映射爲該聲明對應的keyword element的children,substatements之間的相對順序 MUST 和YANG中定義的順序完全一致。

YANG中的comments MAY 映射爲XML的comments。

           Mapping of arguments of the YANG statements.

        +------------------+---------------+-------------+
        | keyword          | argument name | yin-element |
        +------------------+---------------+-------------+
        | anyxml           | name          | false       |
        | argument         | name          | false       |
        | augment          | target-node   | false       |
        | base             | name          | false       |
        | belongs-to       | module        | false       |
        | bit              | name          | false       |
        | case             | name          | false       |
        | choice           | name          | false       |
        | config           | value         | false       |
        | contact          | text          | true        |
        | container        | name          | false       |
        | default          | value         | false       |
        | description      | text          | true        |
        | deviate          | value         | false       |
        | deviation        | target-node   | false       |
        | enum             | name          | false       |
        | error-app-tag    | value         | false       |
        | error-message    | value         | true        |
        | extension        | name          | false       |
        | feature          | name          | false       |
        | fraction-digits  | value         | false       |
        | grouping         | name          | false       |
        | identity         | name          | false       |
        | if-feature       | name          | false       |
        | import           | module        | false       |
        | include          | module        | false       |
        | input            | <no argument> | n/a         |
        | key              | value         | false       |
        | leaf             | name          | false       |
        | leaf-list        | name          | false       |
        | length           | value         | false       |
        | list             | name          | false       |
        | mandatory        | value         | false       |
        | max-elements     | value         | false       |
        | min-elements     | value         | false       |
        | module           | name          | false       |
        | must             | condition     | false       |
        | namespace        | uri           | false       |
        | notification     | name          | false       |
        | ordered-by       | value         | false       |
        | organization     | text          | true        |
        | output           | <no argument> | n/a         |
        | path             | value         | false       |
        | pattern          | value         | false       |
        | position         | value         | false       |
        | prefix           | value         | false       |
        | presence         | value         | false       |
        | range            | value         | false       |
        | reference        | text          | true        |
        | refine           | target-node   | false       |
        | require-instance | value         | false       |
        | revision         | date          | false       |
        | revision-date    | date          | false       |
        | rpc              | name          | false       |
        | status           | value         | false       |
        | submodule        | name          | false       |
        | type             | name          | false       |
        | typedef          | name          | false       |
        | unique           | tag           | false       |
        | units            | name          | false       |
        | uses             | name          | false       |
        | value            | value         | false       |
        | when             | condition     | false       |
        | yang-version     | value         | false       |
        | yin-element      | value         | false       |
        +------------------+---------------+-------------+

                              Table 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

11.1.1 使用用例

下面的YANG module:

 module acme-foo {
     namespace "http://acme.example.com/foo";
     prefix "acfoo";

     import my-extensions {
         prefix "myext";
     }

     list interface {
         key "name";
         leaf name {
             type string;
         }

         leaf mtu {
             type uint32;
             description "The MTU of the interface.";
             myext:c-define "MY_MTU";
         }
     }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

其中的“c-define”定義在Section 7.7.3,將上述module轉化爲下面的YIN:

     <module name="acme-foo"
             xmlns="urn:ietf:params:xml:ns:yang:yin:1"
             xmlns:acfoo="http://acme.example.com/foo"
             xmlns:myext="http://example.com/my-extensions">

       <namespace uri="http://acme.example.com/foo"/>
       <prefix value="acfoo"/>

       <import module="my-extensions">
         <prefix value="myext"/>
       </import>

       <list name="interface">
         <key value="name"/>
         <leaf name="name">
           <type name="string"/>
         </leaf>
         <leaf name="mtu">
           <type name="uint32"/>
           <description>
             <text>The MTU of the interface.</text>
           </description>
           <myext:c-define name="MY_MTU"/>
         </leaf>
       </list>
     </module>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

12 YANG ABNF Grammar

ABNF, Augmented Backus-Naur Form

這一章看不懂,後面就不粘了。

在YANG中,幾乎所有的statements都是無序的。ABNF grammar 【RFC5234】 爲這些聲明定義了標準的順序。爲了提高module的可讀性, RECOMMENDED 有序。

13 YANG相關錯誤的Error Responses

這一章對於我們實現來說,並不關心,所以跳過。

14 IANA Considerations

這一章同樣沒什麼用。

This document defines a registry for YANG module and submodule names. 
The name of the registry is “YANG Module Names”.

The registry shall record for each entry:

o the name of the module or submodule

o for modules, the assigned XML namespace

o for modules, the prefix of the module

o for submodules, the name of the module it belongs to

o a reference to the (sub)module’s documentation (e.g., the RFC 
number)

There are no initial assignments.

For allocation, RFC publication is required as per RFC 5226 
[RFC5226]. All registered YANG module names MUST comply with the 
rules for identifiers stated in Section 6.2, and MUST have a module 
name prefix.

The module name prefix ‘ietf-’ is reserved for IETF stream documents 
[RFC4844], while the module name prefix ‘irtf-’ is reserved for IRTF 
stream documents. Modules published in other RFC streams MUST have a 
similar suitable prefix.

All module and submodule names in the registry MUST be unique.

All XML namespaces in the registry MUST be unique.

This document registers two URIs for the YANG and YIN XML namespaces 
in the IETF XML registry [RFC3688]. Following the format in RFC 
3688, the following have been registered.

 URI: urn:ietf:params:xml:ns:yang:yin:1

 URI: urn:ietf:params:xml:ns:yang:1

 Registrant Contact: The IESG.

 XML: N/A, the requested URIs are XML namespaces.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

This document registers two new media types as defined in the 
following sections.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章