162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * INET An implementation of the TCP/IP protocol suite for the LINUX 462306a36Sopenharmony_ci * operating system. INET is implemented using the BSD Socket 562306a36Sopenharmony_ci * interface as the means of communication with the user level. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Pseudo-driver for the loopback interface. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Version: @(#)loopback.c 1.0.4b 08/16/93 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Authors: Ross Biro 1262306a36Sopenharmony_ci * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 1362306a36Sopenharmony_ci * Donald Becker, <becker@scyld.com> 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Alan Cox : Fixed oddments for NET3.014 1662306a36Sopenharmony_ci * Alan Cox : Rejig for NET3.029 snap #3 1762306a36Sopenharmony_ci * Alan Cox : Fixed NET3.029 bugs and sped up 1862306a36Sopenharmony_ci * Larry McVoy : Tiny tweak to double performance 1962306a36Sopenharmony_ci * Alan Cox : Backed out LMV's tweak - the linux mm 2062306a36Sopenharmony_ci * can't take it... 2162306a36Sopenharmony_ci * Michael Griffith: Don't bother computing the checksums 2262306a36Sopenharmony_ci * on packets received on the loopback 2362306a36Sopenharmony_ci * interface. 2462306a36Sopenharmony_ci * Alexey Kuznetsov: Potential hang under some extreme 2562306a36Sopenharmony_ci * cases removed. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ci#include <linux/kernel.h> 2862306a36Sopenharmony_ci#include <linux/jiffies.h> 2962306a36Sopenharmony_ci#include <linux/module.h> 3062306a36Sopenharmony_ci#include <linux/interrupt.h> 3162306a36Sopenharmony_ci#include <linux/fs.h> 3262306a36Sopenharmony_ci#include <linux/types.h> 3362306a36Sopenharmony_ci#include <linux/string.h> 3462306a36Sopenharmony_ci#include <linux/socket.h> 3562306a36Sopenharmony_ci#include <linux/errno.h> 3662306a36Sopenharmony_ci#include <linux/fcntl.h> 3762306a36Sopenharmony_ci#include <linux/in.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#include <linux/uaccess.h> 4062306a36Sopenharmony_ci#include <linux/io.h> 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#include <linux/inet.h> 4362306a36Sopenharmony_ci#include <linux/netdevice.h> 4462306a36Sopenharmony_ci#include <linux/etherdevice.h> 4562306a36Sopenharmony_ci#include <linux/skbuff.h> 4662306a36Sopenharmony_ci#include <linux/ethtool.h> 4762306a36Sopenharmony_ci#include <net/sch_generic.h> 4862306a36Sopenharmony_ci#include <net/sock.h> 4962306a36Sopenharmony_ci#include <net/checksum.h> 5062306a36Sopenharmony_ci#include <linux/if_ether.h> /* For the statistics structure. */ 5162306a36Sopenharmony_ci#include <linux/if_arp.h> /* For ARPHRD_ETHER */ 5262306a36Sopenharmony_ci#include <linux/ip.h> 5362306a36Sopenharmony_ci#include <linux/tcp.h> 5462306a36Sopenharmony_ci#include <linux/percpu.h> 5562306a36Sopenharmony_ci#include <linux/net_tstamp.h> 5662306a36Sopenharmony_ci#include <net/net_namespace.h> 5762306a36Sopenharmony_ci#include <linux/u64_stats_sync.h> 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* blackhole_netdev - a device used for dsts that are marked expired! 6062306a36Sopenharmony_ci * This is global device (instead of per-net-ns) since it's not needed 6162306a36Sopenharmony_ci * to be per-ns and gets initialized at boot time. 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_cistruct net_device *blackhole_netdev; 6462306a36Sopenharmony_ciEXPORT_SYMBOL(blackhole_netdev); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* The higher levels take care of making this non-reentrant (it's 6762306a36Sopenharmony_ci * called with bh's disabled). 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_cistatic netdev_tx_t loopback_xmit(struct sk_buff *skb, 7062306a36Sopenharmony_ci struct net_device *dev) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci int len; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci skb_tx_timestamp(skb); 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* do not fool net_timestamp_check() with various clock bases */ 7762306a36Sopenharmony_ci skb_clear_tstamp(skb); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci skb_orphan(skb); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* Before queueing this packet to __netif_rx(), 8262306a36Sopenharmony_ci * make sure dst is refcounted. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_ci skb_dst_force(skb); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci skb->protocol = eth_type_trans(skb, dev); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci len = skb->len; 8962306a36Sopenharmony_ci if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) 9062306a36Sopenharmony_ci dev_lstats_add(dev, len); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci return NETDEV_TX_OK; 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_civoid dev_lstats_read(struct net_device *dev, u64 *packets, u64 *bytes) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci int i; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci *packets = 0; 10062306a36Sopenharmony_ci *bytes = 0; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci for_each_possible_cpu(i) { 10362306a36Sopenharmony_ci const struct pcpu_lstats *lb_stats; 10462306a36Sopenharmony_ci u64 tbytes, tpackets; 10562306a36Sopenharmony_ci unsigned int start; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci lb_stats = per_cpu_ptr(dev->lstats, i); 10862306a36Sopenharmony_ci do { 10962306a36Sopenharmony_ci start = u64_stats_fetch_begin(&lb_stats->syncp); 11062306a36Sopenharmony_ci tpackets = u64_stats_read(&lb_stats->packets); 11162306a36Sopenharmony_ci tbytes = u64_stats_read(&lb_stats->bytes); 11262306a36Sopenharmony_ci } while (u64_stats_fetch_retry(&lb_stats->syncp, start)); 11362306a36Sopenharmony_ci *bytes += tbytes; 11462306a36Sopenharmony_ci *packets += tpackets; 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ciEXPORT_SYMBOL(dev_lstats_read); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic void loopback_get_stats64(struct net_device *dev, 12062306a36Sopenharmony_ci struct rtnl_link_stats64 *stats) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci u64 packets, bytes; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci dev_lstats_read(dev, &packets, &bytes); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci stats->rx_packets = packets; 12762306a36Sopenharmony_ci stats->tx_packets = packets; 12862306a36Sopenharmony_ci stats->rx_bytes = bytes; 12962306a36Sopenharmony_ci stats->tx_bytes = bytes; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic u32 always_on(struct net_device *dev) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci return 1; 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic const struct ethtool_ops loopback_ethtool_ops = { 13862306a36Sopenharmony_ci .get_link = always_on, 13962306a36Sopenharmony_ci .get_ts_info = ethtool_op_get_ts_info, 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic int loopback_dev_init(struct net_device *dev) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats); 14562306a36Sopenharmony_ci if (!dev->lstats) 14662306a36Sopenharmony_ci return -ENOMEM; 14762306a36Sopenharmony_ci return 0; 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic void loopback_dev_free(struct net_device *dev) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci dev_net(dev)->loopback_dev = NULL; 15362306a36Sopenharmony_ci free_percpu(dev->lstats); 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic const struct net_device_ops loopback_ops = { 15762306a36Sopenharmony_ci .ndo_init = loopback_dev_init, 15862306a36Sopenharmony_ci .ndo_start_xmit = loopback_xmit, 15962306a36Sopenharmony_ci .ndo_get_stats64 = loopback_get_stats64, 16062306a36Sopenharmony_ci .ndo_set_mac_address = eth_mac_addr, 16162306a36Sopenharmony_ci}; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic void gen_lo_setup(struct net_device *dev, 16462306a36Sopenharmony_ci unsigned int mtu, 16562306a36Sopenharmony_ci const struct ethtool_ops *eth_ops, 16662306a36Sopenharmony_ci const struct header_ops *hdr_ops, 16762306a36Sopenharmony_ci const struct net_device_ops *dev_ops, 16862306a36Sopenharmony_ci void (*dev_destructor)(struct net_device *dev)) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci dev->mtu = mtu; 17162306a36Sopenharmony_ci dev->hard_header_len = ETH_HLEN; /* 14 */ 17262306a36Sopenharmony_ci dev->min_header_len = ETH_HLEN; /* 14 */ 17362306a36Sopenharmony_ci dev->addr_len = ETH_ALEN; /* 6 */ 17462306a36Sopenharmony_ci dev->type = ARPHRD_LOOPBACK; /* 0x0001*/ 17562306a36Sopenharmony_ci dev->flags = IFF_LOOPBACK; 17662306a36Sopenharmony_ci dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE; 17762306a36Sopenharmony_ci netif_keep_dst(dev); 17862306a36Sopenharmony_ci dev->hw_features = NETIF_F_GSO_SOFTWARE; 17962306a36Sopenharmony_ci dev->features = NETIF_F_SG | NETIF_F_FRAGLIST 18062306a36Sopenharmony_ci | NETIF_F_GSO_SOFTWARE 18162306a36Sopenharmony_ci | NETIF_F_HW_CSUM 18262306a36Sopenharmony_ci | NETIF_F_RXCSUM 18362306a36Sopenharmony_ci | NETIF_F_SCTP_CRC 18462306a36Sopenharmony_ci | NETIF_F_HIGHDMA 18562306a36Sopenharmony_ci | NETIF_F_LLTX 18662306a36Sopenharmony_ci | NETIF_F_NETNS_LOCAL 18762306a36Sopenharmony_ci | NETIF_F_VLAN_CHALLENGED 18862306a36Sopenharmony_ci | NETIF_F_LOOPBACK; 18962306a36Sopenharmony_ci dev->ethtool_ops = eth_ops; 19062306a36Sopenharmony_ci dev->header_ops = hdr_ops; 19162306a36Sopenharmony_ci dev->netdev_ops = dev_ops; 19262306a36Sopenharmony_ci dev->needs_free_netdev = true; 19362306a36Sopenharmony_ci dev->priv_destructor = dev_destructor; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci netif_set_tso_max_size(dev, GSO_MAX_SIZE); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci/* The loopback device is special. There is only one instance 19962306a36Sopenharmony_ci * per network namespace. 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_cistatic void loopback_setup(struct net_device *dev) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci gen_lo_setup(dev, (64 * 1024), &loopback_ethtool_ops, ð_header_ops, 20462306a36Sopenharmony_ci &loopback_ops, loopback_dev_free); 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci/* Setup and register the loopback device. */ 20862306a36Sopenharmony_cistatic __net_init int loopback_net_init(struct net *net) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci struct net_device *dev; 21162306a36Sopenharmony_ci int err; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci err = -ENOMEM; 21462306a36Sopenharmony_ci dev = alloc_netdev(0, "lo", NET_NAME_PREDICTABLE, loopback_setup); 21562306a36Sopenharmony_ci if (!dev) 21662306a36Sopenharmony_ci goto out; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci dev_net_set(dev, net); 21962306a36Sopenharmony_ci err = register_netdev(dev); 22062306a36Sopenharmony_ci if (err) 22162306a36Sopenharmony_ci goto out_free_netdev; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci BUG_ON(dev->ifindex != LOOPBACK_IFINDEX); 22462306a36Sopenharmony_ci net->loopback_dev = dev; 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ciout_free_netdev: 22862306a36Sopenharmony_ci free_netdev(dev); 22962306a36Sopenharmony_ciout: 23062306a36Sopenharmony_ci if (net_eq(net, &init_net)) 23162306a36Sopenharmony_ci panic("loopback: Failed to register netdevice: %d\n", err); 23262306a36Sopenharmony_ci return err; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci/* Registered in net/core/dev.c */ 23662306a36Sopenharmony_cistruct pernet_operations __net_initdata loopback_net_ops = { 23762306a36Sopenharmony_ci .init = loopback_net_init, 23862306a36Sopenharmony_ci}; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci/* blackhole netdevice */ 24162306a36Sopenharmony_cistatic netdev_tx_t blackhole_netdev_xmit(struct sk_buff *skb, 24262306a36Sopenharmony_ci struct net_device *dev) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci kfree_skb(skb); 24562306a36Sopenharmony_ci net_warn_ratelimited("%s(): Dropping skb.\n", __func__); 24662306a36Sopenharmony_ci return NETDEV_TX_OK; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic const struct net_device_ops blackhole_netdev_ops = { 25062306a36Sopenharmony_ci .ndo_start_xmit = blackhole_netdev_xmit, 25162306a36Sopenharmony_ci}; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci/* This is a dst-dummy device used specifically for invalidated 25462306a36Sopenharmony_ci * DSTs and unlike loopback, this is not per-ns. 25562306a36Sopenharmony_ci */ 25662306a36Sopenharmony_cistatic void blackhole_netdev_setup(struct net_device *dev) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci gen_lo_setup(dev, ETH_MIN_MTU, NULL, NULL, &blackhole_netdev_ops, NULL); 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci/* Setup and register the blackhole_netdev. */ 26262306a36Sopenharmony_cistatic int __init blackhole_netdev_init(void) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci blackhole_netdev = alloc_netdev(0, "blackhole_dev", NET_NAME_UNKNOWN, 26562306a36Sopenharmony_ci blackhole_netdev_setup); 26662306a36Sopenharmony_ci if (!blackhole_netdev) 26762306a36Sopenharmony_ci return -ENOMEM; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci rtnl_lock(); 27062306a36Sopenharmony_ci dev_init_scheduler(blackhole_netdev); 27162306a36Sopenharmony_ci dev_activate(blackhole_netdev); 27262306a36Sopenharmony_ci rtnl_unlock(); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci blackhole_netdev->flags |= IFF_UP | IFF_RUNNING; 27562306a36Sopenharmony_ci dev_net_set(blackhole_netdev, &init_net); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci return 0; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cidevice_initcall(blackhole_netdev_init); 281