<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[PacketNinjaLabs]]></title><description><![CDATA[Notes on Network Automation and Cloud]]></description><link>https://dev.packetninjalabs.com</link><image><url>https://substackcdn.com/image/fetch/$s_!7iMb!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad64e62-c602-48ee-8ba7-1beedf45c94e_1024x1024.png</url><title>PacketNinjaLabs</title><link>https://dev.packetninjalabs.com</link></image><generator>Substack</generator><lastBuildDate>Tue, 12 May 2026 10:54:09 GMT</lastBuildDate><atom:link href="https://dev.packetninjalabs.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Sean Wijetunga]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[packetninjalabs@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[packetninjalabs@substack.com]]></itunes:email><itunes:name><![CDATA[Sean Wijetunga]]></itunes:name></itunes:owner><itunes:author><![CDATA[Sean Wijetunga]]></itunes:author><googleplay:owner><![CDATA[packetninjalabs@substack.com]]></googleplay:owner><googleplay:email><![CDATA[packetninjalabs@substack.com]]></googleplay:email><googleplay:author><![CDATA[Sean Wijetunga]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Modernising Data Centre Fabrics with BGP EVPN VXLAN - Part 1]]></title><description><![CDATA[Building a Scalable, Multi-Tenant Proof of Concept Aligned with Arista Validated Designs]]></description><link>https://dev.packetninjalabs.com/p/modernising-data-centre-fabrics-with</link><guid isPermaLink="false">https://dev.packetninjalabs.com/p/modernising-data-centre-fabrics-with</guid><dc:creator><![CDATA[Sean Wijetunga]]></dc:creator><pubDate>Thu, 16 Oct 2025 09:39:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!0Ehj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Objective</h2><p>This proof of concept validates a modern data centre fabric built around <strong>BGP EVPN VXLAN with Symmetric IRB</strong>,  The goal was to prove that this architecture delivers predictable scalability, clean multi-tenancy, and a strong foundation for automation.</p><p>developed using Arista vEOS-lab version 4.33.1F, a major feature release that includes several EVPN/VXLAN and control-plane enhancements. Part of the reason for revisiting this build was to validate those improvements and assess how they impact large-scale EVPN fabrics.</p><p>The design remains aligned with <strong>Arista Validated Designs (AVD)</strong> and Cisco&#8217;s equivalent EVPN VXLAN model  focused on scalable multi-tenancy and automation readiness.</p><h2>Design Overview</h2><p>The fabric design uses a structured three-plane model to separate responsibility and simplify automation.<br>Underlay uses OSPF area 0 to provide fast, deterministic IP reachability between VTEPs. Overlay connectivity is handled via VXLAN, and the control plane runs BGP EVPN with route reflectors. Each tenant is represented by a dedicated VRF and L3VNI for scalable inter-VLAN routing.</p><h3>Fabric Design Summary</h3><p><strong>Underlay:</strong> OSPF area 0. Provides fast convergence and ECMP-based IP reachability. Overlay: VXLAN. Extends Layer 2 segments logically over the IP underlay. </p><p><strong>Control Plane:</strong> BGP EVPN (iBGP with Route Reflectors). Distributes MAC and IP reachability information across the fabric.</p><p><strong>Routing Model:</strong> Symmetric IRB. Isolates tenants using VRFs and L3VNIs, enabling scalable inter-VLAN routing.</p><p><strong>MTU:</strong> 9150 underlay / 1500 overlay. Ensures headroom for VXLAN encapsulation.</p><p><strong>Anycast Gateway:</strong> 192.168.X.1 (MAC 00:1c:73:00:00:99). Supports seamless host mobility and efficient ARP suppression.<br>Spines act purely as route reflectors and IP transit; leaves perform all routing and encapsulation as VTEPs.<br>The next stage will move toward an eBGP fabric using BFD for sub-second convergence and simplified fault isolation.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0Ehj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0Ehj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png 424w, https://substackcdn.com/image/fetch/$s_!0Ehj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png 848w, https://substackcdn.com/image/fetch/$s_!0Ehj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png 1272w, https://substackcdn.com/image/fetch/$s_!0Ehj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0Ehj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png" width="1327" height="1265" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1265,&quot;width&quot;:1327,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:264907,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://dev.packetninjalabs.com/i/176281381?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0Ehj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png 424w, https://substackcdn.com/image/fetch/$s_!0Ehj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png 848w, https://substackcdn.com/image/fetch/$s_!0Ehj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png 1272w, https://substackcdn.com/image/fetch/$s_!0Ehj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81ebc892-fcc0-487e-8fe9-2a9383ef1779_1327x1265.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">BGP EVPN VXLAN topology used for validation. Spines operate as route reflectors, while leaf nodes serve as VTEPs for Tenant A and Tenant B, connected via OSPF underlay and Anycast gateways.</figcaption></figure></div><h3>Control Plane - BGP EVPN</h3><p>Each leaf peers with both spines using loopback interfaces. BGP advertises Type-2 (MAC/IP), Type-3 (multicast), and Type-5 (prefix) routes to distribute reachability and routing information across the fabric.</p><pre><code><code>SW-2#sh run | sec bgp
router bgp 65000
   router-id 2.2.2.2
   neighbor EVPN-SPINES peer group
   neighbor EVPN-SPINES remote-as 65000
   neighbor EVPN-SPINES update-source Loopback0
   neighbor EVPN-SPINES send-community extended
   neighbor 10.0.0.14 peer group EVPN-SPINES
   neighbor 10.0.0.15 peer group EVPN-SPINES
   !
   vlan 10
      rd 65000:100010
      route-target both 65000:100010
      redistribute learned
   !
   vlan 20
      rd 65000:100020
      route-target both 65000:100020
      redistribute learned
   !
   address-family evpn
      neighbor EVPN-SPINES activate
   !
   vrf TENANT_A
      route-target import evpn 65000:100000
      route-target export evpn 65000:100000
      redistribute connected
   !
   vrf TENANT_B
      route-target import evpn 65000:200000
      route-target export evpn 65000:200000
      redistribute connected
