Ngsdn-Tutorial-Ⅱ

練習2-Yang,OpenConfig和gNMI基礎

說明:本教程翻譯自Next-Gen SDN TutorialExercise 2 - Yang, OpenConfig, and gNMI basics,自用學習Docker-P4-Tutorial

這套練習旨在讓您更多地了解YANG,OpenConfig和gNMI。

此練習分為三個部分:

  1. 了解YANG語言
  2. 了解YANG編碼
  3. 了解啟用YANG的傳輸協(xié)議(使用gNMI)

第1部分:了解YANG語言

我們將從一個簡單的YANG模塊:demo-port中的yang/demo-port.yang開始

看一下模型并嘗試推導結(jié)構(gòu)。每個葉節(jié)點的有效值是多少?

    leaf speed {
        type identityref {
            base demo-port:SPEED;
        }
        description "Configurable speed of a switch port";
    }

該模型是自包含的,因此閱讀起來并不是很困難。但是,大多數(shù)YANG模型都是定義在許多文件上的,這使得想象出整體結(jié)構(gòu)非常復雜。

為了簡化此過程,我們可以使用一個名為pyang的工具來嘗試可視化模型的結(jié)構(gòu)。

首先輸入yang-tools的Docker:

$ make yang-tools
bash-4.4#

接下來,在demo-port.yang模型上運行pyang

bash-4.4# pyang -f tree demo-port.yang

您應該看到demo-port模塊的樹表示形式。這符合您的期望嗎?

pyang -f tree demo-port.yang

Extra credit:如果您快速完成此操作,則可以嘗試將新的葉子節(jié)點添加到port-configport-state分組,然后重新運行pyang并查看新葉子的添加位置。


我們還可以pyang用來可視化更復雜的模型集,例如Stratum使用的OpenConfig模型集。

這些模型已經(jīng)加載到目錄中的yang-tools容器中/models。

