<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Amr ElHusseiny</title>
    <description>The latest articles on DEV Community by Amr ElHusseiny (@amrelhusseiny).</description>
    <link>https://dev.to/amrelhusseiny</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F882895%2Fdaec7d62-10ce-45b4-b719-2fa753df53f8.png</url>
      <title>DEV Community: Amr ElHusseiny</title>
      <link>https://dev.to/amrelhusseiny</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amrelhusseiny"/>
    <language>en</language>
    <item>
      <title>Linux Networking Part 1 : Kernel Net Stack</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Wed, 04 Jan 2023 07:58:40 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/linux-networking-part-1-kernel-net-stack-180l</link>
      <guid>https://dev.to/amrelhusseiny/linux-networking-part-1-kernel-net-stack-180l</guid>
      <description>&lt;p&gt;Original article on my blog : &lt;a href="https://amrelhusseiny.github.io/blog/004_linux_0001_understanding_linux_networking/004_linux_0001_understanding_linux_networking_part_1/" rel="noopener noreferrer"&gt;https://amrelhusseiny.github.io/blog/004_linux_0001_understanding_linux_networking/004_linux_0001_understanding_linux_networking_part_1/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to series
&lt;/h2&gt;

&lt;p&gt;1st thing 1st, its very handy to download the uncompiled Linux Kernel code from here &lt;a href="https://www.kernel.org" rel="noopener noreferrer"&gt;https://www.kernel.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this series, we will be exploring the way networking in the server world and how it evolved from using the traditional Linux Kernel Networking stack to network virtualization using OVS and towards handling the load of Telco using NFV and SR-IOV.&lt;/p&gt;

&lt;h2&gt;
  
  
  This article in a pinch
&lt;/h2&gt;

&lt;p&gt;The following diagram only shows in a brief what happens to a packet in the Linux Kernel if you would like to glance by, but for more in depth and handy details, keep on reading.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faz1iitcn6jyow9nxd2ul.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faz1iitcn6jyow9nxd2ul.jpg" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1 : Linux Network Stack
&lt;/h2&gt;

&lt;p&gt;In this article, we are the basic flow IPv4/TCP traffic in Linux Kernel following &lt;a href="https://www.youtube.com/watch?v=6Fl1rsxk4JQ" rel="noopener noreferrer"&gt;Jiri Binc's talk in DevConf CZ 2018&lt;/a&gt;, where he beautifully laied out the packet flow for the whole 7 layers of OSI in the Linux Kernel.&lt;br&gt;
Before we get to the flow path, there is some helper tools and concepts we should be familiar with:&lt;/p&gt;
&lt;h3&gt;
  
  
  1) Ring Buffers
&lt;/h3&gt;

&lt;p&gt;At bootup of NIC devie and loading its driver module by the Kernel, the drivers starts by allocating Rx(Recieve) and Tx(Transmission) queues or buffers refered to as Ring Buffers in the device memory, usually the DMA part of the kernel space of memory, you can check the Max and configured sizes of these buffers :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ethtool -g INTERFACE_NAME &lt;/span&gt;
Ring parameters &lt;span class="k"&gt;for &lt;/span&gt;ens192:
Pre-set maximums:
RX:             4096    &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;, Max size &lt;span class="k"&gt;in &lt;/span&gt;bytes
RX Mini:        2048
RX Jumbo:       4096
TX:             4096    &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;, Max size &lt;span class="k"&gt;in &lt;/span&gt;bytes
Current hardware settings:
RX:             1024    &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;, Configured size &lt;span class="k"&gt;in &lt;/span&gt;bytes
RX Mini:        128
RX Jumbo:       512
TX:             512     &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;, Configured size &lt;span class="k"&gt;in &lt;/span&gt;bytes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In earlier versions of the kernel, a packet arriving to those buffers, would trigger a hardware interrupt to the CPU per packet, which is very intrusive, but thankfully NAPI was introduced to help with this issue, below you will get to know it more.&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Socket Buffers (sk_buff)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;sk_buff (Socket buffer)&lt;/strong&gt;, linux interacts with a packet/cell/segment or whaterver the recieved network unit using the Socket Buffer (sk_buff), and each sk_buff's data and metadata (Headers) are treated separatly so kernel does not have to move the packet in memory, socket buffer acts like bucket, they hold the segment data until its done being processed, socket buffers donot get destroyed with packets, they are released and reallocated to new packets, also when they are utilized, the CPU creates new sk_buffs (new buckets) to handle the additional traffic.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Side Note: "sk_buff" and "skb" are interchangable, while you will find skb widely used in the kernel code&lt;/em&gt;&lt;br&gt;
sk_buff consists of (shown in figure below): &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;packet buffer (sk_buff data)&lt;/strong&gt; : a place where the actual packet and data are stored in kernel space memory (DMA memory space - will explore the concept of DMA below), pointed to using the sk_buff struct, the size of the allocated SKB is equal to TCP MSS+Headroom to allow for MSS to change according to connection and user modifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sk_buff struct (Socket Buffer Metadata)&lt;/strong&gt; :  MetaData about the packet stored in packet buffers (Data), which includes pointers and values, they look as follows, keep in mind these are just a part of the sk_buff struct, &lt;a href="http://lxr.linux.no/linux+v2.6.20/include/linux/skbuff.h#L184" rel="noopener noreferrer"&gt;to read the details of sk_buff.h struct, you can find it here&lt;/a&gt;: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9l645ls2a0l06tu8yc2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9l645ls2a0l06tu8yc2.jpg" alt="Image description" width="751" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Interface (input_dev)&lt;/strong&gt; : refers to the interface name the packet arrived at.&lt;br&gt;
2) &lt;strong&gt;Protocol&lt;/strong&gt; : IPv4, IPv6 and so on.&lt;br&gt;
3) &lt;strong&gt;Head&lt;/strong&gt; : pointer to the start of the sk_buff, which actually starts with an empty space giving headroom for extra headers,  like a VLAN tag for instacnce.&lt;br&gt;
4) &lt;strong&gt;Data&lt;/strong&gt; : the data pointer does not indicate the start of data, rather its used dynamically in the stack functions to pop and push headers, so fo example in the kernel when you say pop Ethernet header, all that actually happens is that the data pointer moves to the start of the IP Header, so no headers are physically popped in the memory.&lt;br&gt;
5) &lt;strong&gt;Tail&lt;/strong&gt; : indicates points to the end of the data part and start of the empty part of the sk_buffer, again this empty part is used for diffirent sized packets, since the sk_buffer is sized according to the MTU configured.&lt;br&gt;
6) &lt;strong&gt;End&lt;/strong&gt; : points to the end of the sk_buff in memory .&lt;br&gt;
7) &lt;strong&gt;MAC &amp;amp; IP &amp;amp; TCP header&lt;/strong&gt; pointers are always stored in the sk_buff metadata, enabling to call them directly without needing to do poping and pushing actions on the sk_buff&lt;br&gt;
8) &lt;strong&gt;cloned&lt;/strong&gt; : the head of the SKB may be cloned, not the data though.&lt;/p&gt;

&lt;p&gt;Note : the packet does not get duplicated in Kernel, actual packet data stays in the packet buffers, with each clone or copy, the packet buffer stays intact, instead a new sk_buff (AKA SKB) is created, so new Metadata pointing to the existing packet buffer, although no copying of the packet in the Kernel, the packet is copied it reaches the application and the SKB is released.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Kernel Interrupts (IRQ vs SoftIRQ)
&lt;/h3&gt;

&lt;p&gt;Simply, interrupts are used to stop the CPU from what it is doing and work on the interrupter's part instead, there are models of interrupts, each include many many types, but following you can see there are two categories for these interrupts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Top-Half Interrupts (Hardware Interrupt)&lt;/strong&gt; : These kind of interrupts is very costly, and as a result the Interrupt handler masks it after 1st use, and then after that the NIC driver starts to use the SoftIRQ (Software interrupt) instead which can be interrupted by itself, you can observe these interrupts :
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /proc/interrupts
&lt;span class="c"&gt;## These are the hardware interrupts, including the IRQ ID , the CPU and the number of interrupts of this type that was triggered .&lt;/span&gt;
           CPU0       CPU1       CPU2       CPU3       CPU4           
  0:         28          0          0          0          0  IO-APIC   2-edge      timer
  1:          0          0          0          0          0  IO-APIC   1-edge      i8042
  8:          0          0          0          0          0  IO-APIC   8-edge      rtc0
  9:          0          0          0          0          0  IO-APIC   9-fasteoi   acpi
 12:          0          0          0          0          0  IO-APIC  12-edge      i8042
 14:          0          0          0          0          0  IO-APIC  14-edge      ata_piix
 15:          0          0          0          0          0  IO-APIC  15-edge      ata_piix

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each interrupt (Hardware Interrupt) is identified by a &lt;strong&gt;vector&lt;/strong&gt; which is a one byte identifier, ranging 0-255, from 0-31 are what are called Exceptions (Non-Maskable) interrupts, range 32-47 are maskable interrupts, from 48 to 255 are allocated to Software interrupts (SoftIRQ).&lt;/p&gt;

&lt;p&gt;Quickly, there are 3 types of Hardware interrupts you will face in the output above, MSI-X, MSI, and legacy IRQs, in a brief MSI stands for Message Signaled Interrupts which replaces the old way of handling interrupt using single pysical pin in the CPU socket for each device.&lt;br&gt;
You can read about MSI and other types of hardware interrupts here &lt;a href="https://en.wikipedia.org/wiki/Message_Signaled_Interrupts" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Message_Signaled_Interrupts&lt;/a&gt;.&lt;br&gt;
Also for more info about Hardware interrupts, check &lt;a href="https://www.cs.montana.edu/courses/spring2005/518/Hypertextbook/jim/media/interrupts_on_linux.pdf" rel="noopener noreferrer"&gt;this great paper "Linux Interrupts : The basic concepts"&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bottom-Half Interrupts (Software Interrupt)&lt;/strong&gt; : 
SoftIRQs runs a queue per CPU, you can find them in the ps output, formated as [ksoftiqd/CPU_Number], these queues polls the device driver for processing traffic, instead of device (NIC) hardware interrupting the CPU each time it recieves traffic, you can see recieve and transmission queues :
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# SoftIRQs queues process &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;ps aux | &lt;span class="nb"&gt;grep &lt;/span&gt;ksoftirqd
root          14  0.0  0.0      0     0 ?        S    22:56   0:00 &lt;span class="o"&gt;[&lt;/span&gt;ksoftirqd/0]
root          23  0.0  0.0      0     0 ?        S    22:56   0:00 &lt;span class="o"&gt;[&lt;/span&gt;ksoftirqd/1]
root          29  0.0  0.0      0     0 ?        S    22:56   0:00 &lt;span class="o"&gt;[&lt;/span&gt;ksoftirqd/2]
root          35  0.0  0.0      0     0 ?        S    22:56   0:00 &lt;span class="o"&gt;[&lt;/span&gt;ksoftirqd/3]
root          41  0.0  0.0      0     0 ?        S    22:56   0:00 &lt;span class="o"&gt;[&lt;/span&gt;ksoftirqd/4]

&lt;span class="c"&gt;# Monitoring the Rx and Tx buffers :&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;watch &lt;span class="nt"&gt;-n1&lt;/span&gt; &lt;span class="nb"&gt;grep &lt;/span&gt;RX /proc/softirqs
Every 1.0s: &lt;span class="nb"&gt;grep &lt;/span&gt;RX /proc/softirqs
      NET_RX:          0          2          0        122  

&lt;span class="nv"&gt;$ &lt;/span&gt;watch &lt;span class="nt"&gt;-n1&lt;/span&gt; &lt;span class="nb"&gt;grep &lt;/span&gt;TX /proc/softirqs
Every 1.0s: &lt;span class="nb"&gt;grep &lt;/span&gt;TX /proc/softirqs
NET_TX:          0          0          0          0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3) Other quick concepts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DMA (Direct Memory Access)&lt;/strong&gt; : NIC devices are PCIe devices, previously in order to write something to the memory, they had to  interrupt the CPU, so the CPU copies the packet to a register and then write it to memory, DMA provides non CPU resources with direct access to the memory without interrupting the CPU, example, when a NIC (Network Interface Card - Hardware) has an Ethernet segment that it wants to write to memory, it uses DMA to directly write it to the Memory, without wasting valuable CPU cycles, these DMA writing calls coming from the NIC are redirected by the NorthBridge on the moterhboard to the RAM instead of the CPU intresting to read more about memory allocation in this article &lt;a href="https://blakerain.com/blog/allocating-memory-for-dma-in-linux" rel="noopener noreferrer"&gt;"Allocating Memory for DMA in Linux - by BLAKE RAIN"&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ring Buffers&lt;/strong&gt; : the NIC and the NIC drivers share a TX and RX ring buffers which basically consists of pointers to the location of packet buffers in the memory, they donot contain data, they are only memory pointers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Top half and Bottom half&lt;/strong&gt; : when a packet is DMAed by the NIC to the memory (DMA is a place in Kernel Memory space where NIC card has access to without need for CPU), an Intrupet (SoftIRQ - Soft Interrupt Request) is sent by the NIC to the CPU informing it that a new packet arrived and waiting to be processed, Top half refers to the actions taken at 1st by the CPU, so instead of stopping everything to process this packet, which can be intrusive, it just acknowledges the intrupt and schedules the Bottom half (whcih is the rest of action that will be taken to process the packet) for later.&lt;/li&gt;
&lt;li&gt;Context Switching : the process of moving between the UserSpace Context and the KernelSpace context for a process, which consumes CPU cycles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System Calls&lt;/strong&gt; : Simply put, system calls are used by user in UserSpace to request service from KernelSpace, &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NAPI - for recieved traffic&lt;/strong&gt;  : (New API - need Hardware support), Extension to device drivers designed for network devices to lower the number of interrupts for recieving packets, which comes into effect when there is a huge amount of packets recieved, but it still works in conjunction with normal intrupption process, it also helps with throttling traffic, if the NIC is recieving too much traffic, the NAPI performs dropping the packets on the NIC level without the need to alert/interrupt the kernel, NAPI is only effective on &lt;em&gt;packet recieve events&lt;/em&gt; .

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SoftIRQ&lt;/strong&gt; : The “softIRQ” system in the Linux kernel is a system that kernel uses to process work outside of the device driver IRQ context, device drivers IRQ (Interrupts) are normally of the highest priority for the Linux kernel, and they pause any other types of intrrupts when they arrive, &lt;em&gt;KsoftIRQ&lt;/em&gt; is the queue initiated as a thread per CPU very early on in the Kernel, they handle the SoftIRQ queueing, you can see these queues counters using &lt;code&gt;$ cat /proc/softirqs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ISR (Interrupt Service Routine)&lt;/strong&gt; : A function in the Kernel responsible for figuring out the nature of the interrupt and what actions to be executed after which the CPU resumes to process previously paused processes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Network flow in brief
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6haf1hpgtebdgtmzrrr1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6haf1hpgtebdgtmzrrr1.jpg" alt="Image description" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure B :&lt;/strong&gt; simple explanation of what is being allocated and how packet goes though Kernel : &lt;br&gt;
1) Very early at Kernel boot up, the CPU allocates packet buffers (RX and TX buffers), and build file descriptors.&lt;br&gt;
2) CPU informs the NIC that new descriptors has been created for the NIC to start using.&lt;br&gt;
3) DMA (Direct Access Memory) fetches descriptors.&lt;br&gt;
4) Packet arrives at NIC.&lt;br&gt;
5) DMA Writes the packet to the RX Ring buffer.&lt;br&gt;
6) NIC informs the driver which informs the CPU that new traffic is ready to be processed using &lt;em&gt;Hardware Interrupt (IRQ)&lt;/em&gt;.&lt;br&gt;
8) After the 1st Hardware interrupt, the Interrupt handler masks it, and instead the driver utilizes the use of &lt;em&gt;Software Interrupt (SoftIRQ)&lt;/em&gt; which is much less costly to the CPU (Hardware Interrupts cannot be interrupted which is very costly for the CPU).&lt;br&gt;
9) The SoftIRQ invokes the NAPI subsystem (Wakes up), which calls the NIC Driver's Polling function. &lt;br&gt;
9) CPU process the incoming packets.&lt;br&gt;
10) After a certain time of the SoftIRQs budget runs out, the NAPI system gets back to sleep, if the budget of the SoftIRQs runs out, the CPU moves on to the next task, and the &lt;em&gt;time_squeezed&lt;/em&gt; counter in the /proc/net/softnet_stats is incremented by 1.&lt;/p&gt;

&lt;p&gt;At NIC initiation, the driver does teh following : &lt;br&gt;
1) Allocates Rx &amp;amp; Tx queues in memory (DMA space).&lt;br&gt;
2) Enable NAPI, which is off by default.&lt;br&gt;
3) Register an Interrupt Handler.&lt;br&gt;
4) Enable Hardware interrupts&lt;/p&gt;

