<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Routing on TurboVision</title>
    <link>https://turbovision.in6-addr.net/tags/routing/</link>
    <description>Recent content in Routing on TurboVision</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Tue, 21 Apr 2026 14:06:12 +0000</lastBuildDate>
    <atom:link href="https://turbovision.in6-addr.net/tags/routing/index.xml" rel="self" type="application/rss&#43;xml" />
    
    
    
    <item>
      <title>Linux Networking Series, Part 4: iproute2 and the Migration from ifconfig/route</title>
      <link>https://turbovision.in6-addr.net/linux/networking/linux-networking-series-part-4-iproute2-and-migration-from-ifconfig-route/</link>
      <pubDate>Wed, 09 Jun 2004 00:00:00 +0000</pubDate>
      <lastBuildDate>Wed, 09 Jun 2004 00:00:00 +0000</lastBuildDate>
      <guid>https://turbovision.in6-addr.net/linux/networking/linux-networking-series-part-4-iproute2-and-migration-from-ifconfig-route/</guid>
      <description>&lt;p&gt;Linux admins in 2004 usually have muscle memory for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ifconfig&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;route&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;netstat&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those tools build competent operators. They are not &amp;ldquo;bad.&amp;rdquo; They are simply limited for the routing complexity we run now.&lt;/p&gt;
