LearnThe Network StackYour Network Interface

The Interface

ip link show - a hands-on Linux lab on a real virtual machine.

Every Linux system has network interfaces with names, MAC addresses, drivers, and counters. This lesson teaches you how to find and read all of it.

This page reached you through the thing you are about to meet

The terminal below is connected to a real Linux virtual machine. Every keystroke you type crosses a network to reach it, and every character it prints crosses back. Right now, while you read this, something inside that machine is moving those bytes.

That something is the network interface, and almost nobody ever looks at it. People plug in a cable, join the Wi-Fi, and trust it. Engineers look.

By the end of this lesson you can walk up to any Linux machine and name its interfaces, read their hardware addresses, and identify the code that drives them. You can watch its packet counters move and prove whether a link is alive. Every tool involved is already installed on effectively every Linux system on earth.

The black boxes below are a practice terminal: a safe sandbox that checks the one command each step teaches. It mirrors your lab VM, where the user is student and the host is net-lab. In the lab itself your progress is tracked automatically as you type, and check-progress shows your score at any time. One habit to start today: tab completion. In the lab VM, type the first letters of any path and press Tab, and the shell finishes the path for you. The paths in this lesson are long, and engineers never type them out.

Find every interface the kernel knows about

A network interface is the point where a computer connects to a network. Definitions can wait one minute. First, find yours.

The kernel keeps a public register of every interface it manages: one directory per interface, all in one place, /sys/class/net/. You know ls from Foundations. Point it at the register.

Before you press Enter, commit to a guess: how many interfaces does a machine this small have?

ls /sys/class/net/

prompt: student@net-lab:~$ answer: ls /sys/class/net/ output: eth0 lo hint: List the directory where the kernel registers interfaces: ls /sys/class/net/

Two names. eth0 is the interface this machine reaches the world through, the one carrying your keystrokes at this moment. lo is the loopback, an interface that leads back into the machine itself.

Hold on to the shape of what you just did. You asked a hardware question and a directory listing answered it. That is not a coincidence, and it is the key to half of this lesson.

What a network interface is

On a physical machine, the interface is a NIC, a Network Interface Card: the chip, or the port on the back, where the cable plugs in or the radio lives.

This machine is a virtual machine, so there is no chip. The hypervisor, the software that runs the VM, builds a virtual NIC instead. Your kernel cannot tell the difference. It sees a device with a name, an address, a driver, and counters, exactly as it would on real metal.

Think of an interface as the mailbox on a house. The postal service never delivers to the kitchen table. Every letter, whoever inside it is for, lands in the box first. Network traffic works the same way: every packet, whichever program it is for, arrives at an interface first, and the operating system sorts it from there.

Your two interfaces, properly introduced:

On other machines you will meet names like ens3, enp0s3, or eno1. Those come from a scheme called Predictable Network Interface Names, and the letters are a street address for the card: enp0s3 means Ethernet, PCI bus 0, slot 3. Naming cards after where they sit means the names cannot shuffle when the kernel detects hardware in a different order at boot. Your VM has one virtual NIC and keeps the kernel's own first name for it: eth0.

Two generations of tools

The command people used for this job for decades was ifconfig. It appeared in BSD Unix in 1983, and every Unix copied it.

In the late 1990s Linux rebuilt its network stack, and a kernel developer named Alexey Kuznetsov wrote a new toolkit to drive it: iproute2, the suite the ip command comes from. The difference is the channel. ifconfig asks the kernel questions through ioctl calls, an old mechanism that asks one fixed question at a time. ip speaks netlink, a socket where the kernel answers structured messages about its network state. Netlink can express things the old mechanism never could, which is why ifconfig famously shows at most one IPv4 address per interface while ip shows them all.

Modern Debian does not even install ifconfig by default. ip is the tool, and it is the one this track uses throughout.

iproute2 accepts any unambiguous abbreviation of its words. ip link show, ip l sh, and even plain ip l run the same command. Watch a working engineer's terminal and you will see the short forms all day.

List them properly with ip link show

ip groups its work into objects. link is the object for interfaces themselves, the physical and virtual devices, before any addresses get involved. show is the verb.

You know the machine has eth0 and lo. Before you run this, commit to a prediction: which of the two will report state UP? Both? Neither?

ip link show

prompt: student@net-lab:~$ answer: ip link show ||| ip link ||| ip l sh ||| ip l ||| ip link list ||| ip link ls output: 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 02:fc:00:00:00:05 brd ff:ff:ff:ff:ff:ff hint: The link object and its show verb: ip link show

Two entries, two lines each, and the differences between them teach the whole layer.

The loopback says mtu 65536, qdisc noqueue, state UNKNOWN, and an address of all zeros. eth0 says mtu 1500, qdisc fq_codel, state UP, and a real address, 02:fc:00:00:00:05.

