The network loopback interface (<span><span>lo</span></span>)
1. What is it?
<span>lo</span> is a virtual network interface that is automatically created and managed by the operating system kernel. Its IP address is always <span>127.0.0.1</span> (IPv4) and <span>::1</span> (IPv6), which is known as the loopback address localhost. Any IP packets sent to this address range will be directly looped back by the kernel and will not be sent to the network.
[root@test ~]# ifconfig lo
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 1003 bytes 122348 (119.4 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1003 bytes 122348 (119.4 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
The IPv4 loopback address range is: 127.0.0.0 to 127.255.255.255
Common address: 127.0.0.1 (localhost)
The IPv6 loopback address is: ::1, which is the only loopback address in IPv6, equivalent to IPv4’s 127.0.0.1.
2. What is its purpose?
Its core purpose is to allow network applications on a single host to communicate with themselves.
-
Self-communication: When an application needs to communicate with another application running on the same machine using network protocols (like TCP/IP), packets are sent and received through the
<span>lo</span>interface. -
Simplified design: Applications do not need to worry about whether the peer is on the same machine; they use a unified network API (like sockets) for connections. If the connection is to
<span>127.0.0.1</span>or<span>localhost</span>, the kernel automatically routes the traffic to the<span>lo</span>interface instead of sending it to the physical network card and external network. -
Service and testing: This is the foundation for running and testing network services like web servers and databases. You can install a MySQL database on your local machine and have the web server connect directly to
<span>127.0.0.1:3306</span>without configuring complex networks.
3. A simple analogy
If the physical network card <span>eth0</span> is likened to a phone used to communicate with the external internet, then the loopback interface <span>lo</span> is like your internal intercom at home.
eth0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255 ether 52:54:00:3c:ad:ac txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
4. Kernel driver implementation loopback.c
Network namespace creates a <span><span>lo</span></span> device registered to the kernel network subsystem
static __net_init int loopback_net_init(struct net *net){
struct net_device *dev;
int err;
dev = alloc_netdev(0, "lo", NET_NAME_PREDICTABLE, loopback_setup);
if (!dev)
return -ENOMEM;
dev_net_set(dev, net);
err = register_netdev(dev);
if (err) {
free_netdev(dev);
return err;
}
BUG_ON(dev->ifindex != LOOPBACK_IFINDEX);
net->loopback_dev = dev;
return 0;
}
Set the loopback identifier, mtu, header length, and corresponding ops functions and other network information.
static void gen_lo_setup(struct net_device *dev,
unsigned int mtu,
const struct ethtool_ops *eth_ops,
const struct header_ops *hdr_ops,
const struct net_device_ops *dev_ops,
void (*dev_destructor)(struct net_device *dev)){
dev->mtu = mtu;
dev->hard_header_len = ETH_HLEN;
dev->min_header_len = ETH_HLEN;
dev->addr_len = ETH_ALEN;
dev->type = ARPHRD_LOOPBACK;
dev->flags = IFF_LOOPBACK;
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
// omitted part of attribute settings
dev->netdev_ops = dev_ops;
dev->ethtool_ops = eth_ops;
dev->header_ops = hdr_ops;
dev->needs_free_netdev = true;
dev->priv_destructor = dev_destructor;
}
This is the send function for the loopback device; packets are not sent to the physical network card but are directly returned to the kernel network stack’s receive path. First, clear the receive timestamp, add the send timestamp, parse the Ethernet frame, and use <span>__netif_rx()</span><span> to send the packet into the receive queue, achieving the loopback.</span><pre><code class="language-plaintext">static netdev_tx_t loopback_xmit(struct sk_buff *skb,Statistics of the number of packets sent and received by the loopback device and the number of bytes, available for user space queries.
struct net_device *dev){
skb_tx_timestamp(skb);
skb_clear_tstamp(skb);
skb_orphan(skb);
skb_dst_force(skb);
skb->protocol = eth_type_trans(skb, dev);
int len = skb->len;
if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
dev_lstats_add(dev, len);
return NETDEV_TX_OK;
}
static void loopback_get_stats64(struct net_device *dev,
struct rtnl_link_stats64 *stats){
u64 packets, bytes;
dev_lstats_read(dev, &packets, &bytes);
stats->rx_packets = packets;
stats->tx_packets = packets;
stats->rx_bytes = bytes;
stats->tx_bytes = bytes;
}