bash-4.4# pyang -f tree \
    -p ietf \
    -p openconfig \
    -p hercules \
    openconfig/interfaces/openconfig-interfaces.yang \
    openconfig/interfaces/openconfig-if-ethernet.yang  \
    openconfig/platform/* \
    openconfig/qos/* \
    openconfig/system/openconfig-system.yang \
    hercules/openconfig-hercules-*.yang  | less

您應該看到中顯示的模型的樹結(jié)構(gòu)less。您可以使用箭頭鍵或j/k上下滾動。鍵入q退出。

在接口模型中,我們可以看到啟用或禁用接口的路徑:interfaces/interface[name]/config/enabled

讀取接口上傳的入數(shù)據(jù)包數(shù)量(in-pkts)的路徑是什么?

Extra credit:如果您有時間,請查看/models目錄中的模型或在Github上瀏覽它們。

嘗試找到enabledin-pkts葉子節(jié)點的描述。

    // 接口上接收到的數(shù)據(jù)包總數(shù),包括所有單播,多播,廣播和錯誤數(shù)據(jù)包等。
    leaf in-pkts {
        type oc-yang:counter64;
        description
            "The total number of packets received on the interface,
            including all unicast, multicast, broadcast and bad packets
            etc.";
        reference
            "RFC 2819: Remote Network Monitoring Management Information
            Base";
    }
    // 該葉子包含接口的已配置期望狀態(tài)。
    // 如RFC 2863中所述,在初始化ifEntry之后,
    // 實現(xiàn)IF-MIB的系統(tǒng)使用“運行中”數(shù)據(jù)存儲區(qū)中該葉子的值來將
    // IF-MIB.ifAdminStatus設置為“up”或“down”。
    // “正在運行”的數(shù)據(jù)存儲區(qū)中的“葉”反映在ifAdminStatus中,
    // 但是如果通過SNMP更改了“ifAdminStatus”,則此葉不受影響。
    leaf enabled {
        type boolean;
        default "true";
        description
            "This leaf contains the configured, desired state of the
            interface.
            Systems that implement the IF-MIB use the value of this
            leaf in the 'running' datastore to set
            IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry
            has been initialized, as described in RFC 2863.
            Changes in this leaf in the 'running' datastore are
            reflected in ifAdminStatus, but if ifAdminStatus is
            changed over SNMP, this leaf is not affected.";
        reference
            "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
    }

提示:查看openconfig-interfaces.yang文件。

第2部分:了解YANG編碼

YANG數(shù)據(jù)編碼沒有標準,但是可以將遵循YANG模型將數(shù)據(jù)編碼為XML、JSON或Protobuf(以及其他格式)。這些格式都有自己的編碼規(guī)范。

首先,我們看一下YANG的第一個XML格式規(guī)范表示。要查看以XML編碼的數(shù)據(jù)的空骨架,請運行:

bash-4.4# pyang -f sample-xml-skeleton demo-port.yang

該骨架應與我們在第1部分中看到的樹表示形式匹配。


YANG-XML-Skeleton

我們還可以使用pyang基于YANG模型生成DSDL模式:

bash-4.4# pyang -f dsdl demo-port.yang | xmllint --format -

模式的第一部分描述了樹結(jié)構(gòu),第二部分描述了葉節(jié)點的值約束。

Extra credit:嘗試添加新的速度標識(例如SPEED_100G)或更改中的port-number值范圍demo-port.yang,然后重新運行pyang -f dsdl。您是否看到您的更改反映在DSDL模式中?


接下來,我們將研究使用協(xié)議緩沖區(qū)(protobuf)編碼數(shù)據(jù)。protobuf編碼是一種比XML更緊湊的二進制編碼,并且可以自動為數(shù)十種語言生成庫。我們可以使用ygotproto_generator產(chǎn)生從我們的洋型號protobuf的消息。

bash-4.4# proto_generator -output_dir=/proto -package_name=tutorial demo-port.yang

proto_generator將生成兩個文件:

  • /proto/tutorial/demo_port/demo_port.proto
  • /proto/tutorial/enums/enums.proto

使用less打開demo_port.proto

bash-4.4# less /proto/tutorial/demo_port/demo_port.proto

該文件包含與YANG模型中定義的結(jié)構(gòu)匹配的top-level Ports消息。您可以看到,proto_generator它還向每個protobuf消息字段添加了一個自定義選項yext.schemapath,該字段顯式映射到Y(jié)ANG葉路徑。枚舉(如tutorial.enums.DemoPortSPEED)不包含在此文件中,proto_generator將它們放在單獨的enums.proto文件中:

使用less打開enums.proto

bash-4.4# less /proto/tutorial/enums/enums.proto

如果您完成剛才的Extra credit,您應該會看到10GB speed的枚舉以及添加的任何其他速度。


我們還可以proto_generator用來為Stratum使用的OpenConfig模型構(gòu)建protobuf消息:

bash-4.4# proto_generator \
    -generate_fakeroot \
    -output_dir=/proto \
    -package_name=openconfig \
    -exclude_modules=ietf-interfaces \
    -compress_paths \
    -base_import_path= \
    -path=ietf,openconfig,hercules \
    openconfig/interfaces/openconfig-interfaces.yang \
    openconfig/interfaces/openconfig-if-ip.yang \
    openconfig/lacp/openconfig-lacp.yang \
    openconfig/platform/openconfig-platform-linecard.yang \
    openconfig/platform/openconfig-platform-port.yang \
    openconfig/platform/openconfig-platform-transceiver.yang \
    openconfig/platform/openconfig-platform.yang \
    openconfig/system/openconfig-system.yang \
    openconfig/vlan/openconfig-vlan.yang \
    hercules/openconfig-hercules-interfaces.yang \
    hercules/openconfig-hercules-platform-chassis.yang \
    hercules/openconfig-hercules-platform-linecard.yang \
    hercules/openconfig-hercules-platform-node.yang \
    hercules/openconfig-hercules-platform-port.yang \
    hercules/openconfig-hercules-platform.yang \
    hercules/openconfig-hercules-qos.yang \
    hercules/openconfig-hercules.yang

您將在目錄/proto/openconfig中找到openconfig.protoenums.proto。

Extra credit:嘗試查找用于啟用端口的Protobuf消息字段或獲取Protobuf消息中的入口數(shù)據(jù)包計數(shù)器。

提示:通過schemapath搜索可能會有所幫助。


ygot也可以用來生成符合YANG模型的Go結(jié)構(gòu),并能夠驗證數(shù)據(jù)的結(jié)構(gòu),類型和值。

Extra credit:如果您有多余的時間或?qū)σ黄鹗褂脃ang和Go感興趣,請嘗試為該demo-port模塊生成Go代碼。

bash-4.4# mkdir -p /goSrc
bash-4.4# generator -output_dir=/goSrc -package_name=tutorial demo-port.yang

看看中的Go文件/goSrc。

現(xiàn)在,您可以退出容器(使用Ctrl-Dexit)。

第3部分:了解啟用YANG的傳輸協(xié)議

有幾種YANG模型不可知協(xié)議,可用于獲取或設置符合模型的數(shù)據(jù),例如NETCONF,RESTCONF和gNMI。

本部分重點介紹通過gNMI使用protobuf編碼。

首先,請確保您的Mininet容器仍在運行。

$ make start
docker-compose up -d
mininet is up-to-date
onos is up-to-date

如果您看到以下輸出,則表明Mininet沒有運行:

Starting mininet ... done
Starting onos    ... done

您將需要回到練習1并安裝轉(zhuǎn)發(fā)規(guī)則,以在此練習之間h1a以及h1b之后的部分重新建立ping。

接下來,我們將使用gNMI客戶端CLI從Mininet網(wǎng)絡中的Stratum交換機leaf1讀取所有配置:

$ util/gnmi-cli --grpc-addr localhost:50001 get /

輸出的第一部分顯示了CLI發(fā)出的請求:

REQUEST
path {
}
type: CONFIG
encoding: PROTO

請求的路徑是空路徑(這意味著配置樹的根),數(shù)據(jù)類型只是配置樹,請求的響應編碼為protobuf。

輸出的第二部分顯示了Stratum的響應:

RESPONSE
notification {
  update {
    path {
    }
    val {
      any_val {
        type_url: "type.googleapis.com/openconfig.Device"
        value: \252\221\231\304\001\... TRUNCATED
      }
    }
  }
}

您可以看到Stratum提供了type的響應openconfig.Device,這是在中定義的頂級消息openconfig.proto。響應是基于protobuf消息的數(shù)據(jù)的二進制編碼。

該值不是很容易讓人理解,但是我們可以使用實用程序來轉(zhuǎn)換答復,該實用程序可以在protobuf消息的二進制表示形式和文本表示形式之間進行轉(zhuǎn)換。

我們可以重新運行該命令,但這一次將輸出通過轉(zhuǎn)換器實用程序傳遞less給管道(然后通過管道輸出使?jié)L動更容易):

$ util/gnmi-cli --grpc-addr localhost:50001 get / | util/oc-pb-decoder | less

響應的內(nèi)容應該更容易閱讀。向下滾動到第一個interface。接口啟用了嗎?端口的速度是多少?

interface:leaf1-eth1

Extra credit:您能找到in-pkts嗎?如果沒有,您為什么認為它們不見了?


gNMI的好處之一是它的“無模式”編碼,它允許客戶端或設備僅更新需要更新的路徑。這對于訂閱特別有用。

首先,讓我們通過請求leaf1h1a之間的配置端口來嘗試無模式表示:

$ util/gnmi-cli --grpc-addr localhost:50001 get \
    /interfaces/interface[name=leaf1-eth3]/config

您應該看到此響應在config- enabledhealth-indicator下包含2個葉子:

RESPONSE
notification {
  update {
    path {
      elem {
        name: "interfaces"
      }
      elem {
        name: "interface"
        key {
          key: "name"
          value: "leaf1-eth3"
        }
      }
      elem {
        name: "config"
      }
      elem {
        name: "enabled"
      }
    }
    val {
      bool_val: true
    }
  }
}
notification {
  update {
    path {
      elem {
        name: "interfaces"
      }
      elem {
        name: "interface"
        key {
          key: "name"
          value: "leaf1-eth3"
        }
      }
      elem {
        name: "config"
      }
      elem {
        name: "health-indicator"
      }
    }
    val {
      string_val: "GOOD"
    }
  }
}

無模式的表示形式為每個包含路徑的葉子提供并update了葉子的值。您可以確認該接口已啟用(設置為true)。

接下來,我們將為leaf1連接到h1a(端口3)的接口訂閱入口單播數(shù)據(jù)包計數(shù)器:

$ util/gnmi-cli --grpc-addr localhost:50001 \
    --interval 1000 sub-sample \
    /interfaces/interface[name=leaf1-eth3]/state/counters/in-unicast-pkts

輸出的第一部分顯示了CLI發(fā)出的請求:

REQUEST
subscribe {
  subscription {
    path {
      elem {
        name: "interfaces"
      }
      elem {
        name: "interface"
        key {
          key: "name"
          value: "leaf1-eth3"
        }
      }
      elem {
        name: "state"
      }
      elem {
        name: "counters"
      }
      elem {
        name: "in-unicast-pkts"
      }
    }
    mode: SAMPLE
    sample_interval: 1000
  }
  updates_only: true
}

我們具有訂閱路徑,訂閱的類型(采樣)和采樣率(每1000ms或1s)。

輸出的第二部分是響應流:

RESPONSE
update {
  timestamp: 1567895852136043891
  update {
    path {
      elem {
        name: "interfaces"
      }
      elem {
        name: "interface"
        key {
          key: "name"
          value: "leaf1-eth3"
        }
      }
      elem {
        name: "state"
      }
      elem {
        name: "counters"
      }
      elem {
        name: "in-unicast-pkts"
      }
    }
    val {
      uint_val: 1592
    }
  }
}

每個響應都有一個時間戳、路徑和新值。因為我們正在采樣,所以您應該看到每秒打印一次新的更新。保持運行狀態(tài),這時候我們也產(chǎn)生一些流量。

在另一個窗口中,打開Mininet CLI并開始ping:

$ make mn-cli
*** Attaching to Mininet CLI...
*** To detach press Ctrl-D (Mininet will keep running)
mininet> h1a ping h1b

在第一個窗口中,uint_val當ping仍在運行時,您應該看到每秒增加1。(如果不完全是1,那么可能會有其他流量,例如NDP消息導致流量增加。)

您可以使用Ctrl-C停止gNMI訂閱。


最后,我們將使用gNMI的變更訂閱功能監(jiān)視鏈接事件。

為第一個交換機的第一個端口的操作狀態(tài)啟動訂閱:

$ util/gnmi-cli --grpc-addr localhost:50001 sub-onchange \
    /interfaces/interface[name=leaf1-eth3]/state/oper-status

您應該立即看到一個響應,指示端口1為UP

RESPONSE
update {
  timestamp: 1567896668419430407
  update {
    path {
      elem {
        name: "interfaces"
      }
      elem {
        name: "interface"
        key {
          key: "name"
          value: "leaf1-eth3"
        }
      }
      elem {
        name: "state"
      }
      elem {
        name: "oper-status"
      }
    }
    val {
      string_val: "UP"
    }
  }
}

在運行Mininet CLI的Shell中,讓我們斷開leaf1連接到h1a的接口:

mininet> sh ifconfig leaf1-eth3 down

您應該在gNMI CLI窗口中看到一個響應,顯示leaf1連接h1a的接口是DOWN

RESPONSE
update {
  timestamp: 1567896891549363399
  update {
    path {
      elem {
        name: "interfaces"
      }
      elem {
        name: "interface"
        key {
          key: "name"
          value: "leaf1-eth3"
        }
      }
      elem {
        name: "state"
      }
      elem {
        name: "oper-status"
      }
    }
    val {
      string_val: "DOWN"
    }
  }
}

我們可以使用以下Mininet命令恢復界面:

mininet> sh ifconfig leaf1-eth3 up

您應該在gNMI CLI窗口中看到另一個響應,指示該接口為UP。


Extra credit:我們還可以使用gNMI禁用或啟用接口。

保留您的gNMI訂閱以運行操作狀態(tài)更改。

在Mininet CLI中,在兩個主機之間啟動ping操作。

mininet> h1a ping h1b

您應該看到在Mininet CLI中顯示了答復。

在第三個窗口中,我們將使用gNMI CLI將enabled葉子的配置值從true更改為false。

$ util/gnmi-cli --grpc-addr localhost:50001 set \
    /interfaces/interface[name=leaf1-eth3]/config/enabled \
    --bool-val false

在gNMI設置窗口中,您應該看到指示enabled葉子的新值的請求:

REQUEST
update {
  path {
    elem {
      name: "interfaces"
    }
    elem {
      name: "interface"
      key {
        key: "name"
        value: "leaf1-eth3"
      }
    }
    elem {
      name: "config"
    }
    elem {
      name: "enabled"
    }
  }
  val {
    bool_val: false
  }
}

在gNMI訂閱窗口中,您應該看到一個新的響應,指示的運行狀態(tài)leaf1-eth3DOWN

RESPONSE
update {
  timestamp: 1567896891549363399
  update {
    path {
      elem {
        name: "interfaces"
      }
      elem {
        name: "interface"
        key {
          key: "name"
          value: "leaf1-eth3"
        }
      }
      elem {
        name: "state"
      }
      elem {
        name: "oper-status"
      }
    }
    val {
      string_val: "DOWN"
    }
  }
}

在Mininet CLI窗口中,您應該觀察到ping命令已停止工作。

接下來,我們可以重新啟用端口:

$ util/gnmi-cli --grpc-addr localhost:50001 set \
    /interfaces/interface[name=leaf1-eth3]/config/enabled \
    --bool-val true

您應該在gNMI訂閱窗口中看到另一個更新,指示該接口是UP,并且ping應該在Mininet CLI窗口中恢復。

恭喜你!

您已經(jīng)完成了第二個練習!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容