&lt;p&gt;I would recommend for a detailed description of the flow, to check &lt;a href="https://blog.packagecloud.io/monitoring-tuning-linux-networking-stack-receiving-data/" rel="noopener noreferrer"&gt;this link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Keywords
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;File Descriptor : is a number the operating system uses to identify an open file &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - TSS (Tuple Space Search) : this is used by OVS for the Second Level table which is &lt;em&gt;dpcls&lt;/em&gt; basicaly it depends on hash matching to existing tuple, meaning when you are able to match on a tuple of same values in each packet , you create a hash to match it and forward based on that hash, instead of looking up each value separatly .
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Commands Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Show Interrupt counters (IRQs and SoftIRQs)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$ cat /proc/interrupts&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Show SoftIRQ Processes&lt;/td&gt;
&lt;td&gt;`$ ps aux \&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monitor the RX Buffer per CPU (Rx &amp;amp; TX)&lt;/td&gt;
&lt;td&gt;{% raw %}&lt;code&gt;$ watch -n1 grep RX /proc/softirqs&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$ watch -n1 grep TX /proc/softirqs&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;To see the number of packets dropped by the NIC&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$ cat /sys/class/net/ens192/statistics/rx_missed_errors&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.linuxfoundation.org/networking/kernel_flow?s[]=network&amp;amp;s[]=stack" rel="noopener noreferrer"&gt;Linux Foundation Wiki - sk_buff Kernel Flow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kernel.org" rel="noopener noreferrer"&gt;Linux Kernel Archive &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.kernel.org/networking/skbuff.html" rel="noopener noreferrer"&gt;SK Buffer - deep look &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.linuxfoundation.org/networking/sk_buff" rel="noopener noreferrer"&gt;Linux Foundation Explanation of the SK_Buff&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=6Fl1rsxk4JQ" rel="noopener noreferrer"&gt;DevConf CZ 2018 - Linux Packet Flow (Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=noqSZorzooc&amp;amp;list=WL&amp;amp;index=88" rel="noopener noreferrer"&gt;Linux Conf 2017 - Kernel-bypass networking for fun and profit (Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dspace.cuni.cz/bitstream/handle/20.500.11956/99083/120298453.pdf?sequence=1&amp;amp;isAllowed=y" rel="noopener noreferrer"&gt;NIC Offloading - Master Thesis (Ondrej Hlavaty) (PDF)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cse.iitb.ac.in/~mythili/os/anno_slides/network_stack_kernel_bypass_slides.pdf" rel="noopener noreferrer"&gt;Kernel-bypass techniques for high-speed network packet processing (PDF)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=MpjlWt7fvrw&amp;amp;list=WL&amp;amp;index=85" rel="noopener noreferrer"&gt;Kernel-bypass techniques for high-speed network packet processing (Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.cloudflare.com/kernel-bypass/" rel="noopener noreferrer"&gt;CloudFlare - Kernel bypass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.intel.com/content/www/us/en/developer/articles/technical/ovs-dpdk-datapath-classifier.html" rel="noopener noreferrer"&gt;Intel - OVS-DPDK Datapath Classifier - (Very Good for understanding how DPDK exactly works with Intel HW)&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://networkbuilders.intel.com/university/course/open-vswitch-with-dpdk-architectural-deep-dive" rel="noopener noreferrer"&gt;Intel - OVS DPDK Architectural Deep Dive (3 Part Video)&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://networkbuilders.intel.com/university/course/dpdk-open-vswitch-accelerating-the-path-to-the-guest" rel="noopener noreferrer"&gt;Intel - DPDK Open vSwitch: Accelerating the Path to the Guest (4 Part Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opensource.com/article/19/4/interprocess-communication-linux-storage" rel="noopener noreferrer"&gt;Inter Process Communication (3 part Article)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TCP/IP ARCHITECTURE, DESIGN, AND IMPLEMENTATION IN LINUX - Sameer Seth , M. Ajaykumar Venkatesulu (Book)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.linuxfoundation.org/networking/napi" rel="noopener noreferrer"&gt;NAPI (NewAPI) - Network Driver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.packagecloud.io/illustrated-guide-monitoring-tuning-linux-networking-stack-receiving-data/" rel="noopener noreferrer"&gt;Illustrated Guide to Monitoring and Tuning the Linux Networking Stack: Receiving Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf" rel="noopener noreferrer"&gt;Red Hat Enterprise Linux Network Performance Tuning Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/a/59491902/20268697" rel="noopener noreferrer"&gt;Stack Overflow - Ring Buffers and DMA Memory - illustration of the process &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://vger.kernel.org/~davem/skb_data.html" rel="noopener noreferrer"&gt;How SKBs work&lt;/a&gt;

&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>help</category>
      <category>discuss</category>
    </item>
    <item>
      <title>gNMI Network Automation (Part 3) : gNMI Telemetry, Telegraf &amp; InfluxDB</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Sat, 19 Nov 2022 23:20:01 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/gnmi-network-automation-part-3-gnmi-telemetry-telegraf-influxdb-15b8</link>
      <guid>https://dev.to/amrelhusseiny/gnmi-network-automation-part-3-gnmi-telemetry-telegraf-influxdb-15b8</guid>
      <description>&lt;h1&gt;
  
  
  gNMI Network Automation (Part 3) : gNMI Telemetry, Telegraf &amp;amp; InfluxDB
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This article is based on Damien Garros's talk in NANOG 77 &lt;a href="https://www.youtube.com/watch?v=lzppzWGRHGo&amp;amp;list=WL&amp;amp;index=49" rel="noopener noreferrer"&gt;"Getting started with modern time series database"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We are used to monitoring network devices using SNMP by pulling devices statistics through an RRD server (example Cacti), but a new approach (not so new) is replacing SNMP by relying on Streaming (Push) telemetry from device to server instead of pulling, by using gNMI (Network gRPC protocol originally developed by Google, now widely adopted by vendors).&lt;/p&gt;

&lt;p&gt;Summary of steps will be taken : &lt;br&gt;
1) Setup Containerlab and prepare the IOS-XR image using&lt;a href="https://dev.to/amrelhusseiny/network-automation-simulating-network-topologies-with-containers-and-gnmi-1obm"&gt; Part1&lt;/a&gt;.&lt;br&gt;
2) Get to know a little bit abouyt gNMI and gRPC and how to read configuration templates for OpenConfig and Vendor Specific in &lt;a href="https://dev.to/amrelhusseiny/gnmi-network-automation-part-2-gnmi-configuration-ciscos-ios-xr-2fhj"&gt;Part2&lt;/a&gt; .&lt;br&gt;
3) Start our testing Network topology.&lt;br&gt;
4) Configuring 2 IOS-XR PE/P routers using gNMI.&lt;br&gt;
5) Pulling and configuring both Telegraf and InfluxDB containers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note : All Lab files used in this article, you can find in my Github &lt;a href="https://github.com/amroashram/containerlab_labs/tree/main/04_telemetry" rel="noopener noreferrer"&gt;here&lt;/a&gt; .&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Brief about topology
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8mgb98m43347mkqzptvj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8mgb98m43347mkqzptvj.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1st, we have 2 containerlab topology files, one for the Network topology that we are will be collecting telemtry data from, and one for the Telegraf (Collector) and InfluxDB (Time Streamed Data Database) .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The network topolgy consists of :&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2 IOS-XR 6.5.1 PE/P routers : running a full L3VPN Backbone protocols, IS-IS/MPLS/LDP/MP-BGP and will be configured using gNMI configuration files you can find ready in the github page, I chose to confgiure them using gNMI so you can check how to use gNMI also for configuration management not just for Telemetry.&lt;/li&gt;
&lt;li&gt;2 Open FRRouting containers runing as CE routers, configured with eBGP, configuration files are loaded onto them while initiating using Containerlab, so nothing to be done there, although its cool to get to know FRR, if you want to log onto the FRR container, you can use '# docker exec -it CE_NAME vtysh', you will find its prompt is like Cisco's IOS.&lt;/li&gt;
&lt;li&gt;2 Linux containers connected to CEs, will be used to generate traffic using IPerf3.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Running the topology
&lt;/h2&gt;

&lt;p&gt;1) Initiate the topology using Containerlab : &lt;br&gt;
&lt;code&gt;$ containerlab deploy -t 04_topology.clab.yml&lt;/code&gt;&lt;br&gt;
The containlab template loks like follows, you can also find&lt;a href="https://github.com/amroashram/containerlab_labs/blob/main/04_telemetry/04_topology.clab.yml" rel="noopener noreferrer"&gt; it here&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;04_topology&lt;/span&gt;

&lt;span class="na"&gt;topology&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# CEs using  RRouting open image&lt;/span&gt;
    &lt;span class="na"&gt;CE1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frrouting/frr:v7.5.1&lt;/span&gt;
        &lt;span class="na"&gt;binds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Binds used to copy files to the created containers at start&lt;/span&gt;
            &lt;span class="c1"&gt;# 1) FRR uses the Dameon file to check whiches protocols to spin up as it runs as seprate process&lt;/span&gt;
            &lt;span class="c1"&gt;# same daemons file will be used on both CEs as they are running the same protocols.&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;template_config/04_CE1_FRR_daemons:/etc/frr/daemons&lt;/span&gt;
            &lt;span class="c1"&gt;# 2) Router configuration is loaded configuring interfaces, and eBGP session.&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;template_config/04_CE1_FRR_conf:/etc/frr/frr.conf&lt;/span&gt;
    &lt;span class="na"&gt;CE2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frrouting/frr:v7.5.1&lt;/span&gt;
        &lt;span class="na"&gt;binds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;template_config/04_CE1_FRR_daemons:/etc/frr/daemons&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;template_config/04_CE2_FRR_conf:/etc/frr/frr.conf&lt;/span&gt;
    &lt;span class="c1"&gt;# Backbone PEs (ISIS/MP-BGP/MPLS)&lt;/span&gt;
    &lt;span class="na"&gt;PE1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-xrv9k&lt;/span&gt;
        &lt;span class="c1"&gt;# To be able to use this image, you need to check Part 1 and 2 so you can create an IOS-XR container.&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-xrv9k:7.2.1&lt;/span&gt;
    &lt;span class="na"&gt;PE2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-xrv9k&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-xrv9k:7.2.1&lt;/span&gt;
    &lt;span class="na"&gt;PC1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;praqma/network-multitool:latest&lt;/span&gt;
        &lt;span class="c1"&gt;# Installing IPerf3 at startup&lt;/span&gt;
    &lt;span class="na"&gt;PC2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;praqma/network-multitool:latest&lt;/span&gt;

  &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PC1:eth1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CE1:eth2"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CE1:eth3"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE1:eth3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE1:eth2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE2:eth2"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE2:eth3"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CE2:eth3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CE2:eth2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PC2:eth1"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The IOS-XR images will take 10 to 15 minutes, you can follow its progressusing Docker logs, you should see the following message when its fully started up :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;docker logs &lt;span class="nt"&gt;-f&lt;/span&gt; clab-04_topology-PE1
.......
2022-11-19 20:01:16,258: launch     INFO     Startup &lt;span class="nb"&gt;complete &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;: 0:08:11.193191


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;2) FRR CEs are already configured (configuraiton under the &lt;code&gt;template_config/04_CE1_FRR_conf &amp;amp; template_config/04_CE2_FRR_conf&lt;/code&gt;), now to configure the Linux containers interfaces and default gateway, create or run the file on Github, simply configuring the Linux interfaces : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;clab-04_topology-PC1 ip &lt;span class="nb"&gt;link set &lt;/span&gt;eth1 up
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;clab-04_topology-PC1 ip addr add 10.0.10.2/24 dev eth1
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;clab-04_topology-PC1 ip route add 10.0.20.0/24 via 10.0.10.1 dev eth1
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;clab-04_topology-PC1 apk add iperf3 

&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;clab-04_topology-PC2 ip &lt;span class="nb"&gt;link set &lt;/span&gt;eth1 up
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;clab-04_topology-PC2 ip addr add 10.0.20.2/24 dev eth1
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;clab-04_topology-PC2 ip route add 10.0.10.0/24 via 10.0.20.1 dev eth1
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;clab-04_topology-PC2 apk add iperf3 


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;3) To configure the PEs, using gNMI, make sure to have gNMIC tool installed , then run the following 2 commands under the gnmi_config directory : &lt;br&gt;
Please find the configuration files in the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/amroashram/containerlab_labs/blob/main/04_telemetry/gnmi_config/04_xrv_pe1_gnmi.yml" rel="noopener noreferrer"&gt;04_xrv_pe1_gnmi.yml &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/amroashram/containerlab_labs/blob/main/04_telemetry/gnmi_config/04_xrv_pe2_gnmi.yml" rel="noopener noreferrer"&gt;04_xrv_pe2_gnmi.yml &lt;/a&gt;
```bash
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;$ gnmic -a clab-04_topology-PE1 --insecure -u admin -p admin -e json_ietf  set --request-file 04_xrv_pe1_gnmi.yml &lt;br&gt;
 $ gnmic -a clab-04_topology-PE2 --insecure -u admin -p admin -e json_ietf  set --request-file 04_xrv_pe2_gnmi.yml &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;For this gNMI configuration file, you can check the previous article where you will find a detailed description of each configuration part.

Now, the testing network topology is readymoving to our main scope, Telemetry.