Every one of those differences has a reason, and one of them, that UNKNOWN on an interface that plainly works, is a small mystery this lesson settles near the end. First, take the line apart field by field.

Reading the output, field by field

The lo line first:

FieldMeaning
1:The interface index. The kernel numbers every interface, starting at 1.
lo:The interface name.
<LOOPBACK,UP,LOWER_UP>Flags. LOOPBACK marks the device type. UP means an administrator enabled it. LOWER_UP means the layer underneath is alive.
mtu 65536The MTU, Maximum Transmission Unit: the largest packet, in bytes, this interface will carry.
qdisc noqueueThe queuing discipline, the kernel policy that schedules outgoing packets. noqueue means packets are handed over immediately, no queue at all.
state UNKNOWNThe operational state. Hold that thought.
link/loopback 00:00:00:00:00:00The link type, and a MAC address of all zeros. Loopback traffic never crosses a wire, so it needs no real hardware address.

Then eth0:

FieldMeaning
2:Interface index 2.
<BROADCAST,MULTICAST,UP,LOWER_UP>It can send to every machine on the local network at once (broadcast) and to subscribed groups (multicast), and it is up at both layers.
mtu 1500The standard Ethernet MTU.
qdisc fq_codelA fair queue. More below.
state UPOperationally up and passing traffic.
link/ether 02:fc:00:00:00:05An Ethernet device, and its MAC address. The next step is about this number.
brd ff:ff:ff:ff:ff:ffThe broadcast address. A frame sent to all-ones is received by every machine on the local network. A protocol called ARP leans on this constantly. It gets its own lesson soon.

Three of these fields hide more than they show.

UP versus LOWER_UP. They look redundant and are not. UP records a decision: an administrator enabled the interface. LOWER_UP records a fact: the layer below, the cable or the virtual link, is alive. An enabled interface with no cable shows UP with NO-CARRIER in place of LOWER_UP, and no traffic moves. Both must hold before an interface works, and knowing which one is missing tells you whether to check a config or a cable.

The two MTUs. Ethernet settled on 1500 bytes as the wire limit decades ago. The loopback has no wire, so the kernel raises its MTU to 65536 bytes, a shade over the largest packet IP can even describe: the total length field in an IPv4 header is 16 bits, so no IPv4 packet bigger than 65535 bytes can exist. Bigger chunks per packet means less per-packet overhead, and on loopback there is no reason to hold back.

The two qdiscs. fq_codel stands for Fair Queuing with Controlled Delay. It keeps one greedy connection from filling the transmit queue and adding latency for everyone else, a disease known as bufferbloat. Modern kernels make it the default through the net.core.default_qdisc setting. The loopback delivers instantly to the same machine, so it gets noqueue: nothing to schedule, nothing to queue.

The index numbers are not decoration. Inside the kernel, the number is the interface's real identity, and the name is a label for humans. Routes and sockets refer to interfaces by index, and when you meet an IPv6 address written like fe80::1%eth0, that suffix is a human-readable way of naming the index.

Commit: who chose this MAC address?

eth0's hardware address is 02:fc:00:00:00:05. Factory NICs from Intel, Broadcom, or Realtek carry addresses burned in during manufacturing. Take a position before the next screen.

Read the MAC straight from the kernel

A MAC address, for Media Access Control, is a 48-bit number written as six pairs of hexadecimal digits. It identifies one interface on the local network. When your machine sends a frame to a neighbor, the frame header says which MAC it came from and which MAC it is for. Every switch in the building forwards frames by looking at exactly those fields.

You saw the address inside ip link show output. Now get it the way scripts get it. That register directory from the first step, /sys/class/net/, is part of sysfs, a virtual filesystem where the kernel presents device state as readable files. The files are not on disk. Reading one asks the kernel directly, and inside eth0's directory there is a file named address.

cat prints a file. Point it there.

cat /sys/class/net/eth0/address

prompt: student@net-lab:~$ answer: cat /sys/class/net/eth0/address output: 02:fc:00:00:00:05 hint: The address file inside the eth0 directory: cat /sys/class/net/eth0/address

One line, one fact, no parsing. That is the sysfs trade everywhere: ip link show gives you everything at once for your eyes, and sysfs gives one value per file for your scripts.

Now finish the anatomy of the first byte, because both of its low bits are flags. Bit 1 you know: locally administered. Bit 0 is the group bit: set only on multicast and broadcast destinations, never on a real interface's own address. Which hands you a fact most engineers never notice: every unicast MAC address on earth has an even first byte.

Your VM generates its own address at boot, so yours may differ from this screen. The even, locally administered start is the part that repeats.