SW-2#</code></code></pre><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ff_5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ff_5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png 424w, https://substackcdn.com/image/fetch/$s_!Ff_5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png 848w, https://substackcdn.com/image/fetch/$s_!Ff_5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png 1272w, https://substackcdn.com/image/fetch/$s_!Ff_5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ff_5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png" width="1047" height="220" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:220,&quot;width&quot;:1047,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:14442,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://dev.packetninjalabs.com/i/176281381?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Ff_5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png 424w, https://substackcdn.com/image/fetch/$s_!Ff_5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png 848w, https://substackcdn.com/image/fetch/$s_!Ff_5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png 1272w, https://substackcdn.com/image/fetch/$s_!Ff_5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feaf997b6-e50d-4cef-bb19-0b979bc42d62_1047x220.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><h3>Underlay Design</h3><p>The underlay uses OSPF area 0 for loopback and point-to-point reachability. ECMP provides multiple parallel paths, making the fabric resilient and predictable.</p><pre><code>SW-2#sh run | sec ospf 
interface Ethernet2
   ip ospf network point-to-point
   ip ospf area 0.0.0.0
interface Ethernet3
   ip ospf network point-to-point
   ip ospf area 0.0.0.0
interface Loopback0
   ip ospf area 0.0.0.0
router ospf 10
   max-lsa 12000
SW-2#</code></pre><h3>VXLAN Overview</h3><p>VXLAN forms the overlay transport between VTEPs. Each leaf acts as a VTEP, encapsulating traffic from locally attached hosts and decapsulating traffic from remote leaves.<br>The outer IP header carries the VTEP loopbacks, and the inner Ethernet frame remains untouched, preserving original VLAN tags.</p><pre><code>SW-1#<strong>sh run int vxlan1</strong>
interface Vxlan1
   vxlan source-interface Loopback0
   vxlan udp-port 4789
   vxlan vlan 10 vni 100010
   vxlan vrf TENNANT_A vni 100000
SW-1#

SW-2#<strong>sh run int vxlan1</strong>
interface Vxlan1
   vxlan source-interface Loopback0
   vxlan udp-port 4789
   vxlan vlan 10 vni 100010
   vxlan vlan 20 vni 100020
   vxlan vrf TENANT_A vni 100000
   vxlan vrf TENANT_B vni 200000
SW-2#
SW-3#<strong>sh run int vxlan1</strong>
interface Vxlan1
   vxlan source-interface Loopback0
   vxlan udp-port 4789
   vxlan vlan 20 vni 100020
   vxlan vrf TENANT_B vni 20000
SW-3#</code></pre><pre><code><strong>SW-1#sh vxlan vni</strong>
VNI to VLAN Mapping for Vxlan1
VNI          VLAN       Source       Interface       802.1Q Tag
------------ ---------- ------------ --------------- ----------
100010       10         static       Ethernet3       untagged  
                                     Ethernet4       untagged  
                                     Vxlan1          10        

