Same Job, Different Shell Part 4: Routing Tables

Once you know an interface’s own address (Part 3), the next diagnostic question is almost always “where does traffic from here actually go.” A routing table answers that, and reading one is one of the few commands in this series where the underlying concept, not just the syntax, differs slightly between platforms.

Linux: ip route

$ ip route show
default via 192.0.2.1 dev eth0
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.2

Two lines, and both matter. The first is the default route, everything not otherwise matched goes out eth0 via the gateway 192.0.2.1. The second is the connected route the kernel installs automatically the moment an address is assigned to eth0, anything in 192.0.2.0/24 is directly reachable, no gateway needed.

For a specific destination, rather than reading the whole table and mentally matching the longest prefix yourself, ask the kernel to do the lookup:

$ ip route get 1.1.1.1
1.1.1.1 via 192.0.2.1 dev eth0 src 192.0.2.2 uid 0
    cache

That single command answers “which route will this specific packet actually take” directly, which is the question you actually have most of the time, rather than “show me everything and let me figure it out.”

The legacy tool, if you’re on an older box:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.0.2.1       0.0.0.0         UG    0      0        0 eth0
192.0.2.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0

-n stops it resolving hostnames for gateway/destination, which you almost always want; without it, a slow or dead DNS server can make route itself hang.

Windows: route print and Get-NetRoute

C:\> route print

produces the classic, dense, all-in-one text table: IPv4 routes, IPv6 routes, and the persistent routes list, all in one scroll. It’s the direct visual equivalent of Linux’s route -n, right down to the Destination/Gateway/Genmask-style columns, and it’s still what most Windows admins reach for first out of habit.

Get-NetRoute is the structured, scriptable version:

PS> Get-NetRoute -AddressFamily IPv4 |
    Format-Table DestinationPrefix, NextHop, InterfaceAlias, RouteMetric -AutoSize
# just the default route (the Windows analogue of Linux's "ip route | grep default")
PS> Get-NetRoute -DestinationPrefix "0.0.0.0/0" | Select-Object -ExpandProperty NextHop

DestinationPrefix is Windows’ name for what Linux calls the route’s prefix (0.0.0.0/0 for default, same CIDR notation both places). NextHop is the gateway; a NextHop of 0.0.0.0 means the same thing Linux’s connected route without a via means, directly reachable on that subnet, no gateway hop needed.

Where the concepts actually diverge: RouteMetric

Every Windows route carries a RouteMetric, and Windows genuinely uses it: when multiple routes could match the same destination (two NICs both with a default route, for instance, one Wi-Fi and one Ethernet), the one with the lower RouteMetric wins, combined with the interface’s own metric.

Linux’s routing table has a metric field too (visible in ip route show output as metric N when it’s non-default, and it’s the Metric column in route -n), but day-to-day Linux administration leans on Linux’s actual tiebreaker mechanism far more: routing tables, ip rule, and policy-based routing. Windows has nothing directly equivalent to ip rule’s “route lookup depends on which table applies to this source/mark/fwmark” model; multi-path selection on Windows is metric-and-interface-priority based, not policy-table based. If you’re coming from Linux and looking for Windows’ ip rule or VRF-style equivalent, there genuinely isn’t a clean one at the Get-NetRoute level, it lives one layer up in things like Hyper-V virtual switches or third-party SD-WAN/VPN client route injection instead.

Adding a route: the one place Get-NetRoute’s cousin needs more than you’d expect

New-NetRoute looks like a straight equivalent to ip route add at a glance, but it has one requirement Linux’s version doesn’t: an interface is mandatory, not optional. You can’t add a route on Windows without telling it which -InterfaceAlias (or -InterfaceIndex) it belongs to.

# Linux: the kernel works out the interface from the gateway's subnet
$ sudo ip route add 198.51.100.0/24 via 192.0.2.1
# Windows: InterfaceAlias is required, not inferred
PS> New-NetRoute -DestinationPrefix "198.51.100.0/24" -InterfaceAlias "Ethernet" -NextHop 192.0.2.1

Leave -InterfaceAlias off and it fails outright rather than guessing, which is a small but real difference in how forgiving the two platforms are about an incomplete command.

Quick reference

What you wantLinuxWindows
Full routing tableip route showroute print
Structured/scriptable tableip route show (parse or -j for JSON)Get-NetRoute
Which route will this destination takeip route get <ip>Get-NetRoute -DestinationPrefix <ip>/32 (approximate; doesn’t do longest-prefix-match the way ip route get does)
Just the default routeip route show defaultGet-NetRoute -DestinationPrefix "0.0.0.0/0"
Add a routeip route add <cidr> via <gw>New-NetRoute -DestinationPrefix <cidr> -InterfaceAlias <if> -NextHop <gw>
Legacy text tableroute -nroute print

What’s next

Part 5 covers name resolution: dig, nslookup, and resolvectl against Resolve-DnsName, nslookup, and ipconfig /displaydns, including real query output captured live for this series.

Cross-references: Beyond ifconfig: The ip Command Reference Every Network Engineer Needs covers ip rule and policy routing tables in full, the piece of Linux routing this post only flags as having no Windows equivalent.