A MAC address is not an identity. ip link can set a new one in two seconds, and modern phones invent a fresh locally administered address for every Wi-Fi network specifically so the real one cannot be tracked. Filters and trust decisions built on MAC addresses stop honest hardware and never stop an attacker.

The driver behind the interface

Every device in a Linux system is managed by a driver: a piece of kernel code, usually a loadable kernel module, that knows how to operate that specific hardware. Somebody wrote one for your NIC, the kernel loaded it at boot, and it has been moving your packets ever since.

sysfs tells you which one. Inside the interface's directory, device/ leads to the device itself, and its uevent file holds the identity card. Before you read it, one more commit: this is a microVM with no real hardware. What kind of driver would you even expect?

cat /sys/class/net/eth0/device/uevent

prompt: student@net-lab:~$ answer: cat /sys/class/net/eth0/device/uevent output: DRIVER=virtio_net MODALIAS=virtio:d00000001v... hint: The uevent file lives one level down, inside device/: cat /sys/class/net/eth0/device/uevent

The DRIVER line answers the question: virtio_net. virtio is the family of paravirtual devices, meaning the driver knows perfectly well it is inside a VM and cooperates with the hypervisor through shared memory instead of pretending to poke real hardware. That honesty is why it is fast, and why the same driver name appears on VMs at AWS, on Firecracker microVMs like this one, and on every KVM cloud. On physical servers this line says things like e1000e, igb, or bnxt_en instead.

The MODALIAS line is the deeper story: it is the search string the kernel publishes when a device appears. At boot, the kernel announced this device with that exact string, and modprobe loaded whichever module lists a matching alias. That is the entire mechanism by which Linux finds drivers for hardware nobody configured. The screen above shortens the tail; on your VM the line ends with the full vendor id.

Two related moves for your kit. readlink /sys/class/net/eth0/device/driver resolves the driver as a symlink, and the last part of the path it prints is the driver name. And on physical servers, ethtool -i eth0 asks the driver to introduce itself. It queries the hardware through the driver, so on minimal virtual NICs it often comes back empty-handed, while the sysfs files you just used are populated by the kernel itself and work everywhere.

Commit: errs or drop?

The kernel counts every packet that crosses every interface, and it has been counting since boot. The ledger has separate columns per interface, and two of them are named errs and drop.

The ledger: /proc/net/dev

The ledger lives in /proc, the other virtual filesystem: like /sys, its files are generated by the kernel at the moment you read them. Every read of this one hands you a fresh snapshot of every counter on every interface.

cat /proc/net/dev

prompt: student@net-lab:~$ answer: cat /proc/net/dev output: Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 1234 16 0 0 0 0 0 0 1234 16 0 0 0 0 0 0 eth0: 56789 321 0 0 0 0 0 0 12345 198 0 0 0 0 0 0 hint: The ledger is a proc file: cat /proc/net/dev

One row per interface, split into two halves: Receive on the left, Transmit on the right.

Your numbers will differ from this screen, and here is the part worth smiling at: they grow because you looked. Your terminal session travels over eth0, so the very act of printing this table transmitted bytes, and the next read will show them. On a live interface the ledger never stands still.

Now look at the lo row. Receive and transmit are identical, byte for byte, packet for packet. They always are: every packet the loopback sends, it also receives. An imbalance there would mean the kernel lost traffic on a path that does not physically exist, which is why matching lo columns are one of the quiet sanity checks in the file.

Every column, and the two that matter at 3 AM

The full column list, once, for reference:

ColumnMeaning
bytesTotal bytes since boot.
packetsTotal packets since boot.
errsFrames that arrived damaged: checksum or framing failures.
dropFrames discarded by the kernel, usually a full buffer.
fifoHardware queue overruns. Rare on modern systems.
frameReceive-side alignment errors: bits that did not line up into bytes.
compressedCompressed packets. Zero unless you run compressed links.
multicastMulticast frames received.
collsCollisions while sending. A relic of half-duplex Ethernet, where two machines could talk over each other on shared wire. Always zero on anything modern.
carrierThe link vanished mid-transmission.

A healthy interface holds errs, drop, fifo, frame, colls, and carrier at zero or near it. When a network feels slow, this file is where feelings become numbers: climbing errs points at the physical world, climbing drop points at the machine, and you already know why.

One file per fact: the rest of the eth0 directory

The address file was not special. The interface's whole directory is a cabinet of one-fact files:

Practice The Interface in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.

More lessons in Your Network Interface

FileWhat it holds
addressThe MAC address.
operstateThe operational state: up, down, or unknown.
mtuThe current MTU as a bare number.
carrier1 if the link layer sees a live link, 0 if not.
speedLink speed in Mbps on physical NICs. Virtual NICs often report -1: there is no wire to have a speed.
duplexfull, half, or unknown on virtual NICs, for the same rea