VNI to dynamic VLAN Mapping for Vxlan1
VNI          VLAN       VRF             Source       
------------ ---------- --------------- ------------ 
100000       4097       TENANT_A       evpn         
!
SW-2#<strong>sh vxlan vni</strong>
VNI to VLAN Mapping for Vxlan1
VNI          VLAN       Source       Interface       802.1Q Tag
------------ ---------- ------------ --------------- ----------
100010       10         static       Ethernet1       untagged  
                                     Vxlan1          10        
100020       20         static       Ethernet4       untagged  
                                     Vxlan1          20        

VNI to dynamic VLAN Mapping for Vxlan1
VNI          VLAN       VRF             Source       
------------ ---------- --------------- ------------ 
20000        4094                       evpn         
100000       4097       TENANT_A       evpn         
200000       4098       TENANT_B       evpn         

SW-2#
!
SW-3#<strong>show vxlan vni</strong>
VNI to VLAN Mapping for Vxlan1
VNI          VLAN       Source       Interface       802.1Q Tag
------------ ---------- ------------ --------------- ----------
100020       20         static       Ethernet1       untagged  
                                     Vxlan1          20        

VNI to dynamic VLAN Mapping for Vxlan1
VNI         VLAN       VRF             Source       
----------- ---------- --------------- ------------ 
20000       4097       TENANT_B       evpn         