## Our telemetry setup now
Before we get into the details, lets start by pulling the needed containers : 
```bash


docker pull telegraf
docker pull influxdb


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We will use containerlab replacing Docker Compose to spin up the containers wth their configuration, before running the container, we will have a brief about the tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Telegraf (Collector)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmjzxpwb2qiqc9ystjs4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmjzxpwb2qiqc9ystjs4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is 2 ways in subscribing to gNMI telemtry: &lt;br&gt;
1) Dial-Out : you configure your network device to initiate the TCP session to the collectore and stream out the configured telemetry points, not recommended as it means you need to configure the subscription Metrics on each node, and in case you need to do a change, you need to roll out these changes to all devices.&lt;br&gt;
2) Dial-In : We use this method in our Lab , we only allow gNMI service/port on our IOS-XR devices, then we do all the sunscription configuration on our gNMI Collector (Telegraf).&lt;/p&gt;

&lt;p&gt;Telegraf is the collector agent which will Dial-In/subscribe to a Metric on the device, Telegraf has a &lt;a href="https://github.com/influxdata/telegraf/tree/master/plugins/inputs/gnmi" rel="noopener noreferrer"&gt;plugin for gNMI &lt;/a&gt;developed by Cisco initially that enables configuration of gNMI telemtry, since Telegraf is not only usef for gNMI .&lt;/p&gt;

&lt;p&gt;To understand configuraiton of the Telegraf Container, you have :&lt;br&gt;
1) &lt;a href="https://github.com/influxdata/telegraf/blob/master/docs/CONFIGURATION.md#agent" rel="noopener noreferrer"&gt;Agent&lt;/a&gt; : In this configuration, you would specify interval in which measurements are taken, output batch size, since telegraf aggregates the metrics before sending them out to the Influx database, so you configure the batch size, and the buffer limit for it, so when it momentarliy lose connection to the database, it can cash those metrics until connection is restored and then send them all at once, and so on, here am using the default generated configuration.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;agent&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="s"&gt;interval = "10s"&lt;/span&gt;
  &lt;span class="s"&gt;round_interval = &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="s"&gt;metric_batch_size = &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;
  &lt;span class="s"&gt;metric_buffer_limit = &lt;/span&gt;&lt;span class="m"&gt;10000&lt;/span&gt;
  &lt;span class="s"&gt;collection_jitter = "0s"&lt;/span&gt;
  &lt;span class="s"&gt;flush_interval = "10s"&lt;/span&gt;
  &lt;span class="s"&gt;flush_jitter = "0s"&lt;/span&gt;
  &lt;span class="s"&gt;precision = "0s"&lt;/span&gt;
  &lt;span class="s"&gt;hostname = "telegraf"&lt;/span&gt;
  &lt;span class="s"&gt;omit_hostname = &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;3) &lt;a href="https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_INPUT.md" rel="noopener noreferrer"&gt;Input plugins&lt;/a&gt; : are responsible for transforming incoming data stream from device format (Example : Json , Binary, Protobuffs, etc) to &lt;a href="https://github.com/influxdata/telegraf/blob/master/docs/METRICS.md" rel="noopener noreferrer"&gt;Telegraf Metics&lt;/a&gt; format ( Measurement Name, Tages, Fields, Timestamp ), in our case&lt;a href="https://github.com/influxdata/telegraf/tree/master/plugins/inputs/gnmi" rel="noopener noreferrer"&gt; Cisco developed a gNMI Input plugin&lt;/a&gt; which has been merged to the main Git for Telegraf which subscribes to gNMI Paths.&lt;br&gt;
      For the path that I used , please refer to &lt;a href="https://dev.to/amrelhusseiny/gnmi-network-automation-part-2-gnmi-configuration-ciscos-ios-xr-2fhj"&gt;my previous gNMI guide&lt;/a&gt;, you can use either Cisco's Yang Paths or OpenConfig's , here I will be using OpenConfig's, this will make it easier to use across many vendors.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="pi"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;inputs.gnmi&lt;/span&gt;&lt;span class="pi"&gt;]]&lt;/span&gt;
    &lt;span class="s"&gt;addresses = ["clab-testing_topology-PE1:57400"]&lt;/span&gt;
    &lt;span class="s"&gt;username = "admin"&lt;/span&gt;
    &lt;span class="s"&gt;password = "admin"&lt;/span&gt;
    &lt;span class="s"&gt;redial = "10s"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we can include multiple subscriptions under the same gNMI input module, you can name each one with your preferred description, for Paths, you can use either the OpneConfig ones or the Vendor specific ones, for me i prefer to use gNMIC tool to check what is the output for each module before deciding to use which path, for details on how to use gNMIC, you can refer to&lt;a href="https://dev.to/amrelhusseiny/gnmi-network-automation-part-2-gnmi-configuration-ciscos-ios-xr-2fhj"&gt; my previous article&lt;/a&gt;.&lt;br&gt;
We are creating 2 subscriptions in this example.&lt;br&gt;
1st example is for interface counters, which we want to take on a "Sample" basis in time intervals:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="pi"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;inputs.gnmi.subscription&lt;/span&gt;&lt;span class="pi"&gt;]]&lt;/span&gt;
    &lt;span class="s"&gt;name = "interfaces_counters"&lt;/span&gt;
    &lt;span class="s"&gt;origin = "openconfig-interfaces"&lt;/span&gt;
    &lt;span class="s"&gt;#path = '/interfaces/interface[name="GigabitEthernet0/0/0/1"]/state/counters'&lt;/span&gt;
    &lt;span class="s"&gt;path = '/interfaces/interface/state/counters'&lt;/span&gt;
    &lt;span class="s"&gt;subscription_mode = "sample"&lt;/span&gt; &lt;span class="c1"&gt;# you can find the modes in the gNMI standard&lt;/span&gt;
    &lt;span class="c1"&gt;# Setting sample to 30 Seconds, because on Cisco IOS-XR interval is minimum at 30 Seconds&lt;/span&gt;
    &lt;span class="s"&gt;sample_interval = "30s"&lt;/span&gt;
    &lt;span class="s"&gt;heartbeat_interval = "60s"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Before our next article and Grafana integration, InfluxDB provides a very good WebUI just like Grafana's to see your data collected, just to show you after spinning up our configuration, Interfsces output with some Iperf traffic generation from our linux edge containers looks as follows in Influx dashboard : &lt;/p&gt;

&lt;p&gt;2nd example, we want  to get the IS-IS Adjacency table but in structured way instead of relying on the old SSH/CLI parsing way, you can export/Putput the data in Json format to your script for example, this subscription wont create a graph, instead, its more for Data gathering, this shows you the extensibilty of Telemetry in gNMI, not just for counters, but it can be used for Operational data : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="pi"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;inputs.gnmi.subscription&lt;/span&gt;&lt;span class="pi"&gt;]]&lt;/span&gt;
    &lt;span class="s"&gt;name = "isis_advacency"&lt;/span&gt;
    &lt;span class="s"&gt;origin = "Cisco-IOS-XR-clns-isis-oper"&lt;/span&gt;
    &lt;span class="s"&gt;path = '/isis/instances/instance[instance-name="default"]/neighbors'&lt;/span&gt;
    &lt;span class="s"&gt;subscription_mode = "on_change"&lt;/span&gt; &lt;span class="c1"&gt;# you can find the modes in the gNMI standard&lt;/span&gt;
    &lt;span class="s"&gt;heartbeat_interval = "60s"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;3) &lt;a href="https://github.com/influxdata/telegraf/blob/master/docs/PROCESSORS.md" rel="noopener noreferrer"&gt;Processor&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/influxdata/telegraf/blob/master/docs/AGGREGATORS.md" rel="noopener noreferrer"&gt;Aggregator&lt;/a&gt; plugins: processors are used to filter, decorate, or trasform input as its coming in, unlike aggregators, which are applied over a period of inputs to produce outputs like mean, minimum, maximum and count.&lt;br&gt;
4) &lt;a href="https://github.com/influxdata/telegraf/blob/master/docs/DATA_FORMATS_OUTPUT.md" rel="noopener noreferrer"&gt;Output Plugins&lt;/a&gt;: Just like Input plugins, this shapes data towards the external resource that will store or analyze the data, in our case, we will be using InfluxDB, which provides and Output Plugin for Telegraf.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="pi"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;outputs.influxdb_v2&lt;/span&gt;&lt;span class="pi"&gt;]]&lt;/span&gt;
   &lt;span class="s"&gt;urls = ["http://clab-03_ansible_iosxr_linux_telemetry-influxDB:8086"]&lt;/span&gt;
   &lt;span class="s"&gt;token = "Df-veQgYbF i m40KZfT×q1zHUN3- - IRV4WTHdfXsK_ SUNCiX6171pjGZMHOgYl jmgG-BiwMprBLocpX4L82xg=="&lt;/span&gt;
   &lt;span class="s"&gt;organization = "test_org"&lt;/span&gt;
   &lt;span class="s"&gt;bucket = "test_bucket"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can find the fullconfiguration file fo &lt;a href="https://github.com/amroashram/containerlab_labs/blob/main/04_telemetry/template_config/telegraf.conf" rel="noopener noreferrer"&gt;Telegraf here&lt;/a&gt;, we will use it later while spinning up the container.&lt;/p&gt;

&lt;h3&gt;
  
  
  InfluxDB (Time Streaming Database)
&lt;/h3&gt;

&lt;p&gt;We will use InfluxDB to store the telemetry and collector's data, so we can graph it either using Grafana or in our case, InfluxDB now offers some of Grafana's functionallity, we will use Grafana in the next article.&lt;br&gt;
To configure Influx, its very simple, you just need to set some Env variables as per their&lt;a href="https://hub.docker.com/_/influxdb" rel="noopener noreferrer"&gt; official Docker guide &lt;/a&gt;, which we will do using ContainerLab.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the Telegraf and InfluxDB contianers
&lt;/h3&gt;

&lt;p&gt;Now we will use a second ContainerLab file to initiate the Telegraf+Config and InfluxDB+ENV variables&lt;/p&gt;

&lt;p&gt;Note : I kept the Network topology setup separate from Telegraf&amp;amp;InfluxDB t give you the ease of reconfiguring telemtry without having to destroy and redeploy the IOS-XR images which takes a long time to start.&lt;/p&gt;

&lt;p&gt;Okey, the 2nd containerlab file looks as follows , &lt;a href="https://github.com/amroashram/containerlab_labs/blob/main/04_telemetry/04_telemetry.clab.yaml" rel="noopener noreferrer"&gt;link to github&lt;/a&gt; : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# 04_telemetry.clab.yaml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;04_telemetry&lt;/span&gt;

&lt;span class="na"&gt;topology&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# InfluxDB ------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class="na"&gt;influxDB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;influxdb:latest&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;## This port will be used for Telegraf to connect to &lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8086:8086&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;DOCKER_INFLUXDB_INIT_MODE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;setup&lt;/span&gt;
            &lt;span class="na"&gt;DOCKER_INFLUXDB_INIT_USERNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;influx_super&lt;/span&gt;
            &lt;span class="na"&gt;DOCKER_INFLUXDB_INIT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1020304050607&lt;/span&gt;
            &lt;span class="na"&gt;DOCKER_INFLUXDB_INIT_ORG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test_org&lt;/span&gt;
            &lt;span class="na"&gt;DOCKER_INFLUXDB_INIT_BUCKET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test_bucket&lt;/span&gt;
            &lt;span class="na"&gt;DOCKER_INFLUXDB_INIT_ADMIN_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Df-veQgYbF&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;i&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;m40KZfT×q1zHUN3-&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;IRV4WTHdfXsK_&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;SUNCiX6171pjGZMHOgYl&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;jmgG-BiwMprBLocpX4L82xg=="&lt;/span&gt;
    &lt;span class="c1"&gt;# Telegraf ------------------------------------------------------------------------&lt;/span&gt;
    &lt;span class="na"&gt;telegraf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;telegraf:latest&lt;/span&gt;
        &lt;span class="na"&gt;binds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;telegraf.conf:/etc/telegraf/telegraf.conf:ro&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;57000:57000&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Run &lt;br&gt;
&lt;code&gt;$ containerlab deploy -t 04_telemetry.clab.yaml&lt;/code&gt;&lt;br&gt;
You can check no errors on the Telegraf connection to the InfluxDB or to the PE1 gNMI subscription using docker logs : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

root@vnet:/home/vnet/github_2# docker logs -f clab-04_telemetry-telegraf
2022-11-19T21:57:36Z I! Using config file: /etc/telegraf/telegraf.conf
2022-11-19T21:57:36Z I! Starting Telegraf 1.24.3
2022-11-19T21:57:36Z I! Available plugins: 222 inputs, 9 aggregators, 26 processors, 20 parsers, 57 outputs
2022-11-19T21:57:36Z I! Loaded inputs: gnmi
2022-11-19T21:57:36Z I! Loaded aggregators: 
2022-11-19T21:57:36Z I! Loaded processors: 
2022-11-19T21:57:36Z I! Loaded outputs: influxdb_v2
2022-11-19T21:57:36Z I! Tags enabled: host=telegraf
2022-11-19T21:57:36Z I! [agent] Config: Interval:10s, Quiet:false, Hostname:"telegraf", Flush Interval:10s



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After that log into the Linux container &lt;em&gt;clab-04_topology-PC2&lt;/em&gt; , and 1st test connectivity to &lt;em&gt;clab-04_topology-PC1&lt;/em&gt;, and then if ping is okey, start IPerf3 server on PC2 : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

clab-04_topology-PC2#ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 10.0.10.2
PING 10.0.10.2 &lt;span class="o"&gt;(&lt;/span&gt;10.0.10.2&lt;span class="o"&gt;)&lt;/span&gt; 56&lt;span class="o"&gt;(&lt;/span&gt;84&lt;span class="o"&gt;)&lt;/span&gt; bytes of data.
64 bytes from 10.0.10.2: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;19.4 ms
64 bytes from 10.0.10.2: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.57 ms
64 bytes from 10.0.10.2: &lt;span class="nv"&gt;icmp_seq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.44 ms
3 packets transmitted, 3 received, 0% packet loss, &lt;span class="nb"&gt;time &lt;/span&gt;2003ms
rtt min/avg/max/mdev &lt;span class="o"&gt;=&lt;/span&gt; 1.438/7.469/19.395/8.433 ms

clab-04_topology-PC2# iperf3 &lt;span class="nt"&gt;-s&lt;/span&gt;
&lt;span class="nt"&gt;-----------------------------------------------------------&lt;/span&gt;
Server listening on 5201
&lt;span class="nt"&gt;-----------------------------------------------------------&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And on &lt;em&gt;clab-04_topology-PC1&lt;/em&gt; lets generate some traffic : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;iperf3 &lt;span class="nt"&gt;-c&lt;/span&gt; 10.0.20.2 &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; 1000M
Connecting to host 10.0.20.2, port 5201
&lt;span class="o"&gt;[&lt;/span&gt;  5] &lt;span class="nb"&gt;local &lt;/span&gt;10.0.10.2 port 53437 connected to 10.0.20.2 port 5201
&lt;span class="o"&gt;[&lt;/span&gt; ID] Interval           Transfer     Bitrate         Total Datagrams
&lt;span class="o"&gt;[&lt;/span&gt;  5]   0.00-1.00   sec  98.2 MBytes   824 Mbits/sec  71323  
&lt;span class="o"&gt;[&lt;/span&gt;  5]   1.00-2.00   sec  95.9 MBytes   804 Mbits/sec  69605  
&lt;span class="o"&gt;[&lt;/span&gt;  5]   2.00-3.00   sec  98.3 MBytes   824 Mbits/sec  71356  
&lt;span class="o"&gt;[&lt;/span&gt;  5]   3.00-4.00   sec  98.3 MBytes   825 Mbits/sec  71405  
&lt;span class="o"&gt;[&lt;/span&gt;  5]   4.00-5.00   sec  98.5 MBytes   827 Mbits/sec  71556  
&lt;span class="o"&gt;[&lt;/span&gt;  5]   5.00-6.00   sec  98.2 MBytes   823 Mbits/sec  71283  
&lt;span class="o"&gt;[&lt;/span&gt;  5]   6.00-7.00   sec  97.9 MBytes   821 Mbits/sec  71070  
&lt;span class="o"&gt;[&lt;/span&gt;  5]   7.00-8.00   sec  98.2 MBytes   824 Mbits/sec  71290  
&lt;span class="o"&gt;[&lt;/span&gt;  5]   8.00-9.00   sec  98.1 MBytes   823 Mbits/sec  71223  
&lt;span class="o"&gt;[&lt;/span&gt;  5]   9.00-10.00  sec  98.4 MBytes   825 Mbits/sec  71455  
- - - - - - - - - - - - - - - - - - - - - - - - -
&lt;span class="o"&gt;[&lt;/span&gt; ID] Interval           Transfer     Bitrate         Jitter    Lost/Total Datagrams
&lt;span class="o"&gt;[&lt;/span&gt;  5]   0.00-10.00  sec   980 MBytes   822 Mbits/sec  0.000 ms  0/711566 &lt;span class="o"&gt;(&lt;/span&gt;0%&lt;span class="o"&gt;)&lt;/span&gt;  sender
&lt;span class="o"&gt;[&lt;/span&gt;  5]   0.00-10.26  sec   245 KBytes   196 Kbits/sec  2.803 ms  710324/710498 &lt;span class="o"&gt;(&lt;/span&gt;1e+02%&lt;span class="o"&gt;)&lt;/span&gt;  receiver

iperf Done.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can generate traffic for somewhile and then lets head to InfluxDB to see our telemetry plot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Graphs on InfluxDB
&lt;/h3&gt;

&lt;p&gt;You are able to login to the Web portal of the InfluxDB from your local network, to get ip of the InfluxDB, you can use Containerlab to inspect all the current running nodes : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

containerlab inspect &lt;span class="nt"&gt;-a&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;influx
| 1 | 04_telemetry.clab.yaml | 04_telemetry | clab-04_telemetry-influxDB | 2797cc685296 | influxdb:latest                 | linux    | running | 172.20.20.8/24 | 2001:172:20:20::8/64 |


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Open your web browser to &lt;a href="http://172.20.20.8:8086" rel="noopener noreferrer"&gt;http://172.20.20.8:8086&lt;/a&gt; with user influx_super and password 1020304050607 which we setup in the &lt;em&gt;04_telemetry.clab.yaml&lt;/em&gt;.&lt;br&gt;
Go to Data Explorer , then choose filter as following in snapshot :&lt;br&gt;
1- this shows the interface counters of interface Ge0/0/1, but this accumalates, it does not show the current count only , as on Cisco interface counters just adds up over time, to show the diffirence only , go to step 2.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fso2tlstew20ejj56kqwu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fso2tlstew20ejj56kqwu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2- Change view to 'script editor' and search 'filter function' for 'diffirence' function , add it, and remove the line with 'yield mean' now you only can see the increase/decrease of bytes count on the interface. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0f9wxdqylp19kyu37n7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0f9wxdqylp19kyu37n7.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets also have a look at the ISIS adjaceny neibors on PE1 , this is the benefit of gNMI, it provides more than just counters, you can see even the routing table on change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fycxa5slm7skdw18zo26d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fycxa5slm7skdw18zo26d.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thats it, you can tweek the telegraf.conf file to add your telemetry subscriptions which you can get from the yang files described in &lt;a href="https://dev.to/amrelhusseiny/gnmi-network-automation-part-2-gnmi-configuration-ciscos-ios-xr-2fhj"&gt;Part 2 of this guide &lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;Final thing , to destroy all the created containers, just type &lt;code&gt;$ containerlab destroy -a&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article :) , next will be intergration with Grafana .&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.networktocode.com/post/monitor_your_network_with_gnmi_snmp_and_grafana/" rel="noopener noreferrer"&gt;Blog - Network monitoring using Grafana/gNMI/SNMP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pc.nanog.org/static/published/meetings/NANOG77/2057/20191029_Garros_Getting_Started_With_v1.pdf" rel="noopener noreferrer"&gt;NANOG 77 - Demonstration of Network Monitoring with Grafana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dgarros/nanog77-tsdb-tutorial" rel="noopener noreferrer"&gt;NANOG77 - Demonstration Lab Files (Github)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ultraconfig.com.au/blog/cisco-telemetry-tutorial-with-telegraf-influxdb-and-grafana/" rel="noopener noreferrer"&gt;Blog - CISCO TELEMETRY TUTORIAL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cisco.com/c/en/us/td/docs/iosxr/asr9000/telemetry/b-telemetry-cg-asr9000-61x/b-telemetry-cg-asr9000-61x_chapter_011.html" rel="noopener noreferrer"&gt;Doc - Telemetry Configuration Guide for Cisco&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/influxdata/telegraf/tree/master/plugins/inputs/cisco_telemetry_mdt" rel="noopener noreferrer"&gt;Github - Cisco's MDT Plugin for Telegraf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.influxdata.com/flux/v0.x/stdlib/universe/last/" rel="noopener noreferrer"&gt;InfluxDB Docs - Check for graphs functions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gnmi</category>
      <category>networkautomation</category>
      <category>openconfig</category>
    </item>
    <item>
      <title>gNMI Network Automation (Part 2) : gNMI Configuration Cisco's IOS-XR</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Tue, 08 Nov 2022 18:48:06 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/gnmi-network-automation-part-2-gnmi-configuration-ciscos-ios-xr-2fhj</link>
      <guid>https://dev.to/amrelhusseiny/gnmi-network-automation-part-2-gnmi-configuration-ciscos-ios-xr-2fhj</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this post we are going to focus on 2 parts:&lt;br&gt;
1- Use gRPC to configure a l3VPN backbone (IS-IS,MPLS,MP-BGP) in a 2 node IOS-XR backbone PE/P routers.&lt;br&gt;
2- 2 customer edge CPEs (Using PreConfigured FRR Nodes) and 2 net-tool Linux containers will be used for testing connectivity (Configured using Bash).&lt;br&gt;
3- Next article , we will use gNMI telemetry for gathering interface data and BGP/ISIS adjacency and collect them using Telegraf/InfluxDB and visualize them using Grafana.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenConfig vs Vendor
&lt;/h3&gt;

&lt;p&gt;1st you need to separate gNMI from OpenConfig, gNMI is implemented very maturely and you can find nearly all Network vendors adheres to its standards, this gives you the way to send gRPC calls to the devices, on the other hand OpenConfig implementation widely vary, as you will see in this tutorial which focuses on IOS-XR, some features can be fully configured using OpenConfig schemas/Yangs, and some features mix and match between OpenConfig and Vendor specific Yangs.&lt;/p&gt;

&lt;p&gt;For myself, I'd say there is a long way for OpenConfig to provide a uniform way to interact with multiple platforms.&lt;/p&gt;

&lt;p&gt;A very good article to check for how OpenConfig implements the concept of VRFs and routing protocol, is to check their official &lt;a href="https://www.openconfig.net/docs/models/network_instance_redist/" rel="noopener noreferrer"&gt;OpenConfig RIB Approach&lt;/a&gt;, consider this a prerequsiste before you proceed with the below example, as Openconfig replaces the concept of VRF with a Network Instance, and instead of VRF being one RIB (Table in OpenConfig) with multiple Protocols (OSPF,BGP,..) installing routes into, some vendors do treat all the RIBs/tables under one VRF/Network-instance as one entitiy (RIB/Table), and so all protocol routes are used for best path selection like traditional routing, and some other vendors like Nokia keeps each Protocol table separate under each Network-instance, in this case, you will need to do OpenConfig's Table-Connection between diffirent protocols tables under the same Network-Instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can you figure out whether a vendor is implementing single table RIB or multi-table RIB ?&lt;/strong&gt;&lt;br&gt;
You can always check the Deviations Yang file under the Yang implementation of the vendor, in our case its not supported on IOS-XR, as the deviations file shows, you can see in output below , that tables and table connections are not supported : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cat &lt;/span&gt;cisco-xr-openconfig-network-instance-deviations.yang
  deviation &lt;span class="s2"&gt;"/oc-netinst:network-instances/oc-netinst:network-instance/oc-netinst:table-connections/oc-netinst:table-connection"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    deviate not-supported&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  deviation &lt;span class="s2"&gt;"/oc-netinst:network-instances/oc-netinst:network-instance/oc-netinst:interfaces/oc-netinst:interface/oc-netinst:config/oc-netinst:associated-address-families"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    deviate not-supported&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
  deviation &lt;span class="s2"&gt;"/oc-netinst:network-instances/oc-netinst:network-instance/oc-netinst:tables/oc-netinst:table"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    deviate not-supported&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here is a more clear representation from &lt;a href="https://datatracker.ietf.org/meeting/94/materials/slides-94-rtgwg-9" rel="noopener noreferrer"&gt;the Anatomy of the Network Instance in OpenConfig&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwbw1ja1dowded7dipghp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwbw1ja1dowded7dipghp.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solving the lack of documentation examples
&lt;/h2&gt;

&lt;p&gt;I faced a big issue figuring out how each vendor implemenets the configuration parts of the gNMI tree, and through my exploration i found 2 ways to go about it :&lt;/p&gt;

&lt;h3&gt;
  
  
  1st Approach : from device CLI
&lt;/h3&gt;

&lt;p&gt;In my IOS-XR example, some parts like the Routing Policies were not implemented in gNMI the same way you would write it in CLI, so what i did is opened a IOS-XR VM configured a route policy as follows : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

route-policy ALLOW_ANY
  pass
end-policy


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then in each vendor there is a way to show the configuration in an XML way , and some have a way to show it in the OpenConfig hirarichy like Cisco, you can use an online tool like &lt;a href="https://codebeautify.org/xml-to-yaml" rel="noopener noreferrer"&gt;CodeBeautify&lt;/a&gt; to convert XML into YAML :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;

#show running-config | xml openconfig 
&lt;span class="nt"&gt;&amp;lt;routing-policy&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://openconfig.net/yang/routing-policy"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;policy-definitions&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;policy-definition&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;ALLOW_ANY&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;config&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;ALLOW_ANY&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;statements&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;statement&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;statement-1667049259886989&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;config&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt;statement-1667049259886989&lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;actions&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;config&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;accept-route/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
       &lt;span class="nt"&gt;&amp;lt;/actions&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/statement&amp;gt;&lt;/span&gt;
     &lt;span class="nt"&gt;&amp;lt;/statements&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/policy-definition&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/policy-definitions&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/routing-policy&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  2nd Approach : Reading Yang files
&lt;/h3&gt;

&lt;p&gt;If you dont have access to a live device, you can read the YANG trees of vendors or OpenConfig which you can clone from &lt;a href="https://github.com/YangModels/yang" rel="noopener noreferrer"&gt;Vendor's Yang Models in this link&lt;/a&gt;, you can fond your needed path in 2 ways :&lt;br&gt;
1) Tree hirarichy, including variable types and keys using &lt;em&gt;PYang&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="se"&gt;\#&lt;/span&gt; pyang openconfig-network-instance.yang &lt;span class="nt"&gt;-f&lt;/span&gt; tree
module: openconfig-network-instance
  +--rw network-instances
     +--rw network-instance&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;name]
        +--rw name                       -&amp;gt; ../config/name
        +--rw fdb
        |  +--rw config
        |  |  +--rw mac-learning?      boolean
        |  |  +--rw mac-aging-time?    uint16
        |  |  +--rw maximum-entries?   uint16
        |  +--ro state
        |  |  +--ro mac-learning?      boolean
        ...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;2) Using &lt;em&gt;gNMIC&lt;/em&gt; extract all the paths in the yang Module (Does not include the variable types) but very handy when you want a path to insert into a Get call :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="c"&gt;# gnmic path openconfig-network-instance.yang --file openconfig-network-instance.yang --config-only&lt;/span&gt;
/bgp/global/afi-safis/afi-safi[afi-safi-name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/afi-safi-name
/bgp/global/afi-safis/afi-safi[afi-safi-name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/afi-safi-name
/bgp/global/afi-safis/afi-safi[afi-safi-name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/enabled
...


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Deviations
&lt;/h2&gt;

&lt;p&gt;Each vendor implementation of gNMI has some deviations (Some parts not compitable with the OpenConfig Standard) which are documented in Yang files, you can find these Yang file in the same directory of the platform's OpenConfig and Vendor specific yangs, for example, listing the Routing Policies yang in the IOS-XR 6.5.1 version.&lt;/p&gt;

&lt;p&gt;1) OpenConfig Yangs : &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

cisco_yang_models/yang/vendor/cisco/xr/651# ll | &lt;span class="nb"&gt;grep &lt;/span&gt;policy | &lt;span class="nb"&gt;grep &lt;/span&gt;openconfig
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 root root  28487 Oct 14 18:28 openconfig-bgp-policy.yang
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 root root   3688 Oct 14 18:28 openconfig-isis-policy.yang
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 root root   4265 Oct 14 18:28 openconfig-policy-types.yang
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 root root  27024 Oct 14 18:28 openconfig-routing-policy.yang


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;2) Cisco specific implementation for configuration :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

cisco_yang_models/yang/vendor/cisco/xr/651# ll | &lt;span class="nb"&gt;grep &lt;/span&gt;policy | &lt;span class="nb"&gt;grep &lt;/span&gt;Cisco | &lt;span class="nb"&gt;grep &lt;/span&gt;cfg
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 root root  12321 Oct 14 18:28 Cisco-IOS-XR-policy-repository-cfg.yang


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;3) Cisco specific implementation for streaming telemetry : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

cisco_yang_models/yang/vendor/cisco/xr/651# ll | &lt;span class="nb"&gt;grep &lt;/span&gt;policy | &lt;span class="nb"&gt;grep &lt;/span&gt;Cisco | &lt;span class="nb"&gt;grep &lt;/span&gt;oper
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 root root   9567 Oct 14 18:28 Cisco-IOS-XR-policy-repository-oper-sub1.yang
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 root root   9532 Oct 14 18:28 Cisco-IOS-XR-policy-repository-oper.yang


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;4) Deviations - showing what is not supported usig the OpenConfig, in this case, you will need to use the vendor specific Yang : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

cisco_yang_models/yang/vendor/cisco/xr/651# ll | &lt;span class="nb"&gt;grep &lt;/span&gt;policy | &lt;span class="nb"&gt;grep &lt;/span&gt;deviations
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 root root   2927 Oct 14 18:28 cisco-xr-openconfig-bgp-policy-deviations.yang
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;  1 root root   1437 Oct 14 18:28 cisco-xr-openconfig-routing-policy-deviations.yang


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Reading the Deviation file is important so you are able to figure out which parts of the OpenConfig is not supported by this platform, for examples in "cisco-xr-openconfig-routing-policy-deviations.yang" you will see :&lt;br&gt;
(This is a small sample from the file for readability)&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;deviation "/rpol:routing-policy/rpol:defined-sets/rpol:neighbor-sets" {&lt;br&gt;
    &lt;strong&gt;deviate not-supported;&lt;/strong&gt;&lt;br&gt;
  }&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Example Lab&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx613ys2uo7o1ho5550ss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx613ys2uo7o1ho5550ss.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find this Lab's files on &lt;a href="https://github.com/amroashram/containerlab_labs/tree/main/03_frr_lab" rel="noopener noreferrer"&gt;my github&lt;/a&gt;, we are using &lt;a href="https://containerlab.dev" rel="noopener noreferrer"&gt;ContainerLab&lt;/a&gt; to deploy the setup and connect nodes to each other, after we have 3 diffirent node types to configure :&lt;br&gt;
1) Endpoint VMs : uses net-tools containers, configured using basic shell .&lt;br&gt;
2) CEs (FRRrouting) : using Containerlab configuration is deployed with initiation of the nodes, FRR Open routing software does not support gNMI since its normally deployed as a part of a bigger package.&lt;br&gt;
3) PEs (IOS-XRV 6.5.1) : these 2 PE/P will completly configured using gNMI.&lt;/p&gt;

&lt;p&gt;Lets focus on our PEs configuration, gNMIC is a great tool/eco-system enable you to use gNMI Yaml configuraiton templates and variable files to simplify the configuration process, in our case , we will deploy configuration as Yaml, but not use Variable files, this will come in a later tutorial.&lt;/p&gt;

&lt;p&gt;I Commented each part of the configuration: &lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c1"&gt;# 02_xrv_pe1_gnmi.yml&lt;/span&gt;&lt;br&gt;
&lt;span class="na"&gt;updates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Interfacece configuration&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Used the Cisco Yangs for this part as the OpenConfig yangs does not directly configure the interface IP, it has to be configured on &lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# a sub-interface instead&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# Interface GigabitEthernet0/0/0/1 Config&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-ifmgr-cfg:/interface-configurations/interface-configuration[active=act][interface-name=GigabitEthernet0/0/0/1]&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;to_PE2&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;Cisco-IOS-XR-ipv4-io-cfg:ipv4-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100.100.10.0&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;netmask&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;255.255.255.254&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;json_ietf&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Interface GigabitEthernet0/0/0/2 Config&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-ifmgr-cfg:/interface-configurations/interface-configuration[active=act][interface-name=GigabitEthernet0/0/0/2]&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;to_CE1&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;Cisco-IOS-XR-ipv4-io-cfg:ipv4-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100.100.20.1&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;netmask&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;255.255.255.254&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;json_ietf&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Interface Loopback0 Config&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-ifmgr-cfg:/interface-configurations/interface-configuration[active=act][interface-name=Loopback0]&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PE1_Loopback&lt;/span&gt;&lt;br&gt;
      &lt;span class="c1"&gt;# Ciscos weird implementation dictates to enable some of configuration elements, you need to set it with Null,&lt;/span&gt;&lt;br&gt;
      &lt;span class="c1"&gt;# in this case to enable a Loopback, you need to set the interface-virtual to Null, dont worry , the Yang file mentions it&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;interface-virtual&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;null&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;Cisco-IOS-XR-ipv4-io-cfg:ipv4-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100.64.0.1&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;netmask&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;255.255.255.255&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;json_ietf&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# IS-IS &lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Configuring ISIS using OpenConfig&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-network-instance:/network-instances/network-instance[name=default]/protocols&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="c1"&gt;# Some identifiers and types are supported by the OpenConfig or vendor like openconfig-policy-types:ISIS&lt;/span&gt;&lt;br&gt;
        &lt;span class="c1"&gt;# you will be able to find them in separate Yang Files called types and so on&lt;/span&gt;&lt;br&gt;
        &lt;span class="c1"&gt;# So in this case , the platform may no recognise ISIS, you have to mention the Types Yang it belongs to&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;identifier&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-policy-types:ISIS&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="c1"&gt;# This is the RIB name rather than a VRF name , under each Network-Instance (Global/VRF) you will find default RIB&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;isis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;level-capability&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LEVEL_2&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;net&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;49.0001.0064.0000.0001.00&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;afi-safi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;af&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;afi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-isis-types:IPV4&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;safi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-isis-types:UNICAST&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;interfaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;interface&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;interface-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Loopback0&lt;/span&gt;&lt;br&gt;
                &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;passive&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;br&gt;
                &lt;span class="na"&gt;afi-safi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;af&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;afi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-isis-types:IPV4&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;safi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-isis-types:UNICAST&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
                        &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;br&gt;
              &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;interface-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GigabitEthernet0/0/0/1&lt;/span&gt;&lt;br&gt;
                &lt;span class="na"&gt;afi-safi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;af&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;afi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-isis-types:IPV4&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;safi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-isis-types:UNICAST&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
                        &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# MPLS &amp;amp; LDP&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Note : since I am using IOS-XR 6.5.1 , only Cisco Yang models supported for MPLS &amp;amp; LDP&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;#        Openconfig Yangs are not supported &lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-mpls-ldp-cfg:/mpls-ldp&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;enable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;null&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;default-vrf&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;interfaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;interface&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;interface-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GigabitEthernet0/0/0/1&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;enable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;null&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# MP-BGP (We are using point to point peering instead of RR)&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-network-instance:/network-instances/network-instance[name=default]/protocols&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;identifier&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-policy-types:BGP&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;bgp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;65000&lt;/span&gt;&lt;br&gt;
                &lt;span class="na"&gt;router-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100.64.0.1&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;afi-safis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                &lt;span class="na"&gt;afi-safi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;afi-safi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-bgp-types:L3VPN_IPV4_UNICAST&lt;/span&gt;&lt;br&gt;
                    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;br&gt;
                  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;afi-safi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-bgp-types:IPV4_UNICAST&lt;/span&gt;&lt;br&gt;
                    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;neighbors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;neighbor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;neighbor-address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100.64.0.2&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                    &lt;span class="na"&gt;peer-as&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;65000&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;afi-safis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                    &lt;span class="na"&gt;afi-safi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;afi-safi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-bgp-types:L3VPN_IPV4_UNICAST&lt;/span&gt;&lt;br&gt;
                        &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                          &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;br&gt;
                      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;afi-safi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-bgp-types:IPV4_UNICAST&lt;/span&gt;&lt;br&gt;
                        &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                          &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;local-address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100.64.0.1&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# Configuring Next Hop Self will be deployed using Ciscos Yangs&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# As no similar in OpenConfig &lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Enablig Next-Hop-Self on both IPv4 and VPNv4 Families (No RR used)&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-ipv4-bgp-cfg://bgp/instance[instance-name=default]/instance-as[as=0]/four-byte-as[as=65000]/default-vrf/bgp-entity/neighbors/neighbor[neighbor-address=100.64.0.2]/neighbor-afs/neighbor-af&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;af-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ipv4-unicast&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;activate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
        &lt;span class="na"&gt;next-hop-self&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;br&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;af-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vpnv4-unicast&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;activate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
        &lt;span class="na"&gt;next-hop-self&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# VRF Configuration &lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Following 3 parts can be combined in one call, but i preferred to separate them to be easier to understand &lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# Configuring Allow all Route Policy , IOS-XR by default denies all if no Route&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Policy configured in eBGP session , cannot use the OpenConfig Yang for this policy , got a lot of issues&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-policy-repository-cfg:/routing-policy&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;route-policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;route-policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
          &lt;span class="na"&gt;route-policy-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AcceptAny&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;rpl-route-policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;route-policy AcceptAny\n  pass\nend-policy\n&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# Create VRF&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-network-instance:/network-instances&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;network-instance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CustomerVRF&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CustomerVRF&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;route-distinguisher&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1:1&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# initiate OpenConfigs BGP-IPv4 table under the CustomerVRF network instance&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-network-instance:/network-instances/network-instance[name=CustomerVRF]&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;enabled-address-families&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-types:IPV4&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;tables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;BGP&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;address-family&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;IPV4&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
              &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;BGP&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;address-family&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-types:IPV4&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# Doing redistribute Connected into VRF , using Ciscos Yangs, not available in OpenConfig: &lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-ipv4-bgp-cfg:/bgp/instance[instance-name=default]/instance-as[as=0]/four-byte-as[as=65000]/vrfs/vrf[vrf-name=CustomerVRF]/vrf-global/vrf-global-afs/vrf-global-af[af-name=ipv4-unicast]/connected-routes&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Doing redistribute Static into VRF , using Ciscos Yangs, not available in OpenConfig: &lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-ipv4-bgp-cfg:/bgp/instance[instance-name=default]/instance-as[as=0]/four-byte-as[as=65000]/vrfs/vrf[vrf-name=CustomerVRF]/vrf-global/vrf-global-afs/vrf-global-af[af-name=ipv4-unicast]/static-routes&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# Assinging interfaces to VRF after VRF creation &lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-network-instance:/network-instances/network-instance[name=CustomerVRF]&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;interfaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;interface&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GigabitEthernet0/0/0/2&lt;/span&gt;&lt;br&gt;
          &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GigabitEthernet0/0/0/2&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;interface&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GigabitEthernet0/0/0/2&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# Configuring BGP under VRF : &lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-network-instance:/network-instances/network-instance[name=CustomerVRF]/&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;protocols&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;identifier&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;BGP&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt; &lt;span class="c1"&gt;# this points to the primary RIB under the VRF (Table belongs to CustomerVRF Network-Instance)&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;bgp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;65000&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;router-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100.100.20.1&lt;/span&gt;&lt;br&gt;
                &lt;span class="na"&gt;afi-safis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                  &lt;span class="na"&gt;afi-safi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;afi-safi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-bgp-types:IPV4_UNICAST&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                        &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;neighbors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                &lt;span class="na"&gt;neighbor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;neighbor-address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100.100.20.0&lt;/span&gt;&lt;br&gt;
                    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;peer-as&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;65001&lt;/span&gt;&lt;br&gt;
                    &lt;span class="na"&gt;afi-safis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;afi-safi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;afi-safi-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-bgp-types:IPV4_UNICAST&lt;/span&gt;&lt;br&gt;
                          &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                            &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;br&gt;
                    &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                      &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
                        &lt;span class="na"&gt;local-address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100.100.20.1&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# Applying: (Unable to same using OpenConfig)&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# 1) Import &amp;amp; Export Policy with eBGP Peer (CE)&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# 2) Applying AS-Override (cuz both CEs are same AS) &lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-ipv4-bgp-cfg:/bgp/instance[instance-name=default]/instance-as[as=0]/four-byte-as[as=65000]/vrfs/vrf[vrf-name=CustomerVRF]/vrf-neighbors/vrf-neighbor[neighbor-address=100.100.20.0]/vrf-neighbor-afs/vrf-neighbor-af[af-name=ipv4-unicast]/&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;route-policy-in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AcceptAny&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;route-policy-out&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AcceptAny&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;as-override&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# To configure Route Target import and export, we will use the Cisco Specific Yang Cisco-IOS-XR-infra-rsi-cfg.yang: &lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Import Route target&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-infra-rsi-cfg:/vrfs/vrf[vrf-name=CustomerVRF]/afs/af[af-name=ipv4][saf-name=unicast][topology-name=default]/Cisco-IOS-XR-ipv4-bgp-cfg:bgp/import-route-targets/route-targets/route-target[type=as]&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
      &lt;span class="na"&gt;as-or-four-byte-as&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;as-xx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;as-index&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;stitching-rt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# Export route target&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-infra-rsi-cfg:/vrfs/vrf[vrf-name=CustomerVRF]/afs/af[af-name=ipv4][saf-name=unicast][topology-name=default]/Cisco-IOS-XR-ipv4-bgp-cfg:bgp/export-route-targets/route-targets/route-target[type=as]&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
      &lt;span class="na"&gt;as-or-four-byte-as&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;as-xx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;as-index&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;stitching-rt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# LLDP&lt;/span&gt;&lt;br&gt;
  &lt;span class="c1"&gt;# ================================================================================&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;openconfig-lldp:/lldp&lt;/span&gt;&lt;br&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;&lt;br&gt;
      &lt;span class="c1"&gt;# Uncomment if you want to enable LLDP globally &lt;/span&gt;&lt;br&gt;
      &lt;span class="c1"&gt;# config:&lt;/span&gt;&lt;br&gt;
      &lt;span class="c1"&gt;#   enabled: true&lt;/span&gt;&lt;br&gt;
      &lt;span class="na"&gt;interfaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
        &lt;span class="na"&gt;interface&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GigabitEthernet0/0/0/1&lt;/span&gt;&lt;br&gt;
            &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GigabitEthernet0/0/0/1&lt;/span&gt;&lt;br&gt;
              &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="na"&gt;deletes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;br&gt;
  &lt;span class="c1"&gt;# Enable interfaces - works by deleteing Shutdown &lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-ifmgr-cfg:/interface-configurations/interface-configuration[active=act][interface-name=GigabitEthernet0/0/0/1]/shutdown&lt;/span&gt;&lt;br&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Cisco-IOS-XR-ifmgr-cfg:/interface-configurations/interface-configuration[active=act][interface-name=GigabitEthernet0/0/0/2]/shutdown&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Remote Wire Shark&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;You can capture traffic using SSH Capture in a Containerlab deployment, open WireShark, and the SSH capture :&lt;br&gt;
Remote Server Address : IP of Node running Containerlab&lt;br&gt;
Remote Capture command : &lt;code&gt;$ sudo ip netns exec clab-02_xrv_gnmi-CE1 tcpdump -U -nni eth3 -w -&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Template : &lt;code&gt;$ sudo ip netns exec NODE_NAME tcpdump -U -nni INTERFACE_TO_CAPTURE -w -&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful commands
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;On Cisco IOS-XR , if you are aconfused of how to implement a gNMI config, you can do it in CLI like you normally do, and then show the gNMI/OpenConfig syntax using below command, enables you to see the config tree : 
&lt;code&gt;show running-config | xml openconfig&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conatiners used
&lt;/h2&gt;

&lt;p&gt;1- We will use the Praqma image which includes network testing tools pre-packaged :&lt;br&gt;
&lt;code&gt;docker pull praqma/network-multitool&lt;/code&gt;&lt;br&gt;
2- Open FRRouting Router for CEs : &lt;br&gt;
&lt;code&gt;docker pull frrouting/frr&lt;/code&gt;&lt;br&gt;
3- IOS-XRV Containers, images should be provided by your support.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/CiscoDevNet/openconfig-getting-started" rel="noopener noreferrer"&gt;CiscoDevnet getting started with gNMI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://karneliuk.com/2018/08/openconfig-part-3-advanced-openconfig-w-ansible-for-arista-eos-cisco-ios-xr-and-nokia-sr-os-route-policy-bgp-and-interfaces-again/" rel="noopener noreferrer"&gt;BLOG - OpenConfig. Part 3. Advanced OpenConfig (w/ Ansible) for Arista EOS, Cisco IOS XR and Nokia SR OS: route policy BGP and interfaces again&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=qmIWzr6lG_M" rel="noopener noreferrer"&gt;Youtube - Red Hat Ansible OpenConfig Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pc.nanog.org/static/published/meetings/NANOG71/1456/20171003_Alvarez_Getting_Started_With_v1.pdf" rel="noopener noreferrer"&gt;PDF - NANOG Getting started with OpenConfig&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/meeting/94/materials/slides-94-rtgwg-9" rel="noopener noreferrer"&gt;PDF - openconfig-network-instance IETF Presentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ciscolive.com/c/dam/r/ciscolive/us/docs/2019/pdf/5eU6DfQV/LTRSPG-2601-LG.pdf" rel="noopener noreferrer"&gt;Excellent Source - Cisco Live - Cisco IOS XR Programmability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.brianlinkletter.com/2021/05/use-containerlab-to-emulate-open-source-routers/" rel="noopener noreferrer"&gt;FRR - Use Containerlab to emulate open-source routers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.networktocode.com/post/monitor_your_network_with_gnmi_snmp_and_grafana/" rel="noopener noreferrer"&gt;Telemetry Monitoring using Grafana , gNMI and SNMP&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gnmi</category>
      <category>network</category>
      <category>containerapps</category>
    </item>
    <item>
      <title>Network Automation : Simulating network topologies with Containers and gNMI</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Mon, 24 Oct 2022 19:49:30 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/network-automation-simulating-network-topologies-with-containers-and-gnmi-1obm</link>
      <guid>https://dev.to/amrelhusseiny/network-automation-simulating-network-topologies-with-containers-and-gnmi-1obm</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Like many network engineers, I used to use EVE-NG (or GNS3) to test lab topologies and configurations.Instead of having to control the configuration using the EVE-NG platform, 2 tools available, ContainrLab &amp;amp; vrnetlab enables you to run your most used Network devices in a Docker container platform of your choice, this opens up all the automation tools available for Docker and K8S.&lt;/p&gt;

&lt;p&gt;But beware, unlike traditional containers which replaces the resource intensive Virtual Machine with only the needed parts inside a container form, here are only converting those VM to run as VM emulating container, so those containers will use the same amount of resource as the EVE-NG VM if not a little bit more, but you get to optimize the deplyment of these labs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simply why would you use this ?&lt;/strong&gt;&lt;br&gt;
Answer, you Network lab acts like a K8S deployment, so for example, i have multiple topologies templates ready to run with one command if i need to test something, also if i miss it up, with one command I can destroy the lab and deploy another clean instance of the lab.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;What are the supported platforms ? *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most of the network used platforms are available here, beside all the containerized platforms, also it opens you up to new world of containerizd network devices that cannot be emulatedf with a simple container in EVE-NG (Example Cisco's XRV container if you have access to one). &lt;/p&gt;

&lt;p&gt;In this article , we are going to replace the usage of our belove EVE-NG and GNS3, with Containerlab, but to be clear you will find 2 solutions, we are going to explore ContainrLab only :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solution 1 - VRNetlab : for containerizing the existing "qcow" images we have, and for connectivity between containers, this will be providing the way to package the QCOW into a container form anyways, but the downside with VrnetLab, that it does not provide and easy way to manage the topology, for that ContainerLab implementation of VrnetLab is better in my opinion.&lt;/li&gt;
&lt;li&gt;Solution 2 - Containerlab : for Topology management and configuration automation , its based on vrnetlab also, but a modified version, not identical to the standalone Vrnetlab solution . (subject of this article)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Important note : there is 2 versions of &lt;em&gt;vrnetlab&lt;/em&gt;, &lt;a href="https://github.com/vrnetlab/vrnetlab" rel="noopener noreferrer"&gt;vrnetlab/vrnetlab&lt;/a&gt; is not compatiable with ContainerLab, if you want to use ContainerLab, you would have to install &lt;a href="https://github.com/hellt/vrnetlab" rel="noopener noreferrer"&gt;hellt/vrnetlab&lt;/a&gt;, so the docker image created by one of them cannot be used with the other.&lt;/p&gt;

&lt;p&gt;What we plan here is to introduce 2 tools :&lt;br&gt;
1) ContainerLab for provisioning the topology.&lt;br&gt;
2) gNMI (# gRPC Network Management Interface) - OpenConfig project : gPRC to apply configuration templates, replacing Netconf,RestAPI and SSH , supported by multiple carriers and most of the big device manufacturers. &lt;/p&gt;

&lt;h3&gt;
  
  
  ContainerLab supported platforms (Kinds)
&lt;/h3&gt;

&lt;p&gt;You can find the updated list &lt;a href="https://containerlab.dev/manual/kinds/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nokia SR Linux&lt;/li&gt;
&lt;li&gt;Nokia SR OS&lt;/li&gt;
&lt;li&gt;Arista cEOS&lt;/li&gt;
&lt;li&gt;Arista vEOS&lt;/li&gt;
&lt;li&gt;Juniper cRPD&lt;/li&gt;
&lt;li&gt;Juniper vMX&lt;/li&gt;
&lt;li&gt;Juniper vQFX&lt;/li&gt;
&lt;li&gt;Cisco XRv9k&lt;/li&gt;
&lt;li&gt;Cisco XRv&lt;/li&gt;
&lt;li&gt;Cisco CSR1000v&lt;/li&gt;
&lt;li&gt;Cisco Nexus 9000v&lt;/li&gt;
&lt;li&gt;Cumulus VX&lt;/li&gt;
&lt;li&gt;SONiC&lt;/li&gt;
&lt;li&gt;Dell FTOS10v&lt;/li&gt;
&lt;li&gt;MikroTik RouterOS&lt;/li&gt;
&lt;li&gt;Palo Alto PAN&lt;/li&gt;
&lt;li&gt;IPInfusion OcNOS&lt;/li&gt;
&lt;li&gt;Keysight IXIA-C One&lt;/li&gt;
&lt;li&gt;Check Point Cloudguard&lt;/li&gt;
&lt;li&gt;Linux bridge&lt;/li&gt;
&lt;li&gt;Linux container&lt;/li&gt;
&lt;li&gt;Openvswitch bridge&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  before we start, You can follow the containerlab installation guide &lt;a href="https://containerlab.dev/install/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Packaging our QCOW into containers
&lt;/h2&gt;

&lt;p&gt;1st you need to provide the image file just like the EVE-NG one, some images has open source or trial versions if your vendor does not provide a testing image.&lt;br&gt;
Here we will try with Cisco's IOS-XR 9K 6.5.1, I suggest you clone the &lt;a href="https://github.com/hellt/vrnetlab" rel="noopener noreferrer"&gt;Hellt/VrentLab&lt;/a&gt; Github page :&lt;br&gt;
&lt;code&gt;$ git clone https://github.com/hellt/vrnetlab&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In here you will find the each supported platform has its directory in which we will place our qcow image,most importantly, each directory conatins a README file instructing you what to nam your image file, and which 'make' command to use so it creates the container image and register ir in your Docker.&lt;/p&gt;

&lt;p&gt;For our example for the XR-9K, all you need is to put the qcow image in folder and then run &lt;code&gt;make docker-image&lt;/code&gt;.&lt;br&gt;
Now if you check your Docker images list, you will find our router: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;XR
vrnetlab/vr-xrv9k                 6.5.1       be122c04f93a   3 weeks ago     7.07GB


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I tag it as latest, so its easier to deploy, however you donot need to that:&lt;br&gt;
&lt;code&gt;$ docker tag vrnetlab/vr-xrv9k:7.2.1 vrnetlab/vr-xrv9k:latest&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ContainerLab topology template
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7ng2fxq4wl4zex4dhzf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7ng2fxq4wl4zex4dhzf.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find the topology files on my &lt;a href="https://github.com/amroashram/containerlab_labs/tree/main/01_vmx_xrv_lab" rel="noopener noreferrer"&gt;Github here&lt;/a&gt; :) &lt;/p&gt;

&lt;p&gt;Our topology include Cisco's IOS-XR, Junos's VMX and Nokia's SR-Linux to demonstrate the scale:&lt;br&gt;
Primer: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The topology file for Containerlab is a Yaml file devided int 2 parts, the nodes with their naming, docker image "Kind" and initial configuration file if you have that.&lt;/li&gt;
&lt;li&gt;The kind is dictated by containerlab, you can find the kind you can put in the Yaml &lt;a href="https://containerlab.dev/manual/kinds/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, make sure you choose the right kind for each platform.&lt;/li&gt;
&lt;li&gt;You donot have to include initial/starup configuration file, containerlab by default handles the SSH basic configuration besides other cool configuration liek NetConf and gNMI access.&lt;/li&gt;
&lt;li&gt;For my lab, I included configuration files for each node deploying an IS-IS/MPLS backbone as lab template for me to use in the future.&lt;/li&gt;
&lt;li&gt;The interfaces names in the topology file is replaced by the Linux 'ethX' naming, you can find the interfaces naming scheme on the &lt;a href="https://containerlab.dev/manual/kinds/vr-xrv9k/" rel="noopener noreferrer"&gt;kind/platform&lt;/a&gt; in the Containrlab site .&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our above topology file looks as follows, easy to read: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# 01_vmx_xrv_lab_topology.clab.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;01_vmx_xrv_lab_topology&lt;/span&gt;

&lt;span class="na"&gt;topology&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;PE1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-vmx&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-vmx:21.2R1.10&lt;/span&gt;
        &lt;span class="na"&gt;startup-config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodes_configurations/PE1.txt&lt;/span&gt;
    &lt;span class="na"&gt;P1 &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-vmx&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-vmx:21.2R1.10&lt;/span&gt;
        &lt;span class="na"&gt;startup-config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodes_configurations/P1.txt&lt;/span&gt;
    &lt;span class="na"&gt;P2 &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-vmx&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-vmx:21.2R1.10&lt;/span&gt;
        &lt;span class="na"&gt;startup-config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodes_configurations/P2.txt&lt;/span&gt;
    &lt;span class="na"&gt;P3 &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-vmx&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-vmx:21.2R1.10&lt;/span&gt;
        &lt;span class="na"&gt;startup-config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodes_configurations/P3.txt&lt;/span&gt;
    &lt;span class="na"&gt;P4 &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-xrv9k&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-xrv9k:7.2.1&lt;/span&gt;
        &lt;span class="na"&gt;startup-config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodes_configurations/P4.txt&lt;/span&gt;
    &lt;span class="na"&gt;P5 &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-vmx&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-vmx:21.2R1.10&lt;/span&gt;
        &lt;span class="na"&gt;startup-config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodes_configurations/P5.txt&lt;/span&gt;
    &lt;span class="na"&gt;P6 &lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-xrv9k&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-xrv9k:7.2.1&lt;/span&gt;
        &lt;span class="na"&gt;startup-config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodes_configurations/P6.txt&lt;/span&gt;
    &lt;span class="na"&gt;PE2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vr-xrv9k&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;vrnetlab/vr-xrv9k:7.2.1&lt;/span&gt;
        &lt;span class="na"&gt;startup-config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nodes_configurations/PE2.txt&lt;/span&gt;
    &lt;span class="na"&gt;PE3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;srl&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/nokia/srlinux:latest&lt;/span&gt;

  &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE1:eth2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P1:eth2"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE1:eth3"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P5:eth3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P1:eth4"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P2:eth4"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P1:eth5"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P3:eth5"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P3:eth2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P4:eth2"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P3:eth4"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P5:eth4"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P5:eth2"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P6:eth2"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P2:eth6"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P4:eth6"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P2:eth5"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE2:eth5"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P6:eth3"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P4:eth3"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P6:eth4"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE2:eth4"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE3:e1-5"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P1:eth6"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PE3:e1-6"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;P2:eth7"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To deploy your topology, run : &lt;br&gt;
&lt;code&gt;$ containerlab deploy --topo 01_vmx_xrv_lab_topology.clab.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Containerlab provides an output of the topology container management assigned IPs (IPv4/IPv6) and registers it in your hosts file so you can use the hostname instead :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/hosts
&lt;span class="c"&gt;###### CLAB-01_vmx_xrv_lab_topology-START ######&lt;/span&gt;
172.20.20.8     clab-01_vmx_xrv_lab_topology-PE2
172.20.20.7     clab-01_vmx_xrv_lab_topology-P4
172.20.20.6     clab-01_vmx_xrv_lab_topology-P1
172.20.20.5     clab-01_vmx_xrv_lab_topology-P5
172.20.20.9     clab-01_vmx_xrv_lab_topology-P6
172.20.20.4     clab-01_vmx_xrv_lab_topology-PE1
172.20.20.10    clab-01_vmx_xrv_lab_topology-P2
172.20.20.2     clab-01_vmx_xrv_lab_topology-PE3
172.20.20.3     clab-01_vmx_xrv_lab_topology-P3
2001:172:20:20::8       clab-01_vmx_xrv_lab_topology-PE2
2001:172:20:20::7       clab-01_vmx_xrv_lab_topology-P4
2001:172:20:20::6       clab-01_vmx_xrv_lab_topology-P1
2001:172:20:20::5       clab-01_vmx_xrv_lab_topology-P5
2001:172:20:20::9       clab-01_vmx_xrv_lab_topology-P6
2001:172:20:20::4       clab-01_vmx_xrv_lab_topology-PE1
2001:172:20:20::a       clab-01_vmx_xrv_lab_topology-P2
2001:172:20:20::2       clab-01_vmx_xrv_lab_topology-PE3
2001:172:20:20::3       clab-01_vmx_xrv_lab_topology-P3
&lt;span class="c"&gt;###### CLAB-01_vmx_xrv_lab_topology-END ######&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, since these are full fledged operating systems, it may take a few minutes to fully boot up, you can follow the progress of the booting process using docker logs like follows :&lt;br&gt;
&lt;code&gt;$ docker logs -f clab-01_vmx_xrv_lab_topology-PE3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After nodes are booted youcan ssh normally like any VM, but easier here since you can use the Hostname (The default username and password can be found on the &lt;a href="https://containerlab.dev/manual/kinds/vr-xrv9k/" rel="noopener noreferrer"&gt;Containerlab Wiki&lt;/a&gt;):&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

RP/0/RP0/CPU0:PE2&lt;span class="se"&gt;\#&lt;/span&gt;show interfaces description 
Interface          Status      Protocol    Description
Lo0                up          up          
Nu0                up          up          
Mg0/RP0/CPU0/0     up          up          
Gi0/0/0/0          admin-down  admin-down  
Gi0/0/0/1          admin-down  admin-down  
Gi0/0/0/2          admin-down  admin-down  
Gi0/0/0/3          up          up          description to_P6_Link_11
Gi0/0/0/4          up          up          description to_P2_Link_10


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can see from the output, that some interfaces are already configured, as it booted up and deployed my configuration file.&lt;/p&gt;

&lt;p&gt;Some useful operations commands&lt;br&gt;&lt;br&gt;
To show current topology running nodes : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;containerlab inspect &lt;span class="nt"&gt;--topo&lt;/span&gt; 01_vmx_xrv_lab_topology.clab.yml
+---+----------------------------------+--------------+------------------------------+----------+---------+-----------------+----------------------+
| &lt;span class="c"&gt;# |               Name               | Container ID |            Image             |   Kind   |  State  |  IPv4 Address   |     IPv6 Address     |&lt;/span&gt;
+---+----------------------------------+--------------+------------------------------+----------+---------+-----------------+----------------------+
| 1 | clab-01_vmx_xrv_lab_topology-P1  | fcbc335b26b2 | vrnetlab/vr-vmx:21.2R1.10    | vr-vmx   | running | 172.20.20.6/24  | 2001:172:20:20::6/64 |
| 2 | clab-01_vmx_xrv_lab_topology-P2  | 2c9ca5de1124 | vrnetlab/vr-vmx:21.2R1.10    | vr-vmx   | running | 172.20.20.10/24 | 2001:172:20:20::a/64 |
| 3 | clab-01_vmx_xrv_lab_topology-P3  | 2ad9bc2c91e4 | vrnetlab/vr-vmx:21.2R1.10    | vr-vmx   | running | 172.20.20.3/24  | 2001:172:20:20::3/64 |
| 4 | clab-01_vmx_xrv_lab_topology-P4  | de4c72b64214 | vrnetlab/vr-xrv9k:7.2.1      | vr-xrv9k | running | 172.20.20.7/24  | 2001:172:20:20::7/64 |
| 5 | clab-01_vmx_xrv_lab_topology-P5  | aaa1ae3a4887 | vrnetlab/vr-vmx:21.2R1.10    | vr-vmx   | running | 172.20.20.5/24  | 2001:172:20:20::5/64 |
| 6 | clab-01_vmx_xrv_lab_topology-P6  | e3ad22362111 | vrnetlab/vr-xrv9k:7.2.1      | vr-xrv9k | running | 172.20.20.9/24  | 2001:172:20:20::9/64 |
| 7 | clab-01_vmx_xrv_lab_topology-PE1 | 6d0de04511d9 | vrnetlab/vr-vmx:21.2R1.10    | vr-vmx   | running | 172.20.20.4/24  | 2001:172:20:20::4/64 |
| 8 | clab-01_vmx_xrv_lab_topology-PE2 | 0c78217813d3 | vrnetlab/vr-xrv9k:7.2.1      | vr-xrv9k | running | 172.20.20.8/24  | 2001:172:20:20::8/64 |
| 9 | clab-01_vmx_xrv_lab_topology-PE3 | abdcdb9e2b08 | ghcr.io/nokia/srlinux:latest | srl      | running | 172.20.20.2/24  | 2001:172:20:20::2/64 |
+---+----------------------------------+--------------+------------------------------+----------+---------+-----------------+----------------------+


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or you can show all the current running Containerlab nodes on host, even if they are from diffirent topologies:&lt;br&gt;
&lt;code&gt;$ containerlab inspect --all&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Finally, you can destroy the topology or  all the running instances in one command: &lt;br&gt;
&lt;code&gt;$ containerlab destroy --topo 01_vmx_xrv_lab_topology.clab.yml&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ containerlab destroy --all&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  More labs
&lt;/h2&gt;

&lt;p&gt;You can find more example labs already createdt by the Containerlab creator, which is very useful &lt;a href="https://containerlab.dev/lab-examples/lab-examples/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using gNMI &amp;amp; OpenConfig for Automation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Starting with SSH movint to SNMP then moving to Netconf then RESTful APIs, there has been multiple iterations for config management and telemtry in the network space, due to the vast variety of networking vendors, form factors and specilaization, adoption of new technologies for management and telemetry streaming has been very hard, thankfully a new group of industry leaders has joined the &lt;a href="https://www.openconfig.net" rel="noopener noreferrer"&gt;OpenConfig&lt;/a&gt;  initiative which is trying to create a standard for interoperabilty.&lt;/p&gt;

&lt;p&gt;the gRPC protocol (initially developed by Google)  is the next evolution of Rest and Netconf, it runs on top of HTTP2, making it TCP reliable and allows the ability for Streaming Telemetry, which makes it instrumental in replacing SNMP and then adopted industry wide, It is targeted towards the expansion of Microservices, it enables you to use alomost any of the well known languages to build each part of your application whether the same language or not, and then using gRPC just like REST, you are able to communicate between these microservices in mutually understandable way.&lt;/p&gt;

&lt;p&gt;One of the important diffireneces betwee gRPC and REST is the introducation of data serilaization using  ProtoBuff (Protocol Buffer) instead of JSON which is mostly a little bigger in size and more porccessor intensive, unlike JSON though ProtoBuff is not humanlly readable since its represented in Binary form but very efficient banddwidth and processing wise.&lt;/p&gt;

&lt;p&gt;gNMI (gRPC Network Management Interface) uses gRPC protocol but specilaizes in the Network devices domain , you can refer to &lt;a href="https://www.cisco.com/c/en/us/products/collateral/switches/nexus-9000-series-switches/white-paper-c11-744191.html" rel="noopener noreferrer"&gt;Cisco's page&lt;/a&gt; for more detail about the gNMI protocol, as for OpenConfig, vendors adhere to some model driven standards to implement a similar Yang models so you can get/set config , subscribe to telemetry in a standard Yang representation without having to adapt your code to each new vendor you have.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations of gNMI and OpenConfig
&lt;/h3&gt;

&lt;p&gt;While gNMI is fully implemented for most of the participating vendors, with some limitations for example with Juniper's Junos there is still some issue with Get Config request, generally you should be able to use gNMI as your tool.&lt;/p&gt;

&lt;p&gt;Most importantly jsut like Netconf and SNMP MIBs, the OpenConfig standards does not cover all topics and features, so you may have to use the vendor's specific Yang models instead of the OpenConfig ones while using those specfic features.&lt;/p&gt;

&lt;p&gt;Be vigilant to follow up with the vendor's implementation as they share it publicly, here are some Github pages which you can source your , one of the most adhering vendors is Nokia, their implementation is impcable, you can start to learn from there .&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cisco's IOS-XR/NexusOS/IOS-XE/NCS supported Yang models &lt;a href="https://github.com/YangModels/yang/tree/main/vendor/cisco" rel="noopener noreferrer"&gt;https://github.com/YangModels/yang/tree/main/vendor/cisco&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Juniper's Junos MX/SRX/PTX Yang Models : &lt;a href="https://github.com/Juniper/telemetry" rel="noopener noreferrer"&gt;https://github.com/Juniper/telemetry&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Nokia's SR-Linux Yang Models : &lt;a href="https://github.com/nokia/srlinux-yang-models" rel="noopener noreferrer"&gt;https://github.com/nokia/srlinux-yang-models&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you have download some Yang models, that reflect configuration hirarchy, now how can you read those Yang models, lets have a look at some tools to help out with that.&lt;/p&gt;

&lt;h4&gt;
  
  
  pyang
&lt;/h4&gt;

&lt;p&gt;PYANG is a program, that can be used to validate YANG models against RFCs and more importantly generate a tree representation of a Yanf module.&lt;/p&gt;

&lt;p&gt;Lets say, you want to see how are the configuration of interfaces is impelemented in Cisco's IOS-XR OpenConfig compliant Yang model.&lt;/p&gt;

&lt;p&gt;1st install pyang: &lt;br&gt;
&lt;code&gt;$ pip install pyang&lt;/code&gt;&lt;br&gt;
Now, you can either get the OpenConfig models from the OpenConfig repo which should work properly with complying vendors, or the way i prefer is to get it from the vendor's page, as you will find additional Yang models specific to each vendor, here we will get it from Cisco's Git.&lt;br&gt;
&lt;code&gt;&lt;br&gt;
$ git clone https://github.com/YangModels/yang.git cisco_yang_models&lt;br&gt;
$ cd cisco_yang_models/yang/vendor/cisco/xr/651/&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Lets have a look onto a Yang tree using pyang , the rw referes to read/write , meaning these are configurable , the '[name]' means this is the key for this list, we will use keys later to configure specfic interface or to get its stats : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;pyang openconfig-interfaces.yang &lt;span class="nt"&gt;-f&lt;/span&gt; tree
module: openconfig-interfaces
  +--rw interfaces
     +--rw interface&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;name]
        +--rw name             -&amp;gt; ../config/name
        +--rw config
        |  +--rw &lt;span class="nb"&gt;type           &lt;/span&gt;identityref
        |  +--rw mtu?           uint16
        |  +--rw name?          string
        |  +--rw description?   string
        |  +--rw enabled?       boolean


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Like I said, some Yang models are still vendor specific like the Segment Routing module from Cisco for example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;pyang Cisco-IOS-XR-segment-routing-ms-cfg.yang &lt;span class="nt"&gt;-f&lt;/span&gt; tree 
module: Cisco-IOS-XR-segment-routing-ms-cfg
  +--rw sr
     +--rw local-block!
     |  +--rw lower-bound    uint32
     |  +--rw upper-bound    uint32
     +--rw mappings
     |  +--rw mapping&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;af ip mask]
     |     +--rw af               Srms-address-family
     |     +--rw ip               inet:ip-address-no-zone
     |     +--rw mask             uint32
     |     +--rw sid-start?       uint32
     |     +--rw sid-range?       uint32
     |     +--rw flag-attached?   Srms-mi-flag
     +--rw adjacency-sid
     |  +--rw interfaces
     |     +--rw interface&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;interface]
     |        +--rw address-families
     |        |  +--rw address-family&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;address-family]
     |        |     +--rw next-hops
     |        |     |  +--rw next-hop&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;ip-addr]
     |        |     |     +--rw l2-adjacency-sid
     |        |     |     |  +--rw sid-type?       Sid-type-list
     |        |     |     |  +--rw absolute-sid?   uint32
     |        |     |     |  +--rw index-sid?      uint32
     |        |     |     |  +--rw srlb            Srlb-string
     |        |     |     +--rw ip-addr             inet:ip-address-no-zone
     |        |     +--rw address-family    Srms-address-family
     |        +--rw interface           xr:Interface-name
     +--rw global-block!
     |  +--rw lower-bound    uint32
     |  +--rw upper-bound    uint32
     +--rw &lt;span class="nb"&gt;enable&lt;/span&gt;?          empty


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  gNMIc
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://gnmic.kmrd.dev" rel="noopener noreferrer"&gt;gNMIc&lt;/a&gt; is a tool developed initiatlly by Nokia and then donated to OpenConfig, providing a platform to implement gNMI management, including a very useful CLI tool.&lt;/p&gt;

&lt;p&gt;Lets see what we can do with, 1st like pyang , we can list the available configuration tree, but this time in a more useful Path Value format, this shows you the Configuration Paths you can use in the gNMI call &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

gnmic path openconfig-interfaces &lt;span class="nt"&gt;--file&lt;/span&gt; openconfig-interfaces.yang &lt;span class="nt"&gt;--config-only&lt;/span&gt;
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/description
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/enabled
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/mtu
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/name
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/type
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/description
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/enabled
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/hold-time/config/down
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/hold-time/config/up
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/link-up-down-trap-enable
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/name
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/name
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/subinterfaces/subinterface[index&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/description
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/subinterfaces/subinterface[index&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/enabled
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/subinterfaces/subinterface[index&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/index
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/subinterfaces/subinterface[index&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/config/name
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/subinterfaces/subinterface[index&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/index
/interfaces/interface[name&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;/type


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now lets put it to use with our Lab topology, we can get the configuration of one of  PE2 interfaces like follows :&lt;br&gt;
Get Example : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;gnmic &lt;span class="nt"&gt;-a&lt;/span&gt; clab-01_vmx_xrv_lab_topology-PE2  &lt;span class="nt"&gt;--insecure&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; admin &lt;span class="nt"&gt;-p&lt;/span&gt; admin &lt;span class="nt"&gt;-e&lt;/span&gt; json_ietf  get &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="s1"&gt;'openconfig-interfaces:/interfaces/interface[name="Loopback0"]'&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;
  &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"clab-01_vmx_xrv_lab_topology-PE2"&lt;/span&gt;,
    &lt;span class="s2"&gt;"timestamp"&lt;/span&gt;: 1666636579876879221,
    &lt;span class="s2"&gt;"time"&lt;/span&gt;: &lt;span class="s2"&gt;"2022-10-24T18:36:19.876879221Z"&lt;/span&gt;,
    &lt;span class="s2"&gt;"updates"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
      &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"Path"&lt;/span&gt;: &lt;span class="s2"&gt;"openconfig-interfaces:interfaces/interface[name=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Loopback0&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]"&lt;/span&gt;,
        &lt;span class="s2"&gt;"values"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"interfaces/interface"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
            &lt;span class="o"&gt;{&lt;/span&gt;
              &lt;span class="s2"&gt;"config"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"enabled"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
                &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Loopback0"&lt;/span&gt;,
                &lt;span class="s2"&gt;"type"&lt;/span&gt;: &lt;span class="s2"&gt;"iana-if-type:softwareLoopback"&lt;/span&gt;
              &lt;span class="o"&gt;}&lt;/span&gt;,
              &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Loopback0"&lt;/span&gt;,
              &lt;span class="s2"&gt;"state"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"admin-status"&lt;/span&gt;: &lt;span class="s2"&gt;"UP"&lt;/span&gt;,
                &lt;span class="s2"&gt;"enabled"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
                &lt;span class="s2"&gt;"ifindex"&lt;/span&gt;: 11,
                &lt;span class="s2"&gt;"last-change"&lt;/span&gt;: 33469,
                &lt;span class="s2"&gt;"mtu"&lt;/span&gt;: 1500,
                &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Loopback0"&lt;/span&gt;,
                &lt;span class="s2"&gt;"oper-status"&lt;/span&gt;: &lt;span class="s2"&gt;"UP"&lt;/span&gt;,
                &lt;span class="s2"&gt;"type"&lt;/span&gt;: &lt;span class="s2"&gt;"iana-if-type:softwareLoopback"&lt;/span&gt;
              &lt;span class="o"&gt;}&lt;/span&gt;,
              &lt;span class="s2"&gt;"subinterfaces"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"subinterface"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                  &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="s2"&gt;"index"&lt;/span&gt;: 0,
                    &lt;span class="s2"&gt;"openconfig-if-ip:ipv4"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                      &lt;span class="s2"&gt;"addresses"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                        &lt;span class="s2"&gt;"address"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
                          &lt;span class="o"&gt;{&lt;/span&gt;
                            &lt;span class="s2"&gt;"config"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                              &lt;span class="s2"&gt;"ip"&lt;/span&gt;: &lt;span class="s2"&gt;"100.64.0.22"&lt;/span&gt;,
                              &lt;span class="s2"&gt;"prefix-length"&lt;/span&gt;: 32
                            &lt;span class="o"&gt;}&lt;/span&gt;,
                            &lt;span class="s2"&gt;"ip"&lt;/span&gt;: &lt;span class="s2"&gt;"100.64.0.22"&lt;/span&gt;,
                            &lt;span class="s2"&gt;"state"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
                              &lt;span class="s2"&gt;"ip"&lt;/span&gt;: &lt;span class="s2"&gt;"100.64.0.22"&lt;/span&gt;,
                              &lt;span class="s2"&gt;"origin"&lt;/span&gt;: &lt;span class="s2"&gt;"STATIC"&lt;/span&gt;,
                              &lt;span class="s2"&gt;"prefix-length"&lt;/span&gt;: 32
                            &lt;span class="o"&gt;}&lt;/span&gt;
                          &lt;span class="o"&gt;}&lt;/span&gt;
                        &lt;span class="o"&gt;]&lt;/span&gt;
                      &lt;span class="o"&gt;}&lt;/span&gt;
                    &lt;span class="o"&gt;}&lt;/span&gt;
                  &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;]&lt;/span&gt;
              &lt;span class="o"&gt;}&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
          &lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Update Example : for update, currently i cannot use the OpenConfig interfaces module to do the update for some reason, so instead, i will use the Cisco provided interfaces module, I will update the Loopback0 description :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nv"&gt;$gnmic&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; clab-01_vmx_xrv_lab_topology-PE2  &lt;span class="nt"&gt;--insecure&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; admin &lt;span class="nt"&gt;-p&lt;/span&gt; admin &lt;span class="nt"&gt;-e&lt;/span&gt; json_ietf  &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;--update-path&lt;/span&gt; &lt;span class="s1"&gt;'Cisco-IOS-XR-ifmgr-cfg://interface-configurations/interface-configuration[active="act"][interface-name="Loopback0"]/description'&lt;/span&gt; &lt;span class="nt"&gt;--update-value&lt;/span&gt; &lt;span class="s2"&gt;"management_interface"&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"source"&lt;/span&gt;: &lt;span class="s2"&gt;"clab-01_vmx_xrv_lab_topology-PE2"&lt;/span&gt;,
  &lt;span class="s2"&gt;"timestamp"&lt;/span&gt;: 1666638282750917788,
  &lt;span class="s2"&gt;"time"&lt;/span&gt;: &lt;span class="s2"&gt;"2022-10-24T19:04:42.750917788Z"&lt;/span&gt;,
  &lt;span class="s2"&gt;"results"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"operation"&lt;/span&gt;: &lt;span class="s2"&gt;"UPDATE"&lt;/span&gt;,
      &lt;span class="s2"&gt;"path"&lt;/span&gt;: &lt;span class="s2"&gt;"Cisco-IOS-XR-ifmgr-cfg:interface-configurations/interface-configuration[interface-name=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Loopback0&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;][active=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;act&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;]/description"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;lets confirm change on the device , see it changed: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

RP/0/RP0/CPU0:PE2#show interfaces loopback 0 description 
Interface          Status      Protocol    Description
/--------------------------------------------------------------------------------
Lo0                up          up          management_interface


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;you can try it with more complex modules like for example the VRF module from Cisco 'Cisco-IOS-XR-ip-iarm-vrf-cfg', with the help of pyang tree command you can explare the possible change.&lt;/p&gt;

&lt;p&gt;Next article we will explore the SNMP replacing gNMI Subscription telemetry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful commands :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To show all the paths avilable in a Yang model ( gnmic - bash )
&lt;code&gt;$ gnmic path openconfig-interfaces --file openconfig-interfaces.yang&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;To only see the paths available to be configured 
&lt;code&gt;gnmic path openconfig-interfaces --file openconfig-interfaces.yang --config-only&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;To run gNMI requests using template inventory "config.yaml" containing the targets, and configuration template "nodes_configuration.yaml"
&lt;code&gt;$ gnmic --config config.yaml set --request-file nodes_configuration.yaml --log&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;To show the tree structure of the Yang model ( pyang - python )
&lt;code&gt;$ pyang Cisco-IOS-XR-ifmgr-cfg.yang -f tree&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enable External LAN access to Containerlab containers 
&lt;code&gt;sudo iptables -vnL DOCKER-USER&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://networkop.co.uk/post/2018-11-k8s-topo-p1/" rel="noopener noreferrer"&gt;Building large scale networks with Kubernetes - part 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vrnetlab/vrnetlab" rel="noopener noreferrer"&gt;Github - vrnetlab - VR Network Lab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://containerlab.dev/install/" rel="noopener noreferrer"&gt;ContainerLab -Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/akarneliuk/pygnmi" rel="noopener noreferrer"&gt;Github pygnmi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/CiscoDevNet/xr-gnmi-lab/blob/master/cisco-gNMI-main.ipynb" rel="noopener noreferrer"&gt;Cisco DevOps gNMI IOS-XR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Juniper/telemetry" rel="noopener noreferrer"&gt;Juniper gNMI telemetry Github&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opennetworking.org/wp-content/uploads/2019/10/NG-SDN-Tutorial-Session-2.pdf" rel="noopener noreferrer"&gt;OpenNetworking Guide to use gNMI - Must Check&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rob.sh/post/213/" rel="noopener noreferrer"&gt;OpenConfig Interfaces - Some Examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://research.google/pubs/pub47963/" rel="noopener noreferrer"&gt;Google Research - Network Visibility for the Automation Age&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=zy9QA-uU0u4" rel="noopener noreferrer"&gt;Easy explanation of Yang modules (youtube)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ciscolive.com/c/dam/r/ciscolive/emea/docs/2019/pdf/BRKSPG-2503.pdf" rel="noopener noreferrer"&gt;Cisco Live : gRPC IOS-XR deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/playlist?list=PLsTgo2tBPnTwmeP9zsd8B_tZR-kbguvla" rel="noopener noreferrer"&gt;pyGNMI Demo - gnmi for python (Youtube) &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gnmic.kmrd.dev/user_guide/prompt_suggestions/#ios-xr" rel="noopener noreferrer"&gt;gnmic Prompt mode - Cisco/Juniper/Arista&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://apps.juniper.net/telemetry-explorer/select-software?software=Junos%20OS&amp;amp;release=21.2R2&amp;amp;moduleId=All&amp;amp;platform=11320022" rel="noopener noreferrer"&gt;Juniper Paths Explorer (Official)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>network</category>
      <category>gnmi</category>
      <category>containerlab</category>
      <category>grpc</category>
    </item>
    <item>
      <title>RPKI , securing BGP Infrastructure - with Lab</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Tue, 13 Sep 2022 07:51:56 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/rpki-securing-bgp-infrastructure-32ij</link>
      <guid>https://dev.to/amrelhusseiny/rpki-securing-bgp-infrastructure-32ij</guid>
      <description>&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Introduction&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;What &amp;amp; Why RPKI ?&lt;/li&gt;
&lt;li&gt;Signing ROAs 

&lt;ul&gt;
&lt;li&gt;what is an ROA ?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;How you deploy ? &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;*&lt;em&gt;RPKI-RTR  architecture *&lt;/em&gt;

&lt;ul&gt;
&lt;li&gt;PDUs Structure (rpki-rtr-pdu)&lt;/li&gt;
&lt;li&gt;Protocol workings

&lt;ul&gt;
&lt;li&gt;Serial Query/Cache Response&lt;/li&gt;
&lt;li&gt;Serial Notify&lt;/li&gt;
&lt;li&gt;End of data&lt;/li&gt;
&lt;li&gt;Reset Query &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Applying RPKI [Lab]&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;1) Setup a Validator&lt;/li&gt;
&lt;li&gt;2) Discarding BGP invalids / configuring routers&lt;/li&gt;
&lt;li&gt;3) Validating RPKI operations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;MANRS (Mutually Agreed Norms for Routing Security)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;h2&gt;
  
  
  What &amp;amp; Why RPKI (Resource Public Key Infrastructure)?
&lt;/h2&gt;

&lt;p&gt;BGP is the routing protocol of the Internet backone, but it always lacked a way to validate recieved routes, this opened the protocol up tp some nasty attack of which one of the more popular ones is &lt;em&gt;Route Hijacking&lt;/em&gt; in which a peer would falsely or mistakingly advertise some routes as if it is the originator, you can read more about an example of this case in &lt;a href="https://www.catchpoint.com/blog/bgp-hijacking"&gt;Taiwan's TWNIC hijack&lt;/a&gt; in 2019, intentional attack could have resulted in either blackholing the traffic, or driving traffic towards a sniffing device to spy.&lt;/p&gt;

&lt;p&gt;In order to overcome this, and RFC was created &lt;strong&gt;RFC-6810&lt;/strong&gt; and a work group was spun up to push for the implementation of this. feature represented by &lt;strong&gt;MANRS&lt;/strong&gt; (Mutually Agreed Norms for Routing Security).&lt;/p&gt;

&lt;p&gt;What happens that the BGP running device validates the recieved BGP route againt the RPKI local database to confirm the validty of the originating AS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RPKI is used for Origin Validation and not AS-Path validation&lt;/strong&gt; , RPKI validation process only looks at the OriginAS in the Route NLRI, however it does not look in AS Path, so you may have a hijacker start a malicious router with your AS number behind his own AS and use that to advertise your prefix, or AS-Path, you should be doing Prefix filtering on your boundaries anyways.&lt;/p&gt;

&lt;h2&gt;
  
  
  Signing ROAs
&lt;/h2&gt;

&lt;p&gt;1st you need to understand that there is 5 Certificate Authorities in conjunction with the RIRs (Regional Internet Registry) charged with creating and validating the carriers certificates, you should register ROAs with your RIR, using your already created service provider account.&lt;/p&gt;

&lt;p&gt;side note - Certificate providers are AFRINIC, APNIC, RIPE NCC, LACNIC, ARIN.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J6Ec48z_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iana.org/_img/2013.1/rir-map.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J6Ec48z_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.iana.org/_img/2013.1/rir-map.svg" alt="RIRs" width="300" height="160"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  what is an ROA ?
&lt;/h3&gt;

&lt;p&gt;The Route of Origin Authorization simply consists of a Prefix and its Origin, indicating which AS (Autonomous System) is authorised to advertise this Prefix.&lt;br&gt;
Multiple ROAs can exist for the same Prefix, ROAs can overlap.&lt;/p&gt;

&lt;p&gt;I can better show you how an ROA looks like from a captured RPKI Route Update : &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ekGm57rn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1p8irhohs84nkf2hnz6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ekGm57rn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1p8irhohs84nkf2hnz6a.png" alt="Image description" width="880" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;in the above snapshot, means you can advertise any network in between the /22 and /24 subnet mask, so its not only allowing you advertise one subnet, but a range of subnet masks.&lt;/p&gt;

&lt;p&gt;Cool way to search for the registered prefixes on &lt;a href="https://irrexplorer.nlnog.net"&gt;NLNOG's IRR Exp&lt;/a&gt; , this enables you to see which IRR is a particular ROA is registered with: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OintUOxD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sdq2e7gxcg4lbabo2w3l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OintUOxD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sdq2e7gxcg4lbabo2w3l.png" alt="Image description" width="880" height="344"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How you deploy ?
&lt;/h2&gt;

&lt;p&gt;Simply you will need to do the following, we will go more in detail later:&lt;br&gt;
1) Create ROAs (Route of Origin Authorization).&lt;br&gt;
2) Setting up Validators (Validation Cache Servers).&lt;br&gt;
3) Discarding BGP invalids on boundry routers .&lt;/p&gt;
&lt;h1&gt;
  
  
  RPKI-RTR  architecture
&lt;/h1&gt;

&lt;p&gt;RPKI-RTR is the protocol used in between the validator and the Client routers, the RFCs states the structure to deploy the RPKI service as per the following driagram :&lt;br&gt;
Note : Local Cache = Validator&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IjDbMVzD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67ap0u3l0vzyv5xr61nz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IjDbMVzD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67ap0u3l0vzyv5xr61nz.png" alt="Image description" width="880" height="344"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  PDUs Structure (rpki-rtr-pdu)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EgiSupii--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ps9vmoly47ptn95a28xa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EgiSupii--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ps9vmoly47ptn95a28xa.png" alt="Image description" width="880" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The update header includes the following : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Protcol Version&lt;/strong&gt; : currently version 0&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PDU Type&lt;/strong&gt; : IPv4 for example&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serial Number&lt;/strong&gt; : Indicates the last update number recieved from the upstream Cache or Global RPKI server, so if the downstream client router sends his last PDU Serial number to the upstream Cache , the Cache will send the client router all PDUs with greater Serial number which correspinds to the the updates that this client router did not recieve yet .&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session ID&lt;/strong&gt; : Used in conjunction with the Serial number to identify these Serial Numbers are still attached to the same session that is established with the upstream server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Length&lt;/strong&gt; : length of the whole PDU&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flags&lt;/strong&gt; : 1 for Announcement - 0 for Withdraw&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefix Length&lt;/strong&gt; : Shortest Prefix (Min)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Max Length&lt;/strong&gt; : Longest Prefix (Max) &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prefix&lt;/strong&gt; : The IP Portion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AS&lt;/strong&gt; : 32-bit format AS number (Autonomous Number)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;span&gt;Note : IPx PDU uniqueness is identified by the set of [Prefix, Len, Max-Len,ASN]&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Protocol workings
&lt;/h2&gt;

&lt;p&gt;RPKI uses the port &lt;em&gt;rpki-rtr TCP 323&lt;/em&gt;,  also cache to router communication is recommeneded to use TCP-A0 (you can check &lt;a href="https://datatracker.ietf.org/doc/html/rfc5925"&gt;RFC-5925&lt;/a&gt;) for authentication instead of TCP-MD5.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pbBoPewi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4td97z0jywvs11f9k6t6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pbBoPewi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4td97z0jywvs11f9k6t6.png" alt="Image description" width="644" height="463"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Serial Query/Cache Response
&lt;/h3&gt;

&lt;p&gt;A session is kept up between either the RPKI Cache and the Global RPKI server , or between the downstream RPKI client router and the RPKI Cache.&lt;br&gt;
The router periodically sends the Cache server the last (greatest) PDU Serial number , the cache responds by sending all the updates with a higher Seral number, then the client router updates its current serial number to the last PDU recieved.&lt;br&gt;
To make sure that the data is up to date a Keepalive like interval of 1 hour, at which the Client router should send a Serial Query to make sure his updates are up to date.&lt;/p&gt;
&lt;h3&gt;
  
  
  Serial Notify
&lt;/h3&gt;

&lt;p&gt;When the RPKI Cache recieves updates, it send a Notification to its clients, saying this is a good time to Poll for new data, Client routers must be the one initiating the requests for the update .&lt;/p&gt;
&lt;h3&gt;
  
  
  End of data
&lt;/h3&gt;

&lt;p&gt;If the Cache recieves a query and finds that there is no updates to send to the Client router, instead it sends an End of data PDU&lt;/p&gt;
&lt;h3&gt;
  
  
  Reset Query
&lt;/h3&gt;

&lt;p&gt;Client router requests the whole current updates database from the Cache server, this message can be sent in the rest or the start of the connection so the Client can recieve a full table f updates from the caching server, initiation looks as follows .&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--us9St6GZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i2muafjfojhn461lyy4o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--us9St6GZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i2muafjfojhn461lyy4o.png" alt="Image description" width="438" height="323"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Applying RPKI
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wIfTQ3ny--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ht84su2yj40yfa7q0pa2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wIfTQ3ny--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ht84su2yj40yfa7q0pa2.png" alt="Image description" width="599" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are using Ubuntu with Routinator which is a RIPE developed Route Validator, and 2 IOS-XE routers, Router_1 is RPKI Client, and Router_2 is the eBGP peer that will send the invalid subnet 1.0.0.0/24 .&lt;/p&gt;

&lt;p&gt;After ROA is created, it may take to 10 minutes to show up in the Registries databases and would be able to validate.&lt;/p&gt;
&lt;h2&gt;
  
  
  1) Setup a Validator
&lt;/h2&gt;

&lt;p&gt;There is multiple validators available on the market , we will be using  Routinator ,a validator developed by RIPE.&lt;br&gt;
Remember RPKI Validators downloads the whole RPKI Repository from the RIRs databases, acting as cache afterwards, keeping its database updated by queriing the RIRs periodically .&lt;/p&gt;

&lt;p&gt;There are multiple Validtor softwares available other than Routinator if you prefer such as &lt;a href="https://www.rpki-client.org"&gt;OpenBSD's RPKI-Client&lt;/a&gt; , &lt;a href="https://blog.cloudflare.com/cloudflares-rpki-toolkit/"&gt;Cloudflare's OctoRPKI&lt;/a&gt; , or &lt;a href="https://fortproject.net/en/validator"&gt;FORT's Validator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For now we are going to use Routinator, but feel free to use any of these packages. &lt;/p&gt;
&lt;h3&gt;
  
  
  steps
&lt;/h3&gt;

&lt;p&gt;Update and install gcc C compiler, then installing Rust as Routinator is written in Rust, after that we run it .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get gcc
&lt;span class="nv"&gt;$ &lt;/span&gt;curl https://sh.rustup.rs &lt;span class="nt"&gt;-sSf&lt;/span&gt; | sh 
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.cargo/env 
&lt;span class="nv"&gt;$ &lt;/span&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;routinator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All RIRs repos are by default open to be queried with no issue, but for ARIN, you have to acknowledge you have read the terms and accept, to accept the ARIN's aggreement :&lt;br&gt;
&lt;code&gt;$ routinator init --accept-arin-rpa&lt;/code&gt;&lt;br&gt;
Following command will show and print out the whole Global IP Address allocation (ROAs) , it could some time , i would advise to run it in the background :&lt;br&gt;
&lt;code&gt;$ routinator -v vrps&lt;/code&gt;&lt;br&gt;
To have the Routinator(Validator/RPKI Cache) start listening to Client's/Router's request, start the service with the following command, the default port for RPKI should be 323, but to avoid running the server as root, we will be using port 3323 instead :&lt;br&gt;
&lt;code&gt;$ routinator server --rtr 192.168.1.143:3323 --refresh=900&lt;/code&gt;&lt;br&gt;
Following how your newy installed validator communication looks like&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gql-3FLj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hib02x85lg7okmlvmvc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gql-3FLj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hib02x85lg7okmlvmvc2.png" alt="Image description" width="460" height="342"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Allow List
&lt;/h3&gt;

&lt;p&gt;You can create a whitelist locally in your validator, to add exceptions for some subnets that you donot need validated.&lt;/p&gt;
&lt;h2&gt;
  
  
  2) Discarding BGP invalids / configuring routers
&lt;/h2&gt;

&lt;p&gt;On a Cisco IOS-XE router, its as simple as running the following command under the "router bgp xxxxx" config &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My Authenticator server IP is 192,168.1.143 and port 3323 is the listening port :
&lt;code&gt;Router(config-router)#bgp rpki server tcp 192.168.1.143 port 3323 refresh 900&lt;/code&gt;
Now on the Cisco router I am connected to the validator server and able to see the established session
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Router#show ip bgp rpki servers 
BGP SOVC neighbor is 192.168.1.143/3323 connected to port 3323
Flags 64, Refresh time is 900, Serial number is 0, Session ID is 30149
InQ has 0 messages, OutQ has 0 messages, formatted msg 1
Session IO flags 3, Session flags 4008
 Neighbor Statistics:
  Prefixes 299821
  Connection attempts: 1
  Connection failures: 0
  Errors sent: 0
  Errors received: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and you can see the whole ROA table&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Router(config-router)#do show ip bgp rpki tab
228256 BGP sovc network entries using 36520960 bytes of memory
250017 BGP sovc record entries using 8000544 bytes of memory
Network              Maxlen  Origin-AS  Source  Neighbor
1.0.0.0/24           24      13335      0       192.168.1.143/3323
1.0.4.0/24           24      38803      0       192.168.1.143/3323
1.0.4.0/22           22      38803      0       192.168.1.143/3323
1.0.5.0/24           24      38803      0       192.168.1.143/3323
1.0.6.0/24           24      38803      0       192.168.1.143/3323
....... 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that this table is not your routing table, its for validation not for route reflection.&lt;br&gt;
Now to further have a look about the PDUs , i setup a wireshark capture, after that, you need to go to the capture stream of the port 3323 and click decode as/current/RPKI-Router-Protocol like the following screenshot &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KtaJojcw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kqoxxastnywoe6jaarq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KtaJojcw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0kqoxxastnywoe6jaarq.png" alt="Image description" width="880" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y2yeL2BB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oi1s0aby17hsx8qn2uh0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y2yeL2BB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oi1s0aby17hsx8qn2uh0.png" alt="Image description" width="880" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also use the RPKI validation in your router's route policy's (Cisco, Juniper and so on), for instance you can set a preference for the validated routes, you donot need to reject the non-validated routes, you can just set a worse preference for them. &lt;/p&gt;
&lt;h2&gt;
  
  
  3) Validating RPKI operations
&lt;/h2&gt;

&lt;p&gt;eBGP configured between Router_1 (RPKI Client) and Router_2 (Hijacking router) , and network 1.0.0.0/24 is advertised from Router_2 to Router_1, when we inspect Router_1's routing table we see the subnet not present, meaning RPKI is working.&lt;br&gt;
To see the reason for rejecting the route on Router_1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Router_1#show bgp 1.0.0.0
BGP routing table entry for 1.0.0.0/24, version 0
Paths: (1 available, no best path)
  Not advertised to any peer
  65004
    10.0.0.2 from 10.0.0.2 (10.0.0.2)
      Origin IGP, metric 0, localpref 100, valid, external
     path 7FA8A922B2E8 RPKI State invalid  &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;
      rx pathid: 0, tx pathid: 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  MANRS
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;(Mutually Agreed Norms for Routing Security)&lt;/em&gt;&lt;br&gt;
MANRS is a group of operators initiative pushing for route security and security actions, they publish an Actions whitepaper for service providers how to participate and which actions is compulsory and which actions are options.&lt;br&gt;
You can find detailed explanation in their publication on manrs.org.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compulsory Actions to join
&lt;/h2&gt;

&lt;p&gt;1) Prevent probagation of incorrect routing information : mainly confirm their peer service provider actually holds that IP Prefix and AS number.&lt;br&gt;
2) Correct up to date NOC Contact for carriers correspinding to prefixes/ASs should be registered and kept current with Regional and/or National regisry (RIR &amp;amp; NIR), can be registered with the PeeringDB (&lt;a href="https://docs.peeringdb.com/howto/get-started-operator/"&gt;PeeringDB Network Operators HowTo&lt;/a&gt;).&lt;br&gt;
3) Carriers must publicly document their owned subnets/ASs and also which prefixes/ASs they provide Transit services for through their RPSL with IRRs, or RIRs, and NIR databases, also recommended to create ROAs (Route of Origin Authorizations) foe the list of prefixes will be advertised by the carrier.&lt;br&gt;
4) Prevent Spoofed traffic by using source address filteration or a tool like uRPF.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.catchpoint.com/blog/bgp-hijacking"&gt;(Article) What is BGP ROute Hijacking ?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc6810.html"&gt;(RFC_6810) The Resource Public Key Infrastructure (RPKI)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.iana.org/numbers"&gt;(Website)IANA Numbering organizations and scope&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.manrs.org/"&gt;(Website) Mutually Agreed Norms for Routing Security (MANRS) - SP Group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cisco.com/c/en/us/support/docs/ip/border-gateway-protocol-bgp/217020-bgp-rpki-with-xr7-cisco8000-whitepaper.html"&gt;(Article) BGP RPKI With XR7 (Cisco8000) Whitepaper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.apnic.net/2019/09/11/how-to-creating-rpki-roas-in-myapnic/"&gt;(Article) RPKI ROAs Authentcator - Ubuntu setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.manrs.org/2022/07/one-does-not-simply-deploy-rpki/"&gt;(Article) One Does Not Simply “Deploy RPKI”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=h7Z2l6oqa6M"&gt;(Video) MANRS session - understanding RPKI deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://afrinic.net/resource-certification"&gt;(Article) AFRINIC's RPKI Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://routinator.docs.nlnetlabs.nl/en/stable/"&gt;(Website) Routinator Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://routinator.docs.nlnetlabs.nl/en/stable/installation.html"&gt;(Article) How to install Routinator Validator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>networks</category>
      <category>bgp</category>
      <category>security</category>
    </item>
    <item>
      <title>Extending RFC1918 with RFC-6598 (100.64.0.0/10)</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Sat, 10 Sep 2022 19:18:54 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/extending-rfc1918-with-rfc-6598-100640010-1p1g</link>
      <guid>https://dev.to/amrelhusseiny/extending-rfc1918-with-rfc-6598-100640010-1p1g</guid>
      <description>&lt;h1&gt;
  
  
  introduction
&lt;/h1&gt;

&lt;p&gt;We are all familiar with the RFC-1918 AKA Private IP Spaces (10.x.x.x , 172.16.x.x , 192.168.x.x), called private IP addresses because they can be duplicated by any user as long as the duplicated IP assigned devices does not meet in same L3 network.&lt;/p&gt;

&lt;p&gt;But due to the exhaustion of the Public IPv4 space , IANA has assigned a second address space like RFC-1918 , this time though &lt;a href="https://datatracker.ietf.org/doc/html/rfc6598"&gt;RFC-6598&lt;/a&gt; and its called the &lt;strong&gt;Shared Address space&lt;/strong&gt; since 2012 , while it was originaly intended to be used for CGNAT (Carrier Grade Natting), IANA stated in the standard, that it also can be used in the same manner as RFC-1918 addresses , quoting from RFC-6598:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use of Shared CGN Space Shared Address Space is IPv4 address space designated for Service Provider use with the purpose of facilitating CGN deployment.  &lt;strong&gt;Also, Shared Address Space can be used as additional non-globally routable space on routing equipment that is able to do address translation across router&lt;/strong&gt; interfaces when the addresses are identical on two different interfaces.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The newly assigned address space is the &lt;strong&gt;100.64.0.0/10&lt;/strong&gt;, you may be familiar with, for me was 1st exposed to the usage of this address space in Datacenters's devices loopback interfaces, wherther network devices or baremetal servers, thats why I went on a journy to do research on the usage of this IP Space .&lt;/p&gt;

&lt;p&gt;to pivot a little bit for you to understand what is CGNAT before we continue. &lt;/p&gt;

&lt;h2&gt;
  
  
  CGNAT (Carrier Grade NAT)
&lt;/h2&gt;

&lt;p&gt;Described very simply in the following diagram : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vpmnzg8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfs0ammg97dt16z4yagi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vpmnzg8C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfs0ammg97dt16z4yagi.png" alt="Image description" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; : each home CPE was assigned a Public IP address to use to reach internet directly .&lt;br&gt;
&lt;strong&gt;After&lt;/strong&gt; : Home CPEs are assigned RFC-6589 IP Address (100.64.0.0/10) that will be Natted to Public IP ranges on the edge of your ISP , still the NATing is one to one , but you will only need a Public IP address if you want to reach external resources , as long as you stay in your carrier's network you will beusing your RFC-6598 IP.&lt;/p&gt;

&lt;p&gt;You may ask why not just use RFC-1918 IPs for home CPE, while its possible, it showed to cause operational issue with the carriers.&lt;/p&gt;

&lt;p&gt;One of the considerations that carriers should start doing , is including the 100.64.0.0/10 in their incoming route filter list from other carriers as a security mediation , just like all carriers do with the RFC-1918 ranges , quoting the RFC.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;routing information about Shared Address Space networks MUST NOT be propagated across Service Provider boundaries.  Service Providers MUST filter incoming advertisements regarding Shared Address Space.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;back to our main topic&lt;/p&gt;

&lt;h1&gt;
  
  
  Special Use IP Addresses
&lt;/h1&gt;

&lt;p&gt;Since we are having a look at one of the new address spaces, lets take this opportunity to get to know some of the unfamiliar special use IP ranges stated by IANA in &lt;a href="https://datatracker.ietf.org/doc/html/rfc5735"&gt;RFC-5735&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is to extend your knowledge of the RFCs specs , but not all Networks Engineers adhere to those testing IP ranges, we mostly see the compliance in the Operational spaces only .&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Address Space&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;169.254.0.0/16&lt;/td&gt;
&lt;td&gt;This is the "link local" block.  As described in [RFC3927], it is allocated for communication between hosts on a single link.  Hosts obtain these addresses by auto-configuration, such as when a DHCP server cannot be found.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;192.0.2.0/24 , 198.51.100.0/24,&lt;/td&gt;
&lt;td&gt;This block is assigned as "TEST-NET" for use in documentation and example code.  It is often used in conjunction with domain names example.com or example.net in vendor and protocol documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;192.88.99.0/24&lt;/td&gt;
&lt;td&gt;This block is allocated for use as 6to4 relay anycast addresses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;198.18.0.0/15&lt;/td&gt;
&lt;td&gt;This block has been allocated for use in benchmark tests of network interconnect devices, this range was assigned to minimize the chance of conflict in case a testing device were to be accidentally connected to part of the Internet.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Q&amp;amp;A
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why shouldn't use Shared Address Space range in your Enterprise network ?&lt;/strong&gt; , in the renound &lt;a href="https://blog.ipspace.net/2013/08/can-i-use-shared-rfc-6598-ipv4-address.html"&gt;Ivan Pepelnjak article &lt;/a&gt;, he argues that you should never use this IP address space (100.64.0.0/10) as its not considered Private and it will result in issues if you are using that address space in your enterprise sites at the same time that your Servic Provider is using CGNAT as he would probably using IPs from the same space on his CPE external interface .&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When you should use Shared Address Space IPs in your enterprise ?&lt;/strong&gt; If you ran out of IPv4 private addresses and you are unable to migrate to IPv6 , DONOT use them to interconnect with your service provider and DONOT advertise them your service provider.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Where is it used ?&lt;/strong&gt; some Datacenter providers and clouds use these addresses  in the underlay as they are less likely to conflict with any overlay customer's address which probably is in the RFC-1918 ranges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why Cloud providers are pivoting to use the Shared Address Space in their Data centers?&lt;/strong&gt; At 1st I thought when we used it in our Datacenter underlay that we would be the only ones doing that, but it seems to be an industry wide direction in the Cloud providers specifically, found that also VMWare does the same , you can check &lt;a href="https://kb.vmware.com/s/article/76022"&gt;VMware SDDC&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How many addresses available in the Private/Shared address ranges ?&lt;/strong&gt;
| Address Range  | Number of IPv4 addresses |
|----------------|--------------------------|
| 10.0.0.0/8     | 16 Million addresses     |
| 172.16.0.0/12  | 1 Million addresses      |
| 192.168.0.0/16 | 65536 Addresses          |
| 100.64.0.0/10  |                          |&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;Following are useful RFCs to understand the reason behind the push and the issues faced by carriers implementing CGNAT&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc6598"&gt;RFC-6598 - IANA-Reserved IPv4 Prefix for Shared Address Space&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc6264"&gt;RFC-6264 - An Incremental Carrier-Grade NAT (CGN) for IPv6 Transition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc6304"&gt;RFC-6304 - AS112 Nameserver Operations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://datatracker.ietf.org/doc/html/rfc6269"&gt;RFC-6269 Issues with IP Address Sharing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.f5.com/es_es/company/blog/solving-ip-overlap-in-multi-cloud"&gt;F5 Solving IP Overlap in Multi-Cloud&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>networking</category>
      <category>rfc</category>
    </item>
    <item>
      <title>Automating DrawIO network topology using Python</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Tue, 06 Sep 2022 19:42:51 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/automating-drawio-network-topology-using-python-4k25</link>
      <guid>https://dev.to/amrelhusseiny/automating-drawio-network-topology-using-python-4k25</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;In this blog , we are going to show how to use the draw_network_plot python library to generate a DrawIO Network topology easily instead of manually drawing them yourself .&lt;/p&gt;

&lt;p&gt;DrawIO is widely used as a free alternative to Microsoft's Visio to draw network topologies.&lt;/p&gt;

&lt;p&gt;I will be using Netmiko and CDP to acquire the data needed for the plot for the devices themselves , but this part won't be the focus of the article .&lt;/p&gt;

&lt;p&gt;Focus of the article is how to use the "drawio_network_plot" library" to generate the DrawIO file .&lt;/p&gt;

&lt;h1&gt;
  
  
  Library setup
&lt;/h1&gt;

&lt;p&gt;Make sure to have Python 3.7 and above , then install the library using : &lt;br&gt;
&lt;code&gt;$ pip install drawio_network_plot&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Lab setup
&lt;/h1&gt;

&lt;p&gt;Lab is done on EVE-NG using Cisco's 7200VXR image to create the topology , the whole topology is L3 with Loopback so the Python CentOS server would be able to ssh to each device .&lt;/p&gt;

&lt;p&gt;EVE-NG Topology Diagram (Non-generated): &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyjd4vdm6dcwo6wsfvd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyjd4vdm6dcwo6wsfvd4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuration and Script
&lt;/h1&gt;

&lt;p&gt;You can find both the below script and all the EVE-NG Cisco devices configuration in the following Github Link : &lt;br&gt;
&lt;a href="https://github.com/amroashram/drawio_network_plot/tree/main/examples/cisco_gather_cdp_and_plot" rel="noopener noreferrer"&gt;drawio_network_plot/examples/cisco_gather_cdp_and_plot&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;netmiko&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ConnectHandler&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt; 
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;drawio_network_plot.drawio_network_plot&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NetPlot&lt;/span&gt;

&lt;span class="c1"&gt;# ----------------- Getting live CDP Neigbors to gather links endpoints ---------------------------
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retieve_lldp_neigbor_hostname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devices_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;list_of_cdp_neighborship&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;devices_list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;device_dictionary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;device_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cisco_ios&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;username&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;automation&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;1234567&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;net_connect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConnectHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;device_dictionary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;net_connect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;show cdp neighbor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;lines_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lines_list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# regex to search the name of the device before the domain ID ".default" , then removing the word ".default" from the string
&lt;/span&gt;                &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sourceNodeID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;destinationNodeID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\S+\.default&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.default&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                            &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="c1"&gt;# checking for duplication before adding new link : 
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sourceNodeID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;destinationNodeID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;destinationNodeID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sourceNodeID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;list_of_cdp_neighborship&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;list_of_cdp_neighborship&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;net_connect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;list_of_cdp_neighborship&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Lab Devices , must have the device type for the plotting library to work 
&lt;/span&gt;    &lt;span class="n"&gt;devices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Router_1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;100.0.1.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;router&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeDescription&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NA&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Router_2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;100.0.1.2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;router&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeDescription&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NA&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Spine_1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;100.0.2.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;l3_switch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeDescription&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NA&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Spine_2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;100.0.2.2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;l3_switch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeDescription&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NA&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Leaf_1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;100.0.3.1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;l2_switch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeDescription&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NA&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Leaf_2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;100.0.3.2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;l2_switch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeDescription&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NA&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Leaf_3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ip_address&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;100.0.3.3&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;l2_switch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeDescription&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NA&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;# Getting list of links for each device
&lt;/span&gt;    &lt;span class="n"&gt;list_of_cdp_neighborship&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;retieve_lldp_neigbor_hostname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;peering&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;list_of_cdp_neighborship&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;peering&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# ------------------------------------------------------------------------------------------------------
&lt;/span&gt;    &lt;span class="c1"&gt;# ------------------------------------------------------------------------------------------------------
&lt;/span&gt;    &lt;span class="c1"&gt;# ----------------- Main Part : using library to generate XML DrawIIO format ---------------------------
&lt;/span&gt;    &lt;span class="c1"&gt;# Using the Plot library 
&lt;/span&gt;    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NetPlot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addNodeList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;devices&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLinkList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;list_of_cdp_neighborship&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;display_xml&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="c1"&gt;# ------------------------------------------------------------------------------------------------------
&lt;/span&gt;    &lt;span class="c1"&gt;# ------------------------------------------------------------------------------------------------------
&lt;/span&gt;    &lt;span class="c1"&gt;# ------------------------------------------------------------------------------------------------------
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Library Options
&lt;/h1&gt;

&lt;p&gt;Remember , you can gather the data however you like , this was just a simple demonstration of what you can do , main code to remember is the plotting part : &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# please adhere to the naming scheme in the variables 
&lt;/span&gt;&lt;span class="n"&gt;device_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeName&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;TOR_1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeType&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;l2_switch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nodeDescription&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Leaf Switch 01&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NetPlot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# **IMPORTANT NOTE :**---&amp;gt; Make sure that the sourceNode in the connection is the higher level device and that connections are not replicated , this way when you use the DrawIO automatic layout , it would create the diagram hierarchy the correct way 
&lt;/span&gt;&lt;span class="n"&gt;connections_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sourceNodeID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Router_1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;destinationNodeID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Core_switch_1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="c1"&gt;# Adding using list all at once
&lt;/span&gt;    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addNodeList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLinkList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connections_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Adding node by node and link by link
&lt;/span&gt;    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nodeName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Router_18&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;nodeType&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;router&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Router_17&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Router_18&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# --- Output ---
&lt;/span&gt;    &lt;span class="c1"&gt;# You can print the XML to the Stdout 
&lt;/span&gt;    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;display_xml&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="c1"&gt;# Or You can also directly generate an XML file using the built in function :
&lt;/span&gt;    &lt;span class="c1"&gt;# x.exportXML('examples/output.xml')    
&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Generated output will be collapsed in one point , you will have to choose the Layout you would like in DrawIO after opening the file like showed as follows : &lt;/p&gt;

&lt;h2&gt;
  
  
  Generated Topology
&lt;/h2&gt;

&lt;p&gt;1- Open generated XML file in DrawIO &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib3nzokb74uz94fhibvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib3nzokb74uz94fhibvb.png" alt="Initial Generated File"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2- go to Arrange/Layout/Vertical Tree&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frtocjyqod2x81xdm4bts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frtocjyqod2x81xdm4bts.png" alt="go to Arrange/Layout/Vertical Tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3- Final Result&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhcbir9mimm93o4eb58a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhcbir9mimm93o4eb58a.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For any comment on the pip package , feature addition or any comment , please share your suggestions as this is my 1st PIP library , and divinely its not perfect .&lt;/p&gt;

&lt;p&gt;Thanks ...&lt;/p&gt;

</description>
      <category>python</category>
      <category>networks</category>
      <category>automation</category>
    </item>
    <item>
      <title>Understanding networks ASICS - Part 1</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Sun, 04 Sep 2022 21:07:54 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/understanding-networks-asics-part-1-5b21</link>
      <guid>https://dev.to/amrelhusseiny/understanding-networks-asics-part-1-5b21</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;For people working in the planning portion of networks , they will face important decision for whether to expand on an exiting chassis they already are running or whether they are going with a new vendor or model, if this is your first time to do that , what are the questions you need to ask yourself or your vendor ? &lt;/p&gt;

&lt;p&gt;Depending on the network these chassis are going to be deployed , you need to ask the following :&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Routing vs Switching&lt;/strong&gt; - Are you going to run a routing L3 protocol , or you just need a Web scale L2 switching ?&lt;br&gt;
• &lt;strong&gt;Feature Rich vs High Speed&lt;/strong&gt; - Do you need feature rich such for enterprise edge , or datacenter TOR or backbone service router for example or very fast and lean spine or backbone switching device ?&lt;br&gt;
• &lt;strong&gt;Deep buffer vs Shallow buffer&lt;/strong&gt; - Does your network benefit from a Deeper off chip sizable buffer or Shallower faster on-chip buffer ?&lt;br&gt;
• &lt;strong&gt;Programmable vs Fixed&lt;/strong&gt; - Are you intending to program the chip yourself/vendor will you just use the chip's features as hardware allows ?&lt;br&gt;
• &lt;strong&gt;Advanced vs Basic traffic management&lt;/strong&gt; - Are you going to implement a legacy basic routing control over traffic , or will you start using intent based controller based routing policies ?&lt;br&gt;
• &lt;strong&gt;Fixed box vs Modular chassis&lt;/strong&gt; - Do you need a 1RU box or multi unit expandable modifiable chassis ?&lt;/p&gt;

&lt;p&gt;There is a fierce competition in the Ethernet silicon area in different directions, there is the competition between Commercial general purpose silicon and the traditional Merchant silicon providers in the cost , throughput and features areas . &lt;/p&gt;

&lt;p&gt;It used to be feature rich against high throughput silicons , but its no longer that simple since the cost of chips now mostly depend on the size of the silicon die (portion of the processor holding the transistors), silicon fabricators already set some standard sizes that processor designer have to adhere to  .&lt;/p&gt;

&lt;p&gt;Silicon chips used to face a problem with yields because processors comprised of a single die which became more costly each time you increase its size, but lately there has been a direction to break that single piece of silicon to multiple "Chiplets" with cores on a multiple chiplets and IO maybe on another chiplet , these chiplets even used different transistor sizes to optimize the cost against the feature list , so for instance you may have your CPU core made in 7nm process node you can have the IO chiplet made in the 14nm process node size to make it more cost effective , this approach was pioneered by AMD in its EPIC datacenter CPU family , and in the network space it started to appear with Intel's Tofino 2 family bundling Tofino 2 7nm Cores with , read more about it in &lt;a href="https://www.sdxcentral.com/articles/news/barefoot-networks-debuts-tofino-2-using-7nm-technology/2018/12/"&gt;Intel Tofino 2 pioneering chiplets design&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  ASICS Pipelines
&lt;/h1&gt;

&lt;p&gt;Basically ASICs works in a bunch of Pipelines , for instance in a Network ASIC for example , a pipline dictates the way traffic is being processed from the moment it ingresses through a port to egressing through another port :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MV8cB_ZW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67b3gs8nmq3lj86mrtw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MV8cB_ZW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/67b3gs8nmq3lj86mrtw4.png" alt="Image description" width="463" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kDPwYg9C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6bf44nfqyjdzk2sb9ah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDPwYg9C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6bf44nfqyjdzk2sb9ah.png" alt="Image description" width="678" height="414"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://people.ucsc.edu/~warner/Bufs/cisco-3100-arch.pdf"&gt;Cisco 3100 Architecture&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The parts of the pipeline represents the feature sets , so when a TAC support advises , that a feature is not supported in Hardware , it means that its not implemented in the ASIC's Pipeline, to give an example some chassis does not support VXLAN forwarding, meaning the ASIC's pipeline does not feature a part dedicated for VXLAN encapsulation and decapsulation imprinted on the hardware .&lt;/p&gt;

&lt;p&gt;Sometimes for vendor instead of redesigning a new ASICs pipline to support a new feature , they would reprogram an existing ASIC and do what is called a recirculation , so you want to add support for VXLAN for instance , you would have to go 1st time through the Pipeline to decapsulate the VXLAN header 1st , then recirculate the traffic second time into the same pipeline but this time for L3 lookup , as these actions was not designed on the ASIC to be supported at the same time , some behavior we used to see with GRE and MPLS , you had to choose only one if you want to pass the pipeline once , if you wanted both then you have to pass the pipeline twice , this of course doubles the latency .&lt;/p&gt;

&lt;p&gt;So vendors would go in a Tic Toc cycle of adding feature thus creating a feature rich platform (like Broadcom's Trident family) , the tic , then optimizing the chip design to process those new features on a faster hardware level (like Broadcom's Tomahawk family) .&lt;/p&gt;




&lt;h2&gt;
  
  
  Programmability
&lt;/h2&gt;

&lt;p&gt;Some ASICS , you would have access to the SDK (Example : P4 , OpenFlow or even hardware level Assembly SDK), some are fixed and some are in-between , example for programable networking targeted chips like the Intel Tofino family or Cisco's latest Silicon One chips that supports P4 programing language.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7IbYzNX---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tbwjaneb6b1dpludkwuq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7IbYzNX---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tbwjaneb6b1dpludkwuq.png" alt="Image description" width="880" height="345"&gt;&lt;/a&gt;&lt;em&gt;&lt;a href="https://www.intel.com/content/www/us/en/products/network-io/programmable-ethernet-switch/tofino-3-product-brochure.html"&gt;image source&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ethernet silicon types:&lt;br&gt;
1) Merchant Silicons : Some companies develop chips to be used inside Vendor's products, these are highly specialized Ethernet focused chips that stands in-between general commercial silicons (like general purpose CPUs) and vendor propriety ones , example companies are like Arista, Broadcom ad Mellanox .&lt;br&gt;
2) Vendor chips : some huge vendors develop their own chips for their own specialized devices like routers and switches , most famous are Cisco and Juniper .&lt;/p&gt;




&lt;h1&gt;
  
  
  CPUs vs FPGAs vs ASICS
&lt;/h1&gt;

&lt;p&gt;The difference between the 3 types are features against tradeoffs , CPUs (like x86) provides the most flexibility and programability vs ASICS providing much faster processing speeds and greater bandwidth with the downside of being not programable while that's true, some of the new ASICs provides and SDK but its very hard to develop for , and mostly these SDKs are used by the Networking vendors instead of the end consumer .&lt;/p&gt;

&lt;p&gt;FPGAs are the man in the middle , much faster than CPUs but with more programability than ASICs .&lt;/p&gt;




&lt;h1&gt;
  
  
  Buffering
&lt;/h1&gt;

&lt;p&gt;There is 2 types of buffers , Shallow on-chip buffer , which is very small , very expensive and then yet very fast , and then there is the second type , the Deep buffer , which can be in the hundreds of Gigabytes , but it would be off-chip and would be much slower , you have both in a Chassis router but each handling a particular scenario .&lt;/p&gt;

&lt;p&gt;Following is Pete's (Pete Lumbis) Opinion on which buffer should handle which type of traffic .&lt;br&gt;
A) Deep buffer : should handle long stance transmission , because microsecond congestion on such port would have big impact on RTT of TCP, mostly are measured in Giga Bytes, and mostly off-chip .&lt;br&gt;
B) Shallow buffers : everything else , mostly measured in Mega bytes, mostly on-chip.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bfOw-7DE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ejrt8uqm9g1431gqws5m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bfOw-7DE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ejrt8uqm9g1431gqws5m.png" alt="Image description" width="880" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.broadcom.com/doc/12395356"&gt;Shallow Buffer on Trident3 - Broadcom&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the hardest topics to understand is buffering , &lt;/p&gt;

&lt;h2&gt;
  
  
  When is buffer used :
&lt;/h2&gt;

&lt;p&gt;1- When Egree port traffic is larger than Ingress ports - 2 Inputs , 1 output ports , if buffer is full , this would provide Overrun packets .&lt;br&gt;
2- When speed changes , input 100G to output 10G port for example .&lt;br&gt;
3- When you need to Store and Forward .&lt;br&gt;
4- If there is a Burst of traffic that is bigger than th Pipeline speed of processing , depends on the packet header size .&lt;/p&gt;

&lt;h2&gt;
  
  
  When buffer is not used :
&lt;/h2&gt;

&lt;p&gt;1- Cut through traffic , so traffic coming in and directly being forwarded out with input and output at same speed.&lt;/p&gt;




&lt;h1&gt;
  
  
  Form Factors
&lt;/h1&gt;

&lt;p&gt;Form factor needs differs from a network addressed to a Cloud provide , hyper scaler , enterprise, or a backbone service provider .&lt;/p&gt;

&lt;p&gt;Most Cloud providers and Hyper scalers tends to use a 1RU form factor switches , on the other hand enterprise core switches and service provider's backbone routers tend to be a large multi-line card chassis, in here we are focusing more on the bigger form factor as it provides many concepts to get familiar with .&lt;/p&gt;

&lt;p&gt;Lets take a Juniper MX2020 service router , the same functionality are implemented in many vendors and models but the naming may differ a little bit , but they all tend to provide the same functionality :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hx-w_GAu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ez822mlnejb8yurxipa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hx-w_GAu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1ez822mlnejb8yurxipa.png" alt="Image description" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Routing Engine
&lt;/h2&gt;

&lt;p&gt;Juniper calls it Routing Engine cards , Cisco calls it Route Processor , these are responsible for handling the Control plane in the legacy way including routing protocols , device management, logging , monitoring, and any functionality besides pure packet forwarding , they establish the peerings, hold the routing tables, apply the route selection derive the RIB and then they translate if into the FIB table that gets cascaded to the Forwarding engines .&lt;/p&gt;

&lt;p&gt;They usually have some redundancy features such as ISSU(), Non stop forwarding and so on .&lt;/p&gt;

&lt;p&gt;The separation between the Routing engines and the Forwarding plane is useful in case of failure of both redundant Routing Engines , you would lose access to the device and the peering would stop but traffic would still transit through the chassis normally without drops as the Forwarding engines (Ports Cards) would have a copy of the last FIB, the only issue would be that FIB would be outdated .&lt;/p&gt;

&lt;h2&gt;
  
  
  Forwarding Engine
&lt;/h2&gt;

&lt;p&gt;Refers to the processors on the Line Cards (Ports cards) , a line card may include one or more of these forwarding processors (ASICs), Juniper calls them PFE(Packet Forwarding Engine) , Cisco has multiple names for these such as NPU(Network Processing Unit) , or PSE(Packet Switching Engine) .&lt;/p&gt;

&lt;p&gt;These are responsible for packet header manipulation, classification, scheduling, policing, rewrite, replication, filtering, accounting, fine-grained traffic steer‐ ing, mirroring, sampling, unicast and multicast RPF checks, class-based forwarding, and many others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fabric Processors
&lt;/h2&gt;

&lt;p&gt;When you have a chassis with multiple line cards, you will mostly find these switch fabrics mediating traffic traversing in-between the Line cards (Forwarding Engines).&lt;/p&gt;

&lt;h2&gt;
  
  
  Backplane
&lt;/h2&gt;

&lt;p&gt;The chassis connectivity lines between all three Routing Engines, Line Cards and Switch fabrics .&lt;/p&gt;

&lt;h2&gt;
  
  
  Further
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7mLJ4pDn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1kmie7dq941tf145bn9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7mLJ4pDn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o1kmie7dq941tf145bn9.png" alt="Image description" width="880" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These cards would show connected into the backplane serial but actually the connectivity between these cards are more like a Spine/Leaf topology of a datacenter just compacted into a Chassis form , looks like this logically &lt;/p&gt;




&lt;h1&gt;
  
  
  ASICS provider
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Broadcom
&lt;/h2&gt;

&lt;p&gt;Broadcom has a wide range of ASICs for Networks , we are going to focus on the more relevant ones to our article , there are 2 families :&lt;br&gt;
1- StrataSGX : Mostly Data Center and 1RU form factor , and you have 2 lines : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feature rich (More Enterprise) : Trident and Maverick lines of chips .&lt;/li&gt;
&lt;li&gt;High speed (Service Provider) : Tomahawk line of chips .
2- StrataDNX : Deep buffer Chassis chips , they mostly live on line cards :&lt;/li&gt;
&lt;li&gt;Buffers and Medium speed : Aurad, Qumran, Jericho &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cisco
&lt;/h2&gt;

&lt;p&gt;Cisco has lately unveiled their Silicon One family of chips targeted towards all fields including data centers , hyperscalers , enterprises and service providers , currently you can see the Q200 Silicon one chip used in the Cisco 8000 family of routers.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M8edg-8U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7zbt75fxpz7oc7abmqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M8edg-8U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w7zbt75fxpz7oc7abmqi.png" alt="Image description" width="837" height="568"&gt;&lt;/a&gt;&lt;a href="https://www.cisco.com/c/dam/en/us/solutions/collateral/silicon-one/white-paper-sp-product-family.pdf"&gt;Cisco sourced image&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mellanox
&lt;/h2&gt;

&lt;p&gt;mellanox is now a part of Nvidea , there chips are more to be found inside White Boxes rather than vendor chassis .&lt;br&gt;
They have only one family for Ethernet chips : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spectrum : low latency , feature rich &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Intel
&lt;/h2&gt;

&lt;p&gt;In 2019, Intel acquired Barefoot , the maker of the Tofino silicon which is directed towards the Datacenter Fabric market , as of 2022 , they have 3 generations of the Tofino chips family , with P4 programable chips, Intel calls its chips IFPs (Intelligent Fabric Processors), to put it into presepctivet , some Arista (7170 Series) ad Cisco (Nexus 3400 family - Top of rack) Products have already implemented these chips, following is the difference between the 3 generations : &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--e1MyTErB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/73k4c0rl5jsjkgbygnf7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--e1MyTErB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/73k4c0rl5jsjkgbygnf7.png" alt="Image description" width="880" height="317"&gt;&lt;/a&gt;&lt;em&gt;&lt;a href="https://www.intel.com/content/www/us/en/products/network-io/programmable-ethernet-switch/tofino-3-product-brochure.html"&gt;Intel Source Page&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  References :
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elegantnetwork.github.io/posts/A-Summary-of-Network-ASICs/"&gt;what are network ASICS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bm-switch.com/index.php/blog/whitebox_basics_programmable_fixed_asics/"&gt;White Boxes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nextplatform.com/2018/12/04/programmable-networks-get-a-bigger-foot-in-the-datacenter-door/"&gt;Datacenter ASICs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=n9bUEb1v0pU"&gt;inside a carrier Router/Switch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=Ti3t9OAZL3g&amp;amp;list=WL&amp;amp;index=45"&gt;Network ASICs - Deep Dive&lt;/a&gt; (Recommended)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.intel.com/content/www/us/en/products/network-io/programmable-ethernet-switch/tofino-3-product-brochure.html"&gt;Intel Tofino brochure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://packetpushers.net/chiplets-the-first-step-to-integrated-silicon-photonics-for-faster-interconnects-at-lower-cost/"&gt;Chiplets: The First Step To Integrated Silicon Photonics For Faster Interconnects At Lower Cost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cisco.com/c/dam/en/us/solutions/collateral/silicon-one/white-paper-sp-product-family.pdf"&gt;Cisco Silicon One Product Family&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=pRJZE0C77SQ"&gt;Pete Lumbis Asics for networking engineers&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>networks</category>
      <category>transport</category>
    </item>
    <item>
      <title>Huawei Cloud Engine Ansible</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Thu, 25 Aug 2022 09:35:00 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/huawei-cloud-engine-ansible-20jh</link>
      <guid>https://dev.to/amrelhusseiny/huawei-cloud-engine-ansible-20jh</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;I have been working with the Huawei Cloud Engine series of switches for the Data Center, and one of the great things I was introduced to is the efficient usage of Ansible+Netconf to configure Legacy network devices instead of the trial and error handling way of Python+SSH , which you had to anticipate the delay of the SSH session and to handle a console output using Regex which while very customizable , when it comes to production environments , your supervisors would much prefer a tried and tested technology backed up by the vendor itself .&lt;/p&gt;

&lt;h1&gt;
  
  
  what we will be discussing
&lt;/h1&gt;

&lt;p&gt;Here I will share the steps I was able to start my journey in configuring the Cloud Engine switches using Ansible .&lt;/p&gt;

&lt;h1&gt;
  
  
  Steps
&lt;/h1&gt;

&lt;p&gt;1st I would advise you to configure an EVE-NG Community Environment or a GNS3 environment so you are able to test your playbooks (Ansible) before deploying them to the production environment .&lt;/p&gt;

&lt;h2&gt;
  
  
  1- EVE-NG Installation :
&lt;/h2&gt;

&lt;p&gt;For my deployment , I will be using EVE NG , you can find the download page (&lt;a href="https://www.eve-ng.net/index.php/download/" rel="noopener noreferrer"&gt;https://www.eve-ng.net/index.php/download/&lt;/a&gt;) , download the Community version , as it won't require a retail license .&lt;/p&gt;

&lt;p&gt;You can download it as ISO to install or and OVF to run directly , for me , I am running it on ESXI machine .&lt;/p&gt;

&lt;p&gt;After you downloaded and installed EVE-NG , you should be able to reach the eve machine using SSH 1st to configure it , default SSH user is "root" and default password is "eve" .&lt;/p&gt;

&lt;p&gt;When you login to SSH , you will follow a series of configuration prompts for DNS , NTP and so on , after which you will be able to login to the EVE-NG Web portal to start using the Emulation software .&lt;/p&gt;

&lt;p&gt;On the Web portal , the default user is "admin" and password is "eve" .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9b7j4mc27dn954n577ud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9b7j4mc27dn954n577ud.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  2- Huawei Cloud Engine EVE Image :
&lt;/h1&gt;

&lt;p&gt;In order to work with EVE , you will have to use a preconfigured image , for our device , please follow the following link to download the Huawei CE12800 VM that we will use :&lt;br&gt;
&lt;a href="https://forum.huawei.com/enterprise/en/run-ce12800-ne40e-in-eve-ng/thread/653457-861" rel="noopener noreferrer"&gt;https://forum.huawei.com/enterprise/en/run-ce12800-ne40e-in-eve-ng/thread/653457-861&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  3- Our lab setup :
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcrpy6kzmg0aubhtfgq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcrpy6kzmg0aubhtfgq1.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you followed the above guide to add the Huawei Cloud Engine image to EVE , we will be able to create my lab setup :&lt;/p&gt;

&lt;h2&gt;
  
  
  A) Ansible Machine
&lt;/h2&gt;

&lt;p&gt;I created an ESXi CentOS machine to run the Ansible playbook from , you can install locally on your laptop or machine if you would like , we will be able to reach our Huawei switch from our local Home network .&lt;/p&gt;

&lt;h2&gt;
  
  
  B) On EVE Portal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add new Lab &lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to left side node , "Add an object -&amp;gt; Node -&amp;gt; search Huawei , you find Cloud Engine 12800" , click on it , you will need 2 GB of RAM/Memory reserved per switch to run it :&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsqri77pfiq5mv73r1s4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxsqri77pfiq5mv73r1s4.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next , to bridge the switch to our local Network , so we can access it from our local Laptop or in my case from my CentOS VM , you need to go to "Add an object -&amp;gt; Network -&amp;gt; Management (Cloud0) " , and connect one of the switches interface to the cloud (ex: GE1/0/0) , and right click on the switch then choose start :&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfxw0ctpdpwxn4r5ypux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmfxw0ctpdpwxn4r5ypux.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dinnsh69eh5wjek7dm6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7dinnsh69eh5wjek7dm6.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  C) Configuring Huawei Cloud Engine for Netconf :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hover over the device on EVE to see the IP and Port number you can console to the device using :
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4449xg6wprs81uuhe4xq.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;'$ telnet 192.168.1.109 32769'&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On device , paste the following configuration to add a user and start the Netconf Service : &lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

# Switch Configuration
system
!
interface GE 1/0/0
undo portswitch
undo shutdown 
ip address 192.168.1.130 24
quit
!
ip route-static 0.0.0.0 0 192.168.1.1 
!
netconf
protocol inbound ssh port 830
!
ssh user client001
!
aaa
local-user client001 password irreversible-cipher SetUesrPasswd@123
local-user client001 service-type ssh
quit
commit
!
ssh server cipher aes128_ctr aes256_ctr aes192_ctr aes128_gcm aes256_gcm
ssh user client001 authentication-type password
ssh user client001 service-type snetconf
!
snetconf server enable
!
commit
!
save


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;To confirm that you are able to reach network connectivity , ping your gateway and your Ansible hosting device : &lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&amp;lt;CloudEngine&amp;gt;ping &lt;span class="nt"&gt;-c&lt;/span&gt; 5 192.168.1.1 
  PING 192.168.1.1: 56  data bytes, press CTRL_C to &lt;span class="nb"&gt;break
    &lt;/span&gt;Reply from 192.168.1.1: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5 ms
    Reply from 192.168.1.1: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 ms
    Reply from 192.168.1.1: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 ms
    Reply from 192.168.1.1: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 ms
    Reply from 192.168.1.1: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 ms

  &lt;span class="nt"&gt;---&lt;/span&gt; 192.168.1.1 ping statistics &lt;span class="nt"&gt;---&lt;/span&gt;
    5 packet&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; transmitted
    5 packet&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; received
    0.00% packet loss
    round-trip min/avg/max &lt;span class="o"&gt;=&lt;/span&gt; 2/3/5 ms

&amp;lt;CloudEngine&amp;gt;ping &lt;span class="nt"&gt;-c&lt;/span&gt; 5 192.168.1.102 
  PING 192.168.1.102: 56  data bytes, press CTRL_C to &lt;span class="nb"&gt;break
    &lt;/span&gt;Reply from 192.168.1.102: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 ms
    Reply from 192.168.1.102: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 ms
    Reply from 192.168.1.102: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 ms
    Reply from 192.168.1.102: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 ms
    Reply from 192.168.1.102: &lt;span class="nv"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;56 &lt;span class="nv"&gt;Sequence&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5 &lt;span class="nv"&gt;ttl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;64 &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 ms

  &lt;span class="nt"&gt;---&lt;/span&gt; 192.168.1.102 ping statistics &lt;span class="nt"&gt;---&lt;/span&gt;
    5 packet&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; transmitted
    5 packet&lt;span class="o"&gt;(&lt;/span&gt;s&lt;span class="o"&gt;)&lt;/span&gt; received
    0.00% packet loss
    round-trip min/avg/max &lt;span class="o"&gt;=&lt;/span&gt; 1/2/4 ms


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;To test the Netconf before moving forward to ansible , from your laptop or Ansible hosting VM , run the following command , you should get a long XML output , this means that we are ready for ansible :
&lt;code&gt;$ ssh client001@192.168.1.130 -p 830 netconf&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  4- Setup of the Ansible machine:
&lt;/h1&gt;

&lt;p&gt;Following are the steps for a CentOS machine &lt;/p&gt;

&lt;h2&gt;
  
  
  A)Create a virtual Python environment:
&lt;/h2&gt;

&lt;p&gt;Recommended in the time of writing the article to use Python 3.8 and above.&lt;/p&gt;

&lt;p&gt;Create a virtual environment , in my case using Python 3.10 :&lt;br&gt;
&lt;code&gt;$ sudo /usr/local/bin/python3.10 -m venv huawei_venv&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Activate the created virtual environment , you will find the default Python version is the one you created it with .&lt;/p&gt;

&lt;p&gt;The Ansible module we will be using is part of the net_commons collection : &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="o"&gt;(&lt;/span&gt;huawei_venv&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;--version&lt;/span&gt;
Python 3.10.5

&lt;span class="c"&gt;# Install Ansible and needed libraries for the lab&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;huawei_venv&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; /usr/local/bin/python3.10  &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;ansible ansible-core ncclient jxmlease xmltodict ansible-pylibssh

&lt;span class="c"&gt;# Check Ansible version &lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;huawei_venv&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ansible &lt;span class="nt"&gt;--version&lt;/span&gt;
ansible &lt;span class="o"&gt;[&lt;/span&gt;core 2.13.3]
  config file &lt;span class="o"&gt;=&lt;/span&gt; None
  configured module search path &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'/home/amroashram/.ansible/plugins/modules'&lt;/span&gt;, &lt;span class="s1"&gt;'/usr/share/ansible/plugins/modules'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
  ansible python module location &lt;span class="o"&gt;=&lt;/span&gt; /usr/local/lib/python3.10/site-packages/ansible
  ansible collection location &lt;span class="o"&gt;=&lt;/span&gt; /home/amroashram/.ansible/collections:/usr/share/ansible/collections
  executable location &lt;span class="o"&gt;=&lt;/span&gt; /usr/local/bin/ansible
  python version &lt;span class="o"&gt;=&lt;/span&gt; 3.10.5 &lt;span class="o"&gt;(&lt;/span&gt;main, Aug  8 2022, 17:01:37&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;GCC 8.5.0 20210514 &lt;span class="o"&gt;(&lt;/span&gt;Red Hat 8.5.0-15&lt;span class="o"&gt;)]&lt;/span&gt;
  jinja version &lt;span class="o"&gt;=&lt;/span&gt; 3.1.2
  libyaml &lt;span class="o"&gt;=&lt;/span&gt; True

&lt;span class="c"&gt;# Double confirm that the Netcommons collection is installed &lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;huawei_venv&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ansible-galaxy collection &lt;span class="nb"&gt;install &lt;/span&gt;ansible.netcommon


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  B) lets create a simple Inventory and Playbook to run on our current switch :
&lt;/h2&gt;

&lt;p&gt;Inverntory.yaml&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# inventory.yaml&lt;/span&gt;
&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# ----- Variables for the whole inventory &lt;/span&gt;
  &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ansible_network_os&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;community.network.ce&lt;/span&gt;
    &lt;span class="na"&gt;ansible_user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;client001&lt;/span&gt;
    &lt;span class="na"&gt;ansible_password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SetUesrPasswd@123"&lt;/span&gt;
    &lt;span class="na"&gt;ansible_ssh_common_args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-o&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ProxyCommand="ssh&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-W&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;%h:%p&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-q&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bastion01"'&lt;/span&gt;
    &lt;span class="c1"&gt;# log_path: ansible.log &lt;/span&gt;

  &lt;span class="c1"&gt;# ----- Group names and relations to hosts &lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;huawei&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;leaf_1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;ansible_host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.1.130&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Playbook.yaml : will be adding a vlan (20) to the switch &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# Playbook.yaml&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;leaf_1&lt;/span&gt;
  &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ansible.netcommon.netconf&lt;/span&gt;
  &lt;span class="na"&gt;gather_facts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;no&lt;/span&gt;

  &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;add_VLAN&lt;/span&gt;
    &lt;span class="na"&gt;community.network.ce_vlan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;vlan_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;120&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;WEB_Vlan&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To run the playbook on the inventory :&lt;br&gt;
&lt;code&gt;$ ansible-playbook -i huawei_cloud_engine_inventory.yaml huawei_cloud_engine_playbook.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Output confirming change has been done as follows : &lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;br&gt;
 bash&lt;br&gt;
PLAY [test] ***********************************************************************************************************************************************&lt;br&gt;
skipping: no hosts matched

&lt;p&gt;PLAY RECAP ************************************************************************************************************************************************&lt;/p&gt;

&lt;p&gt;(huawei_venv) [amroashram@centos_proxy huawei_cloud_engine]$ ansible-playbook -i huawei_cloud_engine_inventory.yaml huawei_cloud_engine_playbook.yaml &lt;/p&gt;

&lt;p&gt;PLAY [test] ***********************************************************************************************************************************************&lt;/p&gt;

&lt;p&gt;TASK [add_VLAN] *******************************************************************************************************************************************&lt;br&gt;
changed: [leaf_1]&lt;/p&gt;

&lt;p&gt;PLAY RECAP ************************************************************************************************************************************************&lt;br&gt;
leaf_1                     : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 &lt;/p&gt;
&lt;h1&gt;
  
  
  On switch :
&lt;/h1&gt;

&lt;p&gt;&amp;lt;CloudEngine&amp;gt;display vlan &lt;/p&gt;
&lt;h2&gt;
  
  
  VID          Ports                                                          
&lt;/h2&gt;

&lt;p&gt;1         UT:GE1/0/1(D)      GE1/0/2(D)      GE1/0/3(D)      GE1/0/4(D)&lt;br&gt;&lt;br&gt;
                GE1/0/5(D)      GE1/0/6(D)      GE1/0/7(D)      GE1/0/8(D)&lt;br&gt;&lt;br&gt;
                GE1/0/9(D)&lt;br&gt;&lt;br&gt;
 120     &lt;/p&gt;
&lt;h2&gt;
  
  
  VID  Type     Status  Property  MAC-LRN STAT    BC  MC  UC  Description
&lt;/h2&gt;

&lt;p&gt;1 common   enable  default   enable  disable FWD FWD FWD VLAN 0001&lt;br&gt;&lt;br&gt;
 120 common   enable  default   enable  disable FWD FWD FWD hello    &lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Further Ansible capabilities&lt;br&gt;
&lt;/h1&gt;

&lt;p&gt;To check further usage of the netcommon collection with Cloud Engine , you have the following modules available to do changes on the switches : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handy command , if you do not know what a module does or how to use it in the Playbook , you can always use :
&lt;code&gt;$ ansible-doc community.network.ce_vlan&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Modules : refer back to link (&lt;a href="https://docs.ansible.com/ansible/latest/network/user_guide/platform_ce.html" rel="noopener noreferrer"&gt;https://docs.ansible.com/ansible/latest/network/user_guide/platform_ce.html&lt;/a&gt;) for up to date modules .
community.network.ce_aaa_server
community.network.ce_aaa_server_host
community.network.ce_acl
community.network.ce_acl_advance
community.network.ce_bfd_global
community.network.ce_bfd_session
community.network.ce_bfd_view
community.network.ce_bgp
community.network.ce_bgp_af
community.network.ce_bgp_neighbor
community.network.ce_bgp_neighbor_af
community.network.ce_dldp
community.network.ce_dldp_interface
community.network.ce_eth_trunk
community.network.ce_evpn_bd_vni
community.network.ce_file_copy
community.network.ce_info_center_debug
community.network.ce_info_center_global
community.network.ce_info_center_log
community.network.ce_info_center_trap
community.network.ce_interface
community.network.ce_interface_ospf
community.network.ce_ip_interface
community.network.ce_lacp
community.network.ce_link_status
community.network.ce_lldp
community.network.ce_lldp_interface
community.network.ce_mlag_config
community.network.ce_netconf
community.network.ce_ntp
community.network.ce_ospf
community.network.ce_ospf_vrf
community.network.ce_reboot
community.network.ce_sflow
community.network.ce_snmp_community
community.network.ce_snmp_target_host
community.network.ce_snmp_user
community.network.ce_static_route
community.network.ce_static_route_bfd
community.network.ce_switchport
community.network.ce_vlan
community.network.ce_vrf
community.network.ce_vrf_af
community.network.ce_vrf_interface
community.network.ce_vrrp
community.network.ce_vxlan_tunnel
community.network.ce_vxlan_vap&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  References :
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;EVE_NG Installation : &lt;a href="https://www.eve-ng.net/index.php/documentation/installation/virtual-machine-install/" rel="noopener noreferrer"&gt;https://www.eve-ng.net/index.php/documentation/installation/virtual-machine-install/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Huawei Cloud Engine EVE Image : &lt;a href="https://forum.huawei.com/enterprise/en/run-ce12800-ne40e-in-eve-ng/thread/653457-861" rel="noopener noreferrer"&gt;https://forum.huawei.com/enterprise/en/run-ce12800-ne40e-in-eve-ng/thread/653457-861&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Huawei Cloud Engine Netconf Configuration : &lt;a href="https://support.huawei.com/enterprise/en/doc/EDOC1100198823/4b902677/example-for-establishing-communication-between-the-nms-and-a-device-using-netconf" rel="noopener noreferrer"&gt;https://support.huawei.com/enterprise/en/doc/EDOC1100198823/4b902677/example-for-establishing-communication-between-the-nms-and-a-device-using-netconf&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Cloud Engine  Netcommons Collection Doc : &lt;a href="https://docs.ansible.com/ansible/latest/network/user_guide/platform_ce.html" rel="noopener noreferrer"&gt;https://docs.ansible.com/ansible/latest/network/user_guide/platform_ce.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Python 3.10 veneer : &lt;a href="https://docs.python.org/3/library/venv.html" rel="noopener noreferrer"&gt;https://docs.python.org/3/library/venv.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>huawei</category>
      <category>ansible</category>
      <category>network</category>
    </item>
    <item>
      <title>Python's Netmiko template</title>
      <dc:creator>Amr ElHusseiny</dc:creator>
      <pubDate>Sun, 17 Jul 2022 09:14:05 +0000</pubDate>
      <link>https://dev.to/amrelhusseiny/pythons-netmiko-template-25nc</link>
      <guid>https://dev.to/amrelhusseiny/pythons-netmiko-template-25nc</guid>
      <description>&lt;p&gt;The following is a ready to go netlike template , you just need to choose your way of authentication and the device type , you can find the supported devices on both the documentation and the Git for the Netmiko library :&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Netmiko Source Code :&lt;/strong&gt; &lt;a href="https://github.com/ktbyers/netmiko"&gt;Netmiko Github&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;API reference&lt;/strong&gt; &lt;em&gt;(must check for more functionality)&lt;/em&gt; : &lt;a href="https://ktbyers.github.io/netmiko/docs/netmiko/index.html"&gt;Netmiko Doc&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# netmiko_starter.py 
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;netmiko&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ConnectHandler&lt;/span&gt;

&lt;span class="n"&gt;device_dictionary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s"&gt;'device_type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'DEVICE_TYPE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
                    &lt;span class="s"&gt;'host'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'DEVICE_IP_ADDRESS'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'USERNAME'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;'password'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'PASSWORD'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="c1"&gt;# 'verbose': False ,
&lt;/span&gt;                    &lt;span class="c1"&gt;# 'session_log': 'log.txt', 
&lt;/span&gt;                    &lt;span class="c1"&gt;# 'global_delay_factor': 2, 
&lt;/span&gt;                &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;net_connect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConnectHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;device_dictionary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;net_connect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"show version"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;net_connect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Comments on the code :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;uncomment &lt;em&gt;verbose&lt;/em&gt; if you want to disable Netmiko's Logs .&lt;/li&gt;
&lt;li&gt;uncomment &lt;em&gt;session_log&lt;/em&gt; to debug the connection failures .&lt;/li&gt;
&lt;li&gt;uncomment _ global_delay_factor_ to add delay when waiting for commands output , very useful if the devices are slow , note that this is not in seconds but in multiple , so "2" mean multiply the default delay by 2 and so on &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more functionality , like the types of devices supported ,  please check the API docs .&lt;/p&gt;

&lt;p&gt;Also check the textfsm templates part of the guide , this helps a lot with parsing the output instead of using the normal Regex way , it supports a lot of well known devices outputs .&lt;/p&gt;

&lt;p&gt;good luck &lt;/p&gt;

</description>
      <category>netmiko</category>
      <category>python</category>
    </item>
  </channel>
</rss>
