Networking Basics covers the four questions to ask when a network is broken. This page is the reference for the tool that answers three of them. ip replaced ifconfig, route and arp — which came from net-tools and have been deprecated for well over a decade — with one command that handles everything the kernel knows about networking.

One command, several objects

Every invocation is ip OBJECT COMMAND. Learn the objects and the rest is consistent.

ObjectDeals withReplaces
address / aIP addresses on interfacesifconfig
link / lThe interfaces themselves — up, down, MTU, MACifconfig
route / rWhere packets goroute
neighbour / nThe ARP and NDP cachearp
ruleWhich routing table to consult
netnsNetwork namespaces
tunnel, link addTunnels, bridges, VLANs, veth pairsbrctl, vconfig

The two flags that make it readable

ip -br -c a          # brief, coloured: one line per interface
ip -br -c l          # the same for links
ip -4 -br a          # IPv4 only
ip -6 -br a          # IPv6 only
ip -j -p a           # JSON, for scripts — pipe into jq

ip -br -c a is the line to put in your fingers. The default output wraps across four lines per interface and buries the address you wanted; the brief form gives you name, state and addresses in one row each. Add it as an alias and never type the long form again.

-j emits JSON, which makes ip genuinely scriptable for the first time — no more parsing whitespace with awk. Pipe it into jq.

Addresses

ip a show dev eth0
sudo ip a add 192.168.1.50/24 dev eth0
sudo ip a add 192.168.1.51/24 dev eth0        # a second address is fine
sudo ip a del 192.168.1.51/24 dev eth0
sudo ip a flush dev eth0                      # remove all — careful over SSH

The prefix length is not optional and is not decoration. ip a add 192.168.1.50 dev eth0 with no /24 is taken as /32, giving you an address that can talk to nothing on its own subnet — a confusing failure that looks like a routing problem.

Links

ip -br l                                 # every interface and its state
sudo ip l set dev eth0 up                # or down
sudo ip l set dev eth0 mtu 1400
sudo ip l set dev eth0 address 02:11:22:33:44:55
ip -s l show dev eth0                    # packet counts, errors, drops

ip -s l is the underused one. Rising errors or dropped counters point at a cable, a duplex mismatch or an overloaded interface — a physical problem, not a configuration one, and worth checking before you rewrite anything.

The state field distinguishes DOWN (administratively off) from NO-CARRIER (on, but nothing is plugged in or the switch port is dead). Those are different problems with different fixes.

Routes, and the single most useful command here

ip r                                     # the routing table
ip r get 1.1.1.1                         # which route WOULD be used, and from where
ip r get 192.168.1.20
sudo ip r add default via 192.168.1.1 dev eth0
sudo ip r add 10.20.0.0/16 via 192.168.1.254
sudo ip r del 10.20.0.0/16
ip r show table all                      # including tables you did not know existed

ip r get is the command to reach for first. It does not send a packet — it asks the kernel which route it would choose for that destination, which interface it would leave by, and which source address it would use. When traffic is going somewhere unexpected, this answers it in one line, and it accounts for policy rules and multiple tables that reading ip r by eye would miss.

Where two routes could match, the more specific prefix wins; where they are equally specific, the lower metric wins. That is the whole algorithm, and it explains most surprises — including the one where a VPN adds two /1 routes to override your default without deleting it.

Neighbours

ip n                                     # the ARP cache
ip n show dev eth0
sudo ip n flush dev eth0                 # after replacing hardware or an IP moves
sudo ip n add 192.168.1.9 lladdr 00:11:22:33:44:55 dev eth0 nud permanent

An entry stuck in FAILED or INCOMPLETE means the host is not answering on the local segment at all — a layer-2 problem, so no amount of routing configuration will help. Flushing is the standard fix after an address moves between machines and something is still holding the old MAC.

Nothing you do here survives a reboot

ip changes the kernel’s live state and writes nothing to disk. Every address, route and interface change is gone at the next reboot — and often sooner, because whichever network manager is running may reassert its own configuration within seconds. Use ip to diagnose and to test; make it permanent in the tool your distribution actually uses.

SystemWhere configuration lives
Ubuntu ServerNetplan — YAML in /etc/netplan/, then netplan apply
Fedora, RHEL, Rocky, AlmaNetworkManager — nmcli, or files in /etc/NetworkManager/
Most desktopsNetworkManager — nmcli or the applet
Debian, minimal servers/etc/network/interfaces, or systemd-networkd
Arch, containers, appliancessystemd-networkd — /etc/systemd/network/*.network
# which one is actually in charge?
systemctl is-active NetworkManager systemd-networkd networking
nmcli device status                       # if NetworkManager
sudo netplan get                          # if netplan
networkctl status                         # if systemd-networkd

Two managers fighting over one interface produces settings that revert every few seconds. Establishing which one owns the interface is the first step in any configuration change, not the last.

Not locking yourself out

Changing addresses or routes on a remote machine is the classic way to lose access to it. Give yourself an automatic way back before you touch anything:

sudo shutdown -r +10                 # reboot in ten minutes unless cancelled
# ...make the change, confirm you can still connect from a NEW session...
sudo shutdown -c                     # cancel it

Since ip changes nothing on disk, a reboot restores the previous working configuration. Test with a second SSH session rather than the one you are already in — an existing connection often survives a change that stops any new one being made.

Namespaces

ip netns list
sudo ip netns add test
sudo ip netns exec test ip -br a          # run a command inside it
sudo ip -n test l set lo up

Each namespace has its own interfaces, addresses, routes and firewall rules. This is the mechanism containers use for networking — though container runtimes create their namespaces outside ip netns, so ip netns list will not show Docker’s. Reach those with nsenter -t <pid> -n instead.

Symptom to command

SymptomRun
No address at allip -br a, then check DHCP or the config tool
Address present, nothing reachableip r — is there a default route?
Traffic leaving the wrong interfaceip r get <destination>
Local hosts unreachable, remote fineip n — ARP failures
Works, but slow or lossyip -s l — errors and drops
Settings revert by themselvesA network manager owns the interface
Large transfers hang, small ones workMTU. Test with ping -M do -s 1472

Quick reference

ip -br -c a                        # everything, readably
ip r                               # routing table
ip r get 8.8.8.8                   # which route would be used
ip -s l show dev eth0              # errors and drops
ip n                               # ARP cache
sudo ip a add 10.0.0.5/24 dev eth0
sudo ip r add default via 10.0.0.1
sudo ip l set dev eth0 up
ip -j -p a                         # JSON output

Related