SW-3#
</code></pre><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!O21O!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!O21O!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png 424w, https://substackcdn.com/image/fetch/$s_!O21O!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png 848w, https://substackcdn.com/image/fetch/$s_!O21O!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png 1272w, https://substackcdn.com/image/fetch/$s_!O21O!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!O21O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png" width="1231" height="503" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:503,&quot;width&quot;:1231,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:33499,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://dev.packetninjalabs.com/i/176281381?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!O21O!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png 424w, https://substackcdn.com/image/fetch/$s_!O21O!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png 848w, https://substackcdn.com/image/fetch/$s_!O21O!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png 1272w, https://substackcdn.com/image/fetch/$s_!O21O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fb5e785-6ddc-43a5-acd3-79e20805be4d_1231x503.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">displays <strong>EVPN Route Type 2</strong> entries  the <strong>MAC/IP Advertisement routes</strong>.</figcaption></figure></div><p>0050.0000.0600 = Server6<br>0050.0000.0700 = Server7<br>0050.0000.0800 = Server8<br></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!weo9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!weo9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png 424w, https://substackcdn.com/image/fetch/$s_!weo9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png 848w, https://substackcdn.com/image/fetch/$s_!weo9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png 1272w, https://substackcdn.com/image/fetch/$s_!weo9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!weo9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png" width="1227" height="425" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:425,&quot;width&quot;:1227,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:30469,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://dev.packetninjalabs.com/i/176281381?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!weo9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png 424w, https://substackcdn.com/image/fetch/$s_!weo9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png 848w, https://substackcdn.com/image/fetch/$s_!weo9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png 1272w, https://substackcdn.com/image/fetch/$s_!weo9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d6c64d3-2d5d-4fbc-bfae-7eb15a3d2baf_1227x425.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><strong>EVPN Route Type 5</strong> entries (IP Prefix routes) that carry <strong>IPv4 prefixes</strong> inside BGP EVPN..</figcaption></figure></div><h3>Why Symmetric IRB </h3><p>Asymmetric IRB forces each leaf to know every subnet in every tenant. That scales poorly as VLAN count grows.</p><p>Symmetric IRB solves this by introducing a dedicated VRF and L3VNI per tenant. Each leaf advertises only its locally attached prefixes using Type-5 routes, dramatically reducing control-plane load and making routing predictable.</p><p>It also aligns perfectly with multi-tenant use cases and automation workflows.<br><br><strong>Next Steps</strong></p><p>The next iteration will focus on:</p><ol><li><p>Migrating from iBGP with route reflectors to eBGP with BFD for sub-second convergence.</p></li><li><p>Extending to a dual-site EVPN fabric with firewalls providing north-south traffic control.</p></li><li><p>Orchestrating configuration and verification through Ansible and CloudVision Studios.</p></li><li><p>Integrating streaming telemetry for continuous fabric health and visibility.</p></li></ol><p></p><p>This proof of concept demonstrates how a modern EVPN VXLAN fabric can be modular, scalable, and automation-ready.</p><p>It aligns with production best practices and provides a reproducible baseline for the next phase: dual-site orchestration and operational automation.</p><p><br></p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/subscribe?"><span>Subscribe now</span></a></p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/p/modernising-data-centre-fabrics-with/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/p/modernising-data-centre-fabrics-with/comments"><span>Leave a comment</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Why Parsing Network CLI Outputs Matters]]></title><description><![CDATA[Turning show commands into data for automation]]></description><link>https://dev.packetninjalabs.com/p/why-parsing-network-cli-outputs-matters</link><guid isPermaLink="false">https://dev.packetninjalabs.com/p/why-parsing-network-cli-outputs-matters</guid><dc:creator><![CDATA[Sean Wijetunga]]></dc:creator><pubDate>Tue, 23 Sep 2025 12:53:36 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7rbQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2><p>When most of us started in networking, the CLI was king. You typed <code>show ip interface brief</code>, skimmed the columns, and quickly spotted which interfaces were up or down. That works fine for a human staring at one device. But what happens when you need to check hundreds of devices automatically? That&#8217;s where things break down.</p><h2>The problem with CLI for automation</h2><p>CLI output is built for humans, not machines. It&#8217;s full of quirks like: Inconsistent spacing between columns Extra headers and banners Vendor-specific differences Take this Cisco example:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ywnM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ywnM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png 424w, https://substackcdn.com/image/fetch/$s_!ywnM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png 848w, https://substackcdn.com/image/fetch/$s_!ywnM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png 1272w, https://substackcdn.com/image/fetch/$s_!ywnM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ywnM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png" width="1150" height="219" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:219,&quot;width&quot;:1150,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:23475,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://dev.packetninjalabs.com/i/174335566?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ywnM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png 424w, https://substackcdn.com/image/fetch/$s_!ywnM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png 848w, https://substackcdn.com/image/fetch/$s_!ywnM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png 1272w, https://substackcdn.com/image/fetch/$s_!ywnM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50a7db7d-8f10-4ff5-acf3-94a219b49802_1150x219.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a></figure></div><p>Looks neat to the eye. But if you try to split this text in Python or feed it into Ansible, you&#8217;ll quickly run into spacing issues and unreliable parsing.</p><p><strong>The solution: structured data</strong><br></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7rbQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7rbQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png 424w, https://substackcdn.com/image/fetch/$s_!7rbQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png 848w, https://substackcdn.com/image/fetch/$s_!7rbQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png 1272w, https://substackcdn.com/image/fetch/$s_!7rbQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7rbQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png" width="415" height="317" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:317,&quot;width&quot;:415,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:13993,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://dev.packetninjalabs.com/i/174335566?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7rbQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png 424w, https://substackcdn.com/image/fetch/$s_!7rbQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png 848w, https://substackcdn.com/image/fetch/$s_!7rbQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png 1272w, https://substackcdn.com/image/fetch/$s_!7rbQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc32bc057-a5c2-4caf-9794-5ff785b4df47_415x317.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Now it&#8217;s easy to: </p><ul><li><p>Run consistency checks </p></li><li><p>Compare pre-change vs post-change state </p></li><li><p>Feed data directly into an Ansible inventory or Python script</p></li></ul><h2>Demo: parsing with Python</h2><p>Here&#8217;s a minimal parser that converts raw CLI text into JSON. It&#8217;s not production-grade, but it shows the concept.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!x5e1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!x5e1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png 424w, https://substackcdn.com/image/fetch/$s_!x5e1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png 848w, https://substackcdn.com/image/fetch/$s_!x5e1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png 1272w, https://substackcdn.com/image/fetch/$s_!x5e1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!x5e1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png" width="839" height="545" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:545,&quot;width&quot;:839,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:39317,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://dev.packetninjalabs.com/i/174335566?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!x5e1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png 424w, https://substackcdn.com/image/fetch/$s_!x5e1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png 848w, https://substackcdn.com/image/fetch/$s_!x5e1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png 1272w, https://substackcdn.com/image/fetch/$s_!x5e1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e8fd15f-ee6d-4567-a763-dc0477a217ef_839x545.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Connecting to Ansible</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TdTt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TdTt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png 424w, https://substackcdn.com/image/fetch/$s_!TdTt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png 848w, https://substackcdn.com/image/fetch/$s_!TdTt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png 1272w, https://substackcdn.com/image/fetch/$s_!TdTt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TdTt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5517541b-ac28-4065-84d8-56e59b4da831_437x231.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:11298,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://dev.packetninjalabs.com/i/174335566?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TdTt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png 424w, https://substackcdn.com/image/fetch/$s_!TdTt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png 848w, https://substackcdn.com/image/fetch/$s_!TdTt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png 1272w, https://substackcdn.com/image/fetch/$s_!TdTt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5517541b-ac28-4065-84d8-56e59b4da831_437x231.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Now Ansible can load this YAML file directly into a playbook to validate configs, generate reports, or even drive remediation.</p><h2>Key takeaways </h2><p>Raw CLI &#8800; automation-friendly </p><ul><li><p>Structured data (JSON/YAML) is the foundation for pipelines Even a simple Python script can make CLI data usable today </p></li><li><p>Later, can replace custom parsing with tools like TextFSM, pyATS, or Batfish </p></li></ul><p>Automation isn&#8217;t about abandoning the CLI. It&#8217;s about making the data behind the CLI useful at scale.</p><p></p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/subscribe?"><span>Subscribe now</span></a></p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/p/why-parsing-network-cli-outputs-matters/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/p/why-parsing-network-cli-outputs-matters/comments"><span>Leave a comment</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Backing Up Network Fabrics the Modern Way]]></title><description><![CDATA[Why I Needed More Than &#8220;Nightly Backups&#8221;]]></description><link>https://dev.packetninjalabs.com/p/backing-up-network-fabrics-the-modern</link><guid isPermaLink="false">https://dev.packetninjalabs.com/p/backing-up-network-fabrics-the-modern</guid><dc:creator><![CDATA[Sean Wijetunga]]></dc:creator><pubDate>Mon, 01 Sep 2025 15:30:47 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7iMb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad64e62-c602-48ee-8ba7-1beedf45c94e_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2><p>Config backups have always been part of running networks. Tools like RANCID solved the problem years ago by scraping configs and emailing diffs. That worked in smaller, slower-moving environments.</p><p>In my career supporting financial trading and data center networks, I learned the hard way that this approach does not hold up under pressure. Backups need to be more than nightly snapshots &#8212; they must be structured, reliable, auditable, and fast. That is why I started building <code>fabric-config-backup</code><a href="https://gitlab.com/packetninja-labs/fabric-config-backup">.</a></p><h3>Incidents That Shaped My Approach</h3><p><strong>Drift detection too slow</strong><br>During a trading floor maintenance window, an ACL line was removed on an edge firewall. The drift was only noticed hours later when FIX sessions began failing. By the time RANCID reported the config diff, orders had already been impacted. A pre/post snapshot pipeline would have caught this immediately.</p><p><strong>Format fragility</strong><br>On NX-OS 9.3(5), Cisco published <a href="https://bst.cloudapps.cisco.com/bugsearch/bug/CSCvu49769">CSCvu49769</a> where certain <code>show run</code> outputs omitted default interface commands. Tools scraping configs silently missed critical lines. This broke RANCID and other text-based systems, leaving blind spots in backups.</p><p><strong>Rollback gaps</strong><br>During a data center migration, configs needed to be rolled back. Only the previous night&#8217;s snapshot was available. This missed changes applied earlier in the day, forcing manual reconfiguration under pressure. With Git-integrated automation, a pre-change snapshot could have been taken seconds before the rollout</p><h2>Building a Better Approach</h2><p>I started simple: Python scripts with Netmiko and Scrapli. Over time, I expanded them to cover Arista EOS, Cisco NX-OS, and IOS. The goal was not just &#8220;get a file,&#8221; but to build a workflow:</p><ul><li><p><strong>Multi-vendor coverage</strong> &#8211; Arista, Cisco NX-OS, Cisco IOS in a single inventory</p></li><li><p><strong>Git integration</strong> &#8211; every backup as a commit, signed and timestamped</p></li><li><p><strong>Pre/post snapshots</strong> &#8211; automatic before a change, and again after</p></li><li><p><strong>Error handling</strong> &#8211; no silent failures, every issue is logged</p></li></ul><p>This is how <code>fabric-config-backup</code> was born.</p><h2>Compliance and Governance</h2><p>In critical industries, backups are compliance controls as much as operational safety nets.</p><ul><li><p><strong>Audit trails</strong> &#8211; immutable Git history, not just email diffs</p></li><li><p><strong>Automated checks</strong> &#8211; parse configs into JSON/YAML to enforce standards (AAA, SSH v2, SNMPv3)</p></li><li><p><strong>Regulatory evidence</strong> &#8211; PCI-DSS and SOX require proof that configs are captured and recoverable</p></li></ul><p>When an auditor asks for evidence, I can point to a Git repo rather than a mailbox.</p><h2>Opportunities Beyond Backups</h2><p>Once configs are versioned, new opportunities open up:</p><ul><li><p><strong>CI/CD validation</strong> &#8211; policy checks, security scans, and linting before rollout</p></li><li><p><strong>Baseline enforcement</strong> &#8211; compare against golden configs automatically</p></li><li><p><strong>Event-driven triggers</strong> &#8211; back up on change, not just on schedule</p></li><li><p><strong>Scale</strong> &#8211; async Scrapli sessions snapshot entire fabrics in seconds</p></li></ul><h2>Lessons From the Field</h2><ul><li><p>A migration rollback that used to take hours now takes minutes because snapshots are always there.</p></li><li><p>Bugs that once silently broke backups now raise clear exceptions.</p></li><li><p>Compliance audits are less stressful because history is verifiable and structured.</p></li></ul><p>These lessons are the result of years in environments where downtime is not an option.</p><p>Config backups are no longer just insurance. They are a foundation for compliance, for operational resilience, and for automation-driven excellence.</p><p><strong>Explore the project: <a href="https://gitlab.com/packetninja-labs/fabric-config-backup?utm_source=chatgpt.com">git.packetninjalabs.com/fabric-config-backup</a></strong></p><p></p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/subscribe?"><span>Subscribe now</span></a></p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/p/backing-up-network-fabrics-the-modern/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/p/backing-up-network-fabrics-the-modern/comments"><span>Leave a comment</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Building an Inventory as Code: One Device, One YAML]]></title><description><![CDATA[Turning network devices into structured data is the foundation for automation.]]></description><link>https://dev.packetninjalabs.com/p/building-an-inventory-as-code-one</link><guid isPermaLink="false">https://dev.packetninjalabs.com/p/building-an-inventory-as-code-one</guid><dc:creator><![CDATA[Sean Wijetunga]]></dc:creator><pubDate>Fri, 29 Aug 2025 22:33:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7iMb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad64e62-c602-48ee-8ba7-1beedf45c94e_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have managed networks long enough to know the pain of scattered documentation. IP addresses in spreadsheets, hostnames in a wiki, firewall rules in ticket comments. When you need to act quickly, that mess slows you down.</p><p>Automation only works if the source of truth is clean. That is why I am moving toward inventory as code. The idea is simple: every device has a file, written in YAML, stored in Git. That inventory then feeds Python scripts, Ansible playbooks, and eventually CI/CD pipelines.</p><h2>Why &#8220;one device, one YAML&#8221;</h2><p>Keeping one file per device makes it:</p><ul><li><p>Easy to read</p></li><li><p>Easy to review in Git (a small diff shows the change)</p></li><li><p>Easy to validate with a Python script or CI job</p></li></ul><p>It also lines up with how I already think about production changes: controlled, traceable, peer-reviewable.</p><h2>A basic example</h2><p>Here is a YAML file for a lab leaf switch:</p><pre><code><code>hostname: leaf1-lab
role: leaf
mgmt:
  ip: 10.0.0.21/24