&lt;p&gt;In 2004, &lt;code&gt;iproute2&lt;/code&gt; is no longer an exotic alternative. It is the modern Linux networking toolkit for serious routing, policy routing, QoS, and clearer operational introspection. Yet many systems and admins still cling to old habits because the old tools still appear to work for simple cases.&lt;/p&gt;
&lt;p&gt;This article is about that gap between technical capability and operational habit.&lt;/p&gt;
&lt;h2 id=&#34;why-iproute2-existed-at-all&#34;&gt;Why &lt;code&gt;iproute2&lt;/code&gt; existed at all&lt;/h2&gt;
&lt;p&gt;The old net-tools model was sufficient for straightforward host config:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;one address per interface&lt;/li&gt;
&lt;li&gt;one default route&lt;/li&gt;
&lt;li&gt;one routing table worldview&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As Linux networking use grew (multi-homing, policy routing, traffic shaping, tunnels, dynamic behavior), that worldview became restrictive.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;iproute2&lt;/code&gt; gave Linux a more expressive model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;richer route objects&lt;/li&gt;
&lt;li&gt;multiple routing tables&lt;/li&gt;
&lt;li&gt;policy rules (&lt;code&gt;ip rule&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;traffic control (&lt;code&gt;tc&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;cleaner, scriptable output patterns&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It aligned tooling with the kernel networking stack evolution rather than preserving older command ergonomics forever.&lt;/p&gt;
&lt;h2 id=&#34;first-shock-for-legacy-admins&#34;&gt;First shock for legacy admins&lt;/h2&gt;
&lt;p&gt;The first encounter with &lt;code&gt;iproute2&lt;/code&gt; often feels hostile to old habits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fewer tiny separate commands&lt;/li&gt;
&lt;li&gt;denser syntax&lt;/li&gt;
&lt;li&gt;object-oriented command style&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example mapping:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ifconfig&lt;/code&gt; -&amp;gt; &lt;code&gt;ip addr&lt;/code&gt; / &lt;code&gt;ip link&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;route&lt;/code&gt; -&amp;gt; &lt;code&gt;ip route&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arp&lt;/code&gt; -&amp;gt; &lt;code&gt;ip neigh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This felt like needless churn to many experienced operators. It was not. It was consolidation around a model that could grow.&lt;/p&gt;
&lt;h2 id=&#34;side-by-side-command-translations&#34;&gt;Side-by-side command translations&lt;/h2&gt;
&lt;p&gt;Bring interface up:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# old&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ifconfig eth0 up
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# iproute2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip link &lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; dev eth0 up&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Assign address:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# old&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ifconfig eth0 192.168.50.10 netmask 255.255.255.0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# iproute2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip addr add 192.168.50.10/24 dev eth0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Show routes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# old&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;route -n
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# iproute2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route show&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Add default route:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# old&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;route add default gw 192.168.50.1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# iproute2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route add default via 192.168.50.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ARP/neighbor view:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# old&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;arp -n
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# iproute2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip neigh show&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The migration is learnable quickly if teams focus on concepts, not command nostalgia.&lt;/p&gt;
&lt;h2 id=&#34;the-real-gain-policy-routing-and-multiple-tables&#34;&gt;The real gain: policy routing and multiple tables&lt;/h2&gt;
&lt;p&gt;This is where &lt;code&gt;iproute2&lt;/code&gt; stops being &amp;ldquo;new syntax&amp;rdquo; and becomes strategic.&lt;/p&gt;
&lt;p&gt;With old tools, complex multi-uplink and source-based routing policies were awkward or brittle.
With &lt;code&gt;iproute2&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;define multiple routing tables&lt;/li&gt;
&lt;li&gt;add rules selecting tables by source/interface/mark&lt;/li&gt;
&lt;li&gt;implement deterministic path selection for different traffic classes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Conceptual example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table 100: traffic from app subnet exits ISP-A
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table 200: traffic from backup subnet exits ISP-B
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;main table: local/default behavior
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip rule chooses table by source prefix&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For real operations, this means fewer hacks and clearer intent.&lt;/p&gt;
&lt;h2 id=&#34;tc-quality-of-service-stops-being-theoretical&#34;&gt;&lt;code&gt;tc&lt;/code&gt;: quality of service stops being theoretical&lt;/h2&gt;
&lt;p&gt;Another reason &lt;code&gt;iproute2&lt;/code&gt; matters is &lt;code&gt;tc&lt;/code&gt; (traffic control). Even basic shaping helps in constrained links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;protect interactive traffic&lt;/li&gt;
&lt;li&gt;prevent bulk transfers from killing latency-sensitive use&lt;/li&gt;
&lt;li&gt;improve perceived service quality without buying immediate bandwidth upgrades&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In small organizations, this can postpone expensive provider upgrades and reduce user pain during peak windows.&lt;/p&gt;
&lt;h2 id=&#34;structured-state-inspection&#34;&gt;Structured state inspection&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;iproute2&lt;/code&gt; output encourages richer state visibility:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip -s link
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip -s route
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip addr show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip rule show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route show table all&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This helped standardize troubleshooting playbooks. Instead of mixing tools with inconsistent formatting assumptions, teams could script around one family.&lt;/p&gt;
&lt;p&gt;Consistency lowers cognitive load during incidents.&lt;/p&gt;
&lt;h2 id=&#34;migration-strategy-that-minimized-outages&#34;&gt;Migration strategy that minimized outages&lt;/h2&gt;
&lt;p&gt;The practical migration plan we used:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;inventory all current &lt;code&gt;ifconfig&lt;/code&gt;/&lt;code&gt;route&lt;/code&gt; usage (scripts, docs, runbooks)&lt;/li&gt;
&lt;li&gt;map each behavior to &lt;code&gt;iproute2&lt;/code&gt; equivalent&lt;/li&gt;
&lt;li&gt;validate in staging host with reboot persistence tests&lt;/li&gt;
&lt;li&gt;migrate one role class at a time (gateway first, then server classes)&lt;/li&gt;
&lt;li&gt;keep translation cheat sheet for on-call staff&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The biggest failure mode was partial migration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;config done with one toolset&lt;/li&gt;
&lt;li&gt;troubleshooting done with another&lt;/li&gt;
&lt;li&gt;runbooks referencing old assumptions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mixed mental models create slow incidents.&lt;/p&gt;
&lt;h2 id=&#34;the-admin-habit-chapter-the-critical-one&#34;&gt;The admin habit chapter (the critical one)&lt;/h2&gt;
&lt;p&gt;You asked for a critical chapter on systems and admins keeping old habits. Here it is plainly:&lt;/p&gt;
&lt;h3 id=&#34;habit-inertia-is-normal&#34;&gt;Habit inertia is normal&lt;/h3&gt;
&lt;p&gt;Experienced admins trust what kept systems alive under pressure. That trust is earned. So resistance to tool migration is not laziness by default; it is risk management instinct.&lt;/p&gt;
&lt;h3 id=&#34;habit-inertia-becomes-harmful-when&#34;&gt;Habit inertia becomes harmful when:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;old tools hide important state you now need&lt;/li&gt;
&lt;li&gt;team training stalls on one-person knowledge islands&lt;/li&gt;
&lt;li&gt;script portability and clarity degrade&lt;/li&gt;
&lt;li&gt;incident resolution slows because docs and reality diverge&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;the-cultural-anti-pattern&#34;&gt;The cultural anti-pattern&lt;/h3&gt;
&lt;p&gt;&amp;ldquo;I know &lt;code&gt;ifconfig&lt;/code&gt; by heart, so we do not need &lt;code&gt;iproute2&lt;/code&gt;.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;That sentence optimizes for one operator&amp;rsquo;s comfort, not team reliability.&lt;/p&gt;
&lt;h3 id=&#34;what-worked-culturally&#34;&gt;What worked culturally&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;do not mock old-tool users; they kept systems alive&lt;/li&gt;
&lt;li&gt;teach concept-first, then command mappings&lt;/li&gt;
&lt;li&gt;publish one-page translation references&lt;/li&gt;
&lt;li&gt;run paired incident drills using new toolset&lt;/li&gt;
&lt;li&gt;require new runbooks in &lt;code&gt;iproute2&lt;/code&gt; terms while keeping legacy appendix temporarily&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You migrate people, not just scripts.&lt;/p&gt;
&lt;h2 id=&#34;systems-that-preserve-old-habits-by-design&#34;&gt;Systems that preserve old habits by design&lt;/h2&gt;
&lt;p&gt;Some environments unintentionally freeze old habits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;legacy init scripts untouched for years&lt;/li&gt;
&lt;li&gt;outdated distro docs copied forward&lt;/li&gt;
&lt;li&gt;vendor support pages still using net-tools examples&lt;/li&gt;
&lt;li&gt;no budgeted training windows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If leadership wants modern operational capability, training time must be scheduled, not wished into existence.&lt;/p&gt;
&lt;h2 id=&#34;a-realistic-migration-cheat-sheet&#34;&gt;A realistic migration cheat sheet&lt;/h2&gt;
&lt;p&gt;Teams adopted faster when we provided short &amp;ldquo;day-one&amp;rdquo; substitutions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ifconfig -a        -&amp;gt; ip addr show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;route -n           -&amp;gt; ip route show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;arp -n             -&amp;gt; ip neigh show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ifconfig eth0 up   -&amp;gt; ip link set eth0 up
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ifconfig eth0 down -&amp;gt; ip link set eth0 down&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then a &amp;ldquo;day-seven&amp;rdquo; set for advanced ops:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip rule show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route show table all
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip -s link
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tc qdisc show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tc -s qdisc show&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Small scaffolding prevents operator panic.&lt;/p&gt;
&lt;h2 id=&#34;practical-policy-routing-lab-multi-uplink-realism&#34;&gt;Practical policy-routing lab (multi-uplink realism)&lt;/h2&gt;
&lt;p&gt;To make &lt;code&gt;iproute2&lt;/code&gt; value obvious, run this practical lab:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;two uplinks, two source subnets&lt;/li&gt;
&lt;li&gt;deterministic egress by source network&lt;/li&gt;
&lt;li&gt;fallback default route in main table&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Conceptual setup:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;eth0: 192.168.10.1/24 (users)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;eth1: 192.168.20.1/24 (backups)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wan0: 203.0.113.2/30 via ISP-A
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wan1: 198.51.100.2/30 via ISP-B&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Policy intent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;user subnet exits ISP-A&lt;/li&gt;
&lt;li&gt;backup subnet exits ISP-B&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;High-level implementation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table 100 -&amp;gt; default via ISP-A
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table 200 -&amp;gt; default via ISP-B
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip rule from 192.168.10.0/24 lookup 100
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip rule from 192.168.20.0/24 lookup 200&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This scenario is where old &lt;code&gt;route&lt;/code&gt; mental models crack.
&lt;code&gt;iproute2&lt;/code&gt; expresses it naturally.&lt;/p&gt;
&lt;h2 id=&#34;route-policy-debugging-workflow&#34;&gt;Route policy debugging workflow&lt;/h2&gt;
&lt;p&gt;When policy routing misbehaves:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;inspect &lt;code&gt;ip rule show&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;inspect all tables (&lt;code&gt;ip route show table all&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;test path with source-specific probes&lt;/li&gt;
&lt;li&gt;capture packets at egress interfaces&lt;/li&gt;
&lt;li&gt;verify reverse path expectations upstream&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The critical insight is that main table correctness is insufficient when rules select non-main tables.&lt;/p&gt;
&lt;p&gt;Many teams lost days before adopting this workflow.&lt;/p&gt;
&lt;h2 id=&#34;tc-in-practical-operations-not-theory&#34;&gt;&lt;code&gt;tc&lt;/code&gt; in practical operations, not theory&lt;/h2&gt;
&lt;p&gt;Traffic control was often ignored because docs felt academic. In constrained-link environments, even simple shaping changed daily user experience.&lt;/p&gt;
&lt;p&gt;Typical goals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;keep SSH interactive under load&lt;/li&gt;
&lt;li&gt;keep VoIP/control traffic usable&lt;/li&gt;
&lt;li&gt;prevent backups or large downloads from saturating uplink&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even basic qdisc/class shaping with measured policy beat unmanaged link contention.&lt;/p&gt;
&lt;p&gt;The operational lesson:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if you cannot buy bandwidth today, shape contention intentionally.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;why-admins-kept-old-tools-despite-clear-advantages&#34;&gt;Why admins kept old tools despite clear advantages&lt;/h2&gt;
&lt;p&gt;A direct answer to your requested critical chapter:&lt;/p&gt;
&lt;h3 id=&#34;1-legacy-success-bias&#34;&gt;1) Legacy success bias&lt;/h3&gt;
&lt;p&gt;Admins who survived years of outages with net-tools developed justified trust in what they knew.&lt;/p&gt;
&lt;h3 id=&#34;2-documentation-lag&#34;&gt;2) Documentation lag&lt;/h3&gt;
&lt;p&gt;Team docs often referenced old commands, so training reinforced old habits.&lt;/p&gt;
&lt;h3 id=&#34;3-fear-of-hidden-regressions&#34;&gt;3) Fear of hidden regressions&lt;/h3&gt;
&lt;p&gt;When uptime is fragile, changing tooling feels risky even if architecture demands it.&lt;/p&gt;
&lt;h3 id=&#34;4-organizational-incentives&#34;&gt;4) Organizational incentives&lt;/h3&gt;
&lt;p&gt;Many teams rewarded incident firefighting more than preventive modernization.&lt;/p&gt;
&lt;p&gt;This encouraged short-term patching over model upgrades.&lt;/p&gt;
&lt;h2 id=&#34;what-leadership-got-wrong&#34;&gt;What leadership got wrong&lt;/h2&gt;
&lt;p&gt;Common management error:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Just switch scripts to new commands this quarter.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;That fails because command replacement is the smallest part of migration. The hard parts are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mental model migration&lt;/li&gt;
&lt;li&gt;runbook migration&lt;/li&gt;
&lt;li&gt;training and drills&lt;/li&gt;
&lt;li&gt;ownership and review practices&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Underfund those, and migration becomes fragile theater.&lt;/p&gt;
&lt;h2 id=&#34;a-stronger-migration-governance-model&#34;&gt;A stronger migration governance model&lt;/h2&gt;
&lt;p&gt;What worked in mature teams:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;declare migration objective in behavior terms (not syntax terms)&lt;/li&gt;
&lt;li&gt;define cutover criteria and rollback criteria&lt;/li&gt;
&lt;li&gt;assign migration owner + reviewer&lt;/li&gt;
&lt;li&gt;reserve training time in schedule&lt;/li&gt;
&lt;li&gt;close migration only when docs/runbooks are updated and practiced&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This model looks heavy and is lighter than recurring outages.&lt;/p&gt;
&lt;h2 id=&#34;example-script-refactor-from-net-tools-to-ip-model&#34;&gt;Example: script refactor from net-tools to &lt;code&gt;ip&lt;/code&gt; model&lt;/h2&gt;
&lt;p&gt;Old-style startup logic often interleaved concerns:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ifconfig
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;route add
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ifconfig alias
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;route change
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;arp tweaks&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Refactored style separated concerns:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;01-link-up
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;02-addressing
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;03-main-route
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;04-policy-rules
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;05-table-routes
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;06-validation&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Separation made failure points obvious and rollback cleaner.&lt;/p&gt;
&lt;h2 id=&#34;validation-commands-we-standardized&#34;&gt;Validation commands we standardized&lt;/h2&gt;
&lt;p&gt;After migration scripts ran, we captured:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip addr show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip link show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip rule show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route show table main
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route show table all&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;And in dual-uplink hosts:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route get 8.8.8.8 from 192.168.10.10
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route get 8.8.8.8 from 192.168.20.10&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This directly validated source-policy behavior.&lt;/p&gt;
&lt;h2 id=&#34;case-study-backup-traffic-stealing-business-bandwidth&#34;&gt;Case study: backup traffic stealing business bandwidth&lt;/h2&gt;
&lt;p&gt;A mid-size office had nightly backups crossing same uplink as daytime business traffic. Even after-hours windows overlapped with distributed teams.&lt;/p&gt;
&lt;p&gt;Old world:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;static routes looked fine&lt;/li&gt;
&lt;li&gt;user complaints intermittent&lt;/li&gt;
&lt;li&gt;no deterministic steering&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After &lt;code&gt;iproute2&lt;/code&gt; + basic &lt;code&gt;tc&lt;/code&gt; rollout:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;backup traffic pinned to secondary uplink path&lt;/li&gt;
&lt;li&gt;interactive latency stabilized&lt;/li&gt;
&lt;li&gt;support tickets dropped&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No hardware miracle. Just better control-plane expression.&lt;/p&gt;
&lt;h2 id=&#34;case-study-asymmetric-routing-and-stateful-firewall-pain&#34;&gt;Case study: asymmetric routing and stateful firewall pain&lt;/h2&gt;
&lt;p&gt;Another deployment had two uplinks and stateful firewalling. Return traffic asymmetry caused hard-to-reproduce failures.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;iproute2&lt;/code&gt; policy routing plus explicit mark/rule documentation fixed this by enforcing consistent path selection for critical flows.&lt;/p&gt;
&lt;p&gt;The key was cross-tool alignment:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;marks from firewall path&lt;/li&gt;
&lt;li&gt;rules selecting correct tables&lt;/li&gt;
&lt;li&gt;routes matching intended egress&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without joint documentation, each team fixed &amp;ldquo;their part&amp;rdquo; and system remained broken.&lt;/p&gt;
&lt;h2 id=&#34;training-format-that-converted-skeptics&#34;&gt;Training format that converted skeptics&lt;/h2&gt;
&lt;p&gt;The most effective training was not slides. It was live comparison labs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;reproduce fault under old troubleshooting model&lt;/li&gt;
&lt;li&gt;diagnose with &lt;code&gt;iproute2&lt;/code&gt; visibility&lt;/li&gt;
&lt;li&gt;compare time-to-root-cause&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Skeptics converted when they saw 30-minute mysteries become 5-minute checks.&lt;/p&gt;
&lt;h2 id=&#34;de-risking-migration-in-production-windows&#34;&gt;De-risking migration in production windows&lt;/h2&gt;
&lt;p&gt;In high-risk environments, we used canary hosts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;migrate one representative host class&lt;/li&gt;
&lt;li&gt;run for two full business cycles&lt;/li&gt;
&lt;li&gt;review incidents and false assumptions&lt;/li&gt;
&lt;li&gt;only then expand&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This prevented organization-wide outages from one mistaken assumption about legacy behavior.&lt;/p&gt;
&lt;h2 id=&#34;long-term-payoff&#34;&gt;Long-term payoff&lt;/h2&gt;
&lt;p&gt;Teams that migrate thoroughly gain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;faster incident diagnosis&lt;/li&gt;
&lt;li&gt;cleaner multi-path architecture support&lt;/li&gt;
&lt;li&gt;easier migration to more complex policy stacks and observability tooling&lt;/li&gt;
&lt;li&gt;less dependence on one &amp;ldquo;legendary&amp;rdquo; admin&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is the operational return on investing in model upgrades.&lt;/p&gt;
&lt;h2 id=&#34;what-to-do-if-your-team-is-still-split&#34;&gt;What to do if your team is still split&lt;/h2&gt;
&lt;p&gt;If half your team still clings to old commands in critical runbooks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;do not force immediate ban&lt;/li&gt;
&lt;li&gt;require dual notation temporarily&lt;/li&gt;
&lt;li&gt;set sunset date for old notation&lt;/li&gt;
&lt;li&gt;run drills using only new notation before sunset&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Soft transition with hard deadline works better than symbolic mandates with no follow-through.&lt;/p&gt;
&lt;h2 id=&#34;appendix-migration-workshop-for-mixed-skill-teams&#34;&gt;Appendix: migration workshop for mixed-skill teams&lt;/h2&gt;
&lt;p&gt;This workshop format helped teams move from command translation to model migration.&lt;/p&gt;
&lt;h3 id=&#34;session-1-model-first-refresher&#34;&gt;Session 1: model-first refresher&lt;/h3&gt;
&lt;p&gt;Focus:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;link state vs addressing vs routing vs policy routing&lt;/li&gt;
&lt;li&gt;where each &lt;code&gt;ip&lt;/code&gt; subcommand provides evidence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Required outputs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;each participant explains packet path for three scenarios:
&lt;ul&gt;
&lt;li&gt;local service inbound&lt;/li&gt;
&lt;li&gt;host outbound&lt;/li&gt;
&lt;li&gt;source-based policy route&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;session-2-command-translation-with-intent&#34;&gt;Session 2: command translation with intent&lt;/h3&gt;
&lt;p&gt;Instead of &amp;ldquo;memorize replacements,&amp;rdquo; we mapped old tasks to new intents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;show me host identity&amp;rdquo; -&amp;gt; &lt;code&gt;ip addr&lt;/code&gt;, &lt;code&gt;ip link&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;show me path decision&amp;rdquo; -&amp;gt; &lt;code&gt;ip route&lt;/code&gt;, &lt;code&gt;ip rule&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;show me neighbor resolution&amp;rdquo; -&amp;gt; &lt;code&gt;ip neigh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Participants then wrote short runbook snippets in new format.&lt;/p&gt;
&lt;h3 id=&#34;session-3-failure-simulation-lab&#34;&gt;Session 3: failure simulation lab&lt;/h3&gt;
&lt;p&gt;Injected failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;missing rule in policy table&lt;/li&gt;
&lt;li&gt;wrong route in non-main table&lt;/li&gt;
&lt;li&gt;interface up but address missing&lt;/li&gt;
&lt;li&gt;stale docs pointing to old commands&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Goal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;teach operators to diagnose with &lt;code&gt;iproute2&lt;/code&gt; first&lt;/li&gt;
&lt;li&gt;demonstrate why old command checks can be incomplete&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;session-4-production-rollout-rehearsal&#34;&gt;Session 4: production rollout rehearsal&lt;/h3&gt;
&lt;p&gt;Participants rehearsed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;pre-change checks&lt;/li&gt;
&lt;li&gt;change apply&lt;/li&gt;
&lt;li&gt;validation matrix&lt;/li&gt;
&lt;li&gt;rollback execution&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This reduced fear and improved consistency in real maintenance windows.&lt;/p&gt;
&lt;h2 id=&#34;documentation-template-we-standardized&#34;&gt;Documentation template we standardized&lt;/h2&gt;
&lt;p&gt;For each host role, docs included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;interface map&lt;/li&gt;
&lt;li&gt;addressing model&lt;/li&gt;
&lt;li&gt;route table usage&lt;/li&gt;
&lt;li&gt;policy routing rule priorities&lt;/li&gt;
&lt;li&gt;ownership and contact&lt;/li&gt;
&lt;li&gt;command reference for diagnosis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most valuable addition was &amp;ldquo;rule priority explanation.&amp;rdquo; Without it, teams struggled to reason about why packets followed one table instead of another.&lt;/p&gt;
&lt;h2 id=&#34;operational-anti-pattern-partial-modernization&#34;&gt;Operational anti-pattern: partial modernization&lt;/h2&gt;
&lt;p&gt;Partial modernization looked like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;scripts use &lt;code&gt;iproute2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;on-call runbooks still use old net-tools commands&lt;/li&gt;
&lt;li&gt;incident handoff language remains old model&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Result:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;confusion under stress&lt;/li&gt;
&lt;li&gt;contradictory diagnostics&lt;/li&gt;
&lt;li&gt;slower MTTR&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fix:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;migrate scripts and runbooks together&lt;/li&gt;
&lt;li&gt;run drills enforcing new command set&lt;/li&gt;
&lt;li&gt;retire old references on explicit schedule&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;metrics-proving-migration-value&#34;&gt;Metrics proving migration value&lt;/h2&gt;
&lt;p&gt;To justify migration effort, we tracked:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mean-time-to-diagnose route incidents&lt;/li&gt;
&lt;li&gt;number of incidents requiring senior-only intervention&lt;/li&gt;
&lt;li&gt;change-window rollback frequency&lt;/li&gt;
&lt;li&gt;policy-routing related outage count&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Teams with full adoption showed clear MTTR reductions because diagnostics were more complete and less ambiguous.&lt;/p&gt;
&lt;h2 id=&#34;executive-argument-that-worked&#34;&gt;Executive argument that worked&lt;/h2&gt;
&lt;p&gt;When leadership asked &amp;ldquo;why spend time on this now,&amp;rdquo; the strongest answer was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this reduces outage cost and dependency on single experts&lt;/li&gt;
&lt;li&gt;this prepares us for next-step networking stack evolution&lt;/li&gt;
&lt;li&gt;this lowers incident response variance across shifts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Framing migration as reliability investment, not command preference, secured support faster.&lt;/p&gt;
&lt;h2 id=&#34;incident-story-old-command-success-real-failure&#34;&gt;Incident story: old command success, real failure&lt;/h2&gt;
&lt;p&gt;We had an outage where a host looked &amp;ldquo;fine&amp;rdquo; under old checks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ifconfig&lt;/code&gt; showed address up&lt;/li&gt;
&lt;li&gt;&lt;code&gt;route -n&lt;/code&gt; showed expected default route&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yet traffic for one source subnet took wrong uplink.&lt;/p&gt;
&lt;p&gt;Root cause:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;policy routing rule drift (&lt;code&gt;ip rule&lt;/code&gt;) not covered by legacy checks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;ifconfig&lt;/code&gt; and &lt;code&gt;route&lt;/code&gt; were not lying; they were incomplete for the architecture in use.&lt;/p&gt;
&lt;p&gt;That incident ended the &amp;ldquo;old tools are enough&amp;rdquo; debate in that team.&lt;/p&gt;
&lt;h2 id=&#34;script-modernization-principles&#34;&gt;Script modernization principles&lt;/h2&gt;
&lt;p&gt;When rewriting old network scripts, we followed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;no one-to-one syntax obsession; express intent cleanly&lt;/li&gt;
&lt;li&gt;idempotent operations where possible&lt;/li&gt;
&lt;li&gt;explicit error handling and logging&lt;/li&gt;
&lt;li&gt;clear rollback snippets&lt;/li&gt;
&lt;li&gt;one command group per concern (link, addr, route, rule, tc)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This turned brittle startup scripts into maintainable operations code.&lt;/p&gt;
&lt;h2 id=&#34;documentation-update-pattern&#34;&gt;Documentation update pattern&lt;/h2&gt;
&lt;p&gt;Do not migrate tooling without migrating docs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;runbooks&lt;/li&gt;
&lt;li&gt;onboarding notes&lt;/li&gt;
&lt;li&gt;troubleshooting checklists&lt;/li&gt;
&lt;li&gt;architecture diagrams&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If docs keep old commands only, team behavior reverts under stress.&lt;/p&gt;
&lt;p&gt;We kept a transition period with &amp;ldquo;old/new side-by-side,&amp;rdquo; then removed old references after training cycles.&lt;/p&gt;
&lt;h2 id=&#34;why-this-mattered-beyond-networking-teams&#34;&gt;Why this mattered beyond networking teams&lt;/h2&gt;
&lt;p&gt;As Linux moved deeper into infrastructure roles, networking complexity became cross-team concern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;app teams needed route/policy context for troubleshooting&lt;/li&gt;
&lt;li&gt;operations teams needed deterministic multi-path behavior&lt;/li&gt;
&lt;li&gt;security teams needed clearer enforcement narratives&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;iproute2&lt;/code&gt; helped because it gave a better language for the system as it actually worked.&lt;/p&gt;
&lt;p&gt;Shared language improves shared accountability.&lt;/p&gt;
&lt;h2 id=&#34;practical-command-patterns-worth-standardizing&#34;&gt;Practical command patterns worth standardizing&lt;/h2&gt;
&lt;p&gt;To keep teams aligned, we standardized a compact command set for daily operations.&lt;/p&gt;
&lt;h3 id=&#34;daily-health-snapshot&#34;&gt;Daily health snapshot&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip -brief link
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip -brief addr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route show&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;advanced-path-snapshot-multi-table-hosts&#34;&gt;Advanced path snapshot (multi-table hosts)&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip rule show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route show table all
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route get 1.1.1.1 from &amp;lt;source-ip&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;neighbor-sanity&#34;&gt;Neighbor sanity&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip neigh show&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The value here is consistency. If every operator runs different checks, incident handoff quality drops.&lt;/p&gt;
&lt;h2 id=&#34;migration-completion-checklist&#34;&gt;Migration completion checklist&lt;/h2&gt;
&lt;p&gt;A host was considered fully migrated only when:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;startup scripts use &lt;code&gt;iproute2&lt;/code&gt; natively&lt;/li&gt;
&lt;li&gt;troubleshooting runbooks use &lt;code&gt;iproute2&lt;/code&gt; commands first&lt;/li&gt;
&lt;li&gt;on-call drills executed successfully with new command set&lt;/li&gt;
&lt;li&gt;docs no longer rely on net-tools primary examples&lt;/li&gt;
&lt;li&gt;one full reboot cycle verified no behavioral drift&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This prevented &amp;ldquo;script migration done, operations migration incomplete&amp;rdquo; outcomes.&lt;/p&gt;
&lt;h2 id=&#34;closing-note-on-admin-habits&#34;&gt;Closing note on admin habits&lt;/h2&gt;
&lt;p&gt;Admin habits are not a side issue. They are the operating system of infrastructure teams.&lt;/p&gt;
&lt;p&gt;If habit migration is ignored:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;old command reflexes return under stress&lt;/li&gt;
&lt;li&gt;diagnostics become inconsistent&lt;/li&gt;
&lt;li&gt;toolchain upgrades fail socially before they fail technically&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If habit migration is planned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;new tooling becomes normal quickly&lt;/li&gt;
&lt;li&gt;on-call quality evens out across shifts&lt;/li&gt;
&lt;li&gt;next migrations cost less&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is why this chapter belongs in technical documentation: technical correctness and behavioral adoption are inseparable in production operations.&lt;/p&gt;
&lt;h2 id=&#34;case-study-weekend-branch-cutover-with-policy-routing&#34;&gt;Case study: weekend branch cutover with policy routing&lt;/h2&gt;
&lt;p&gt;A practical branch cutover shows why this migration is worth doing properly.&lt;/p&gt;
&lt;p&gt;Starting state:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;branch office uses one old script set based on &lt;code&gt;ifconfig&lt;/code&gt; and &lt;code&gt;route&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;central office expects source-based routing behavior for specific traffic&lt;/li&gt;
&lt;li&gt;on-call team has mixed command habits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Friday pre-check:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;baseline snapshots captured with both old and new views&lt;/li&gt;
&lt;li&gt;routing intent documented in plain language before any command edits&lt;/li&gt;
&lt;li&gt;rollback plan tested on staging host&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Saturday change window:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;link/address migration to &lt;code&gt;ip&lt;/code&gt; command model&lt;/li&gt;
&lt;li&gt;table/rule migration to explicit &lt;code&gt;ip rule&lt;/code&gt; and table entries&lt;/li&gt;
&lt;li&gt;validation from representative branch hosts&lt;/li&gt;
&lt;li&gt;remote handover dry-run with night shift operator&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Observed result:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;one source subnet still took wrong path during early test&lt;/li&gt;
&lt;li&gt;issue isolated quickly because &lt;code&gt;ip rule show&lt;/code&gt; and &lt;code&gt;ip route get&lt;/code&gt; evidence was already part of the runbook&lt;/li&gt;
&lt;li&gt;fix applied in minutes instead of guesswork hours&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sunday closeout:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reboot validation complete&lt;/li&gt;
&lt;li&gt;documentation updated&lt;/li&gt;
&lt;li&gt;old net-tools references retired for this branch&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key lesson is operational, not syntactic: when model, commands, and runbook language align, migration incidents become short and teachable.&lt;/p&gt;
&lt;h2 id=&#34;appendix-communication-kit-for-migration-leads&#34;&gt;Appendix: communication kit for migration leads&lt;/h2&gt;
&lt;p&gt;When leading migration in mixed-experience teams, communication quality often determined success more than technical complexity.&lt;/p&gt;
&lt;p&gt;We used three recurring messages:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;ldquo;We are preserving behavior while improving model clarity.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;We are not deleting your old knowledge; we are extending it.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Every change has a tested rollback.&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That framing reduced defensive pushback and increased participation.&lt;/p&gt;
&lt;h2 id=&#34;sunset-checklist-for-old-net-tools-references&#34;&gt;Sunset checklist for old net-tools references&lt;/h2&gt;
&lt;p&gt;Before declaring migration complete, verify:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;no primary runbook relies on &lt;code&gt;ifconfig&lt;/code&gt;/&lt;code&gt;route&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;onboarding guide teaches &lt;code&gt;iproute2&lt;/code&gt; first&lt;/li&gt;
&lt;li&gt;escalation templates use &lt;code&gt;ip&lt;/code&gt; command outputs&lt;/li&gt;
&lt;li&gt;incident postmortems reference &lt;code&gt;iproute2&lt;/code&gt; evidence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Until these are true, cultural migration is incomplete even if scripts are modernized.&lt;/p&gt;
&lt;h2 id=&#34;quick-reference-routing-diagnostics-iproute2-era&#34;&gt;Quick-reference routing diagnostics (iproute2 era)&lt;/h2&gt;
&lt;p&gt;When in doubt, run this compact sequence:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip -brief addr
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip rule show
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route show table all
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ip route get &amp;lt;target-ip&amp;gt; from &amp;lt;source-ip&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This four-command sequence resolved most policy-routing incidents faster than mixed legacy checks because it exposes address state, rule selection, table contents, and effective path decision in one pass.&lt;/p&gt;
&lt;h2 id=&#34;closing-migration-metric&#34;&gt;Closing migration metric&lt;/h2&gt;
&lt;p&gt;A reliable sign that migration succeeded is when on-call responders stop saying &amp;ldquo;I know the old way, but&amp;hellip;&amp;rdquo; and start saying &amp;ldquo;here is the path decision and evidence.&amp;rdquo; Language shift is architecture shift.&lt;/p&gt;
&lt;p&gt;That language change is easy to observe in shift handovers and postmortems. When responders naturally reference &lt;code&gt;ip rule&lt;/code&gt;, route tables, and path decisions instead of translating from old command habits, you can trust that the migration is real.&lt;/p&gt;
&lt;p&gt;This language shift is not cosmetic. It signals that operators are now reasoning in terms the system actually uses. When teams describe incidents with accurate model language, handovers improve, root-cause cycles shorten, and corrective actions become more precise. In other words, tooling migration is complete only when diagnostic language, documentation, and decision-making vocabulary all align with the new model.&lt;/p&gt;
&lt;p&gt;Seen this way, &lt;code&gt;iproute2&lt;/code&gt; migration is a long-term investment in operational clarity. The command family provides richer state visibility, but the real value appears when teams standardize how they think, speak, and decide under pressure.&lt;/p&gt;
&lt;p&gt;That operational clarity also reduces everyday risk immediately. Teams that complete this shift document cleaner runbooks, hand over incidents faster, and spend less time on command-translation confusion during outages. That is already enough return for a migration project.&lt;/p&gt;
&lt;h2 id=&#34;recommendations-for-teams-still-on-old-habits&#34;&gt;Recommendations for teams still on old habits&lt;/h2&gt;
&lt;p&gt;If your team is still mostly net-tools:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;start with observation commands (&lt;code&gt;ip addr/route/neigh&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;convert new scripts to &lt;code&gt;iproute2&lt;/code&gt; first&lt;/li&gt;
&lt;li&gt;introduce policy routing concepts early, even if simple now&lt;/li&gt;
&lt;li&gt;train on-call rotation with practical drills&lt;/li&gt;
&lt;li&gt;retire old-command primary docs within a defined timeline&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Do not wait for a major outage to justify the migration.&lt;/p&gt;
&lt;h2 id=&#34;postscript-the-migration-inside-the-migration&#34;&gt;Postscript: the migration inside the migration&lt;/h2&gt;
&lt;p&gt;The visible migration is command tooling. The deeper migration is organizational reasoning. Teams move from &amp;ldquo;what command did we use last time?&amp;rdquo; to &amp;ldquo;what path decision does the system make and why?&amp;rdquo; That shift improves incident quality more than syntax changes alone. In practice, the &lt;code&gt;iproute2&lt;/code&gt; era is where many Linux shops first develop a clearer networking operations language: tables, rules, intent, and evidence. Keeping that language coherent in runbooks and handovers makes daily operations calmer and safer.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