interfaces:
  - { name: Eth1, peer: spine1, ip: 172.16.0.1/31 }
  - { name: Eth2, peer: spine2, ip: 172.16.0.3/31 }
</code></code></pre><p>And here is a short Python script that reads all device files and prints a summary:</p><pre><code><code>import glob, yaml

for f in glob.glob("inventories/lab/devices/*.yml"):
    data = yaml.safe_load(open(f))
    print(f"{data['hostname']:12} {data['mgmt']['ip']:15} {data['role']}")
</code></code></pre><p>Output:</p><pre><code><code>leaf1-lab    10.0.0.21/24    leaf
</code></code></pre><p>That is already useful. Instead of flipping through spreadsheets, I can generate a quick summary. Later I can build checks to catch duplicate IPs or missing fields.</p><h2>Where this goes next&#8230;</h2><ul><li><p>Python can use this data to generate configs or back up running configs.</p></li><li><p>Ansible can consume the same inventory to drive playbooks.</p></li><li><p>GitLab CI can lint these files and refuse a merge if something is invalid.</p></li><li><p>Terraform can connect the same mindset to cloud networking.</p></li></ul><p>This is how I see inventory as the first building block. Get it right, and everything else becomes easier.</p><p>Automation is not about replacing engineers. It is about making the data we already know repeatable and reliable. For me that starts with a simple rule: one device, one YAML.</p><p>Next I will show how I use Python to validate that inventory and stop bad data before it ever reaches production.</p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/subscribe?"><span>Subscribe now</span></a></p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/p/building-an-inventory-as-code-one/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/p/building-an-inventory-as-code-one/comments"><span>Leave a comment</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Why Network Engineers Should Learn Python Basics First]]></title><description><![CDATA[From VLANs to firewall rules, simple Python skills can transform everyday network tasks into automation building blocks.]]></description><link>https://dev.packetninjalabs.com/p/why-network-engineers-should-learn</link><guid isPermaLink="false">https://dev.packetninjalabs.com/p/why-network-engineers-should-learn</guid><dc:creator><![CDATA[Sean Wijetunga]]></dc:creator><pubDate>Fri, 29 Aug 2025 20:31:44 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!7iMb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ad64e62-c602-48ee-8ba7-1beedf45c94e_1024x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every network engineer eventually hits the same point. The job market has shifted. It is no longer enough to know spanning tree, BGP, and multicast inside out. Firms now expect you to understand automation as well.<br><br>I have spent most of my career in low-latency environments where stability and precision matter more than anything else. I can troubleshoot a data centre outage under pressure, I can build an EVPN fabric, I can handle multicast feeds for trading. I can also design and deploy firewalls where a single missed rule could block an exchange feed or expose a service. That background gives me discipline. What I am doing now is building the automation layer on top.</p><h2>Start simple, not complex</h2><p>It is tempting to jump into full frameworks like Ansible or Terraform straight away. The problem is that without the basics those tools feel like magic. You copy code from somewhere else, it works once, and then it breaks when you try to adapt it.</p><p>The smarter path is to start with the foundations of Python.</p><ul><li><p>Lists and dictionaries to represent VLANs, IP addresses, or firewall rules</p></li><li><p>Functions to wrap repeat logic into something reusable</p></li><li><p>File handling to read device inventories from YAML or JSON, or export Palo Alto rules into versioned files</p></li><li><p>Error handling to stop one offline device or one bad API call from crashing the whole run</p></li></ul><h2>A basic example</h2><p>This is one of the first exercises I tried: generate VLAN config from a list.</p><pre><code><code>vlans = [101, 102, 103]

for v in vlans:
    print(f"vlan {v}")
    print(f" name USER-{v}")
</code></code></pre><p>Output:</p><pre><code><code>vlan 101
 name USER-101
vlan 102
 name USER-102
vlan 103
 name USER-103</code></code></pre><p><strong>Example 2: Representing firewall rules as data</strong></p><pre><code><code>rules = [
    {"src": "10.1.1.0/24", "dst": "10.2.2.0/24", "action": "allow"},
    {"src": "0.0.0.0/0",    "dst": "10.2.2.100", "action": "deny"},
]

for r in rules:
    print(f"set rule from {r['src']} to {r['dst']} action {r['action']}")
</code></code></pre><p>Output:</p><pre><code><code>set rule from 10.1.1.0/24 to 10.2.2.0/24 action allow
set rule from 0.0.0.0/0 to 10.2.2.100 action deny
</code></code></pre><p>This is the same pattern. Instead of typing commands one by one, represent the intent in a list or dictionary and loop over it.</p><div><hr></div><p><strong>Example 3: Reading devices from YAML</strong></p><pre><code><code>import yaml

with open("devices.yml") as f:
    devices = yaml.safe_load(f)

for d in devices:
    print(f"{d['hostname']:10} {d['mgmt_ip']:15} {d['role']}")
</code></code></pre><p><em>devices.yml</em></p><pre><code><code>- hostname: leaf1
  mgmt_ip: 10.0.0.21
  role: leaf
- hostname: spine1
  mgmt_ip: 10.0.0.11
  role: spine
</code></code></pre><p>Output:</p><pre><code><code>leaf1      10.0.0.21      leaf
spine1     10.0.0.11      spine
</code></code></pre><p>Now the network is <strong>data first</strong>. That data can feed Python, Ansible, or Terraform.</p><p>The same idea applies to firewalls. Instead of VLANs in a list, imagine a list of security rules with source, destination, and action. Loop through them and you can generate Palo Alto rule syntax or API calls. One pattern, many uses.</p><p>if you are a network engineer wondering where to start with automation, start with Python basics. They are small enough to practice in an evening and powerful enough to carry you through the whole stack.</p><p>Next I will show how I build device inventories as code and why &#8220;one device, one YAML&#8221; is the foundation for everything that follows.</p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/subscribe?"><span>Subscribe now</span></a></p><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/p/why-network-engineers-should-learn/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/p/why-network-engineers-should-learn/comments"><span>Leave a comment</span></a></p><p></p>]]></content:encoded></item><item><title><![CDATA[Getting Started with Python for Networks]]></title><description><![CDATA[Notes on Network Automation and Cloud]]></description><link>https://dev.packetninjalabs.com/p/getting-started-with-python-for-networks</link><guid isPermaLink="false">https://dev.packetninjalabs.com/p/getting-started-with-python-for-networks</guid><dc:creator><![CDATA[Sean Wijetunga]]></dc:creator><pubDate>Fri, 29 Aug 2025 16:17:34 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!fdAH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have spent most of my career working in production networks where downtime is measured in money, not minutes. My background has been low-latency trading environments, Cisco and Arista data centres, and multicast feeds for market data. It is the kind of infrastructure where stability and speed matter.</p><p>That world teaches discipline with change control and deep knowledge of protocols. The job market now expects something more. Network engineers are expected to bring automation into the picture. For me, Python is the natural first step.</p><h2>Why Python?</h2><p>I am not learning Python to become a software developer. I am learning it because I want to do familiar network tasks faster and with fewer mistakes.</p><ul><li><p>Turn device inventories into data I can reuse</p></li><li><p>Parse CLI output without copy and paste gymnastics</p></li><li><p>Automate repeat jobs like backups and interface checks</p></li></ul><p>Python is also the base layer for the rest of the stack. Once I am confident with loops, data structures, and file handling, the same habits carry straight into Ansible for configuration management and Terraform for cloud networking.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fdAH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fdAH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!fdAH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!fdAH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!fdAH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fdAH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1600289,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://packetninjalabs.substack.com/i/172275015?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fdAH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!fdAH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!fdAH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!fdAH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4200fd6c-f4ed-4860-ba1d-4679d948758a_1536x1024.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p></p><h2>A small first step</h2><p>Here is the sort of script I started with. Nothing clever, just a loop through a list of devices to print their management IPs:</p><pre><code><code>devices = [
    {"hostname": "spine1", "mgmt_ip": "10.0.0.11"},
    {"hostname": "leaf1", "mgmt_ip": "10.0.0.21"},
]

for d in devices:
    print(f"{d['hostname']:10} {d['mgmt_ip']}")
</code></code></pre><p>Output:</p><pre><code><code>spine1     10.0.0.11
leaf1      10.0.0.21
</code></code></pre><p>It does not change the world, but it does something useful. I have turned information into structured data and looped over it. That is the foundation for every bit of network automation that comes next.</p><h2>What I am aiming for</h2><p>Short term:</p><ul><li><p>Build a clean inventory of devices in YAML</p></li><li><p>Use Python to read it and check basics like IP addresses, roles, and neighbours</p></li></ul><p>Medium term:</p><ul><li><p>Generate configs instead of writing them by hand</p></li><li><p>Back up running configs automatically</p></li><li><p>Wire this into GitLab CI so every change gets linted and validated</p></li><li><p>Start using Ansible playbooks for standard tasks like backups and VLANs</p></li></ul><p>Long term:</p><ul><li><p>Extend the automation mindset into cloud networking</p></li><li><p>Use Terraform to build VPCs and other cloud infra, while keeping on-prem and cloud consistent with Ansible</p></li><li><p>Add Kubernetes networking later on, because containers and CNI plugins are now part of the story for modern platforms</p></li></ul><p></p><p>This blog is where I will document that journey. I know the networks, that has been my career. Now I am adding the automation skills that the market increasingly demands.</p><p>Next up I will share why network engineers should start with Python basics and not jump straight into heavy frameworks.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe to PacketNinjaLabs and follow my journey in network automation, from trading networks to cloud-native</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://dev.packetninjalabs.com/p/getting-started-with-python-for-networks/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://dev.packetninjalabs.com/p/getting-started-with-python-for-networks/comments"><span>Leave a comment</span></a></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.linkedin.com/in/seansw/&quot;,&quot;text&quot;:&quot;Connect on LinkedIn&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.linkedin.com/in/seansw/"><span>Connect on LinkedIn</span></a></p>]]></content:encoded></item></channel></rss>