diff options
Diffstat (limited to 'drivers/net/loopback.c')
-rw-r--r-- | drivers/net/loopback.c | 98 |
1 files changed, 71 insertions, 27 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 2df7f60fe052..14545a8797a8 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket @@ -22,11 +23,6 @@ * interface. * Alexey Kuznetsov: Potential hang under some extreme * cases removed. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. */ #include <linux/kernel.h> #include <linux/jiffies.h> @@ -59,6 +55,13 @@ #include <net/net_namespace.h> #include <linux/u64_stats_sync.h> +/* blackhole_netdev - a device used for dsts that are marked expired! + * This is global device (instead of per-net-ns) since it's not needed + * to be per-ns and gets initialized at boot time. + */ +struct net_device *blackhole_netdev; +EXPORT_SYMBOL(blackhole_netdev); + /* The higher levels take care of making this non-reentrant (it's * called with bh's disabled). */ @@ -128,21 +131,9 @@ static u32 always_on(struct net_device *dev) return 1; } -static int loopback_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *ts_info) -{ - ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | - SOF_TIMESTAMPING_RX_SOFTWARE | - SOF_TIMESTAMPING_SOFTWARE; - - ts_info->phc_index = -1; - - return 0; -}; - static const struct ethtool_ops loopback_ethtool_ops = { .get_link = always_on, - .get_ts_info = loopback_get_ts_info, + .get_ts_info = ethtool_op_get_ts_info, }; static int loopback_dev_init(struct net_device *dev) @@ -166,12 +157,14 @@ static const struct net_device_ops loopback_ops = { .ndo_set_mac_address = eth_mac_addr, }; -/* The loopback device is special. There is only one instance - * per network namespace. - */ -static void loopback_setup(struct net_device *dev) +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 = 64 * 1024; + dev->mtu = mtu; dev->hard_header_len = ETH_HLEN; /* 14 */ dev->min_header_len = ETH_HLEN; /* 14 */ dev->addr_len = ETH_ALEN; /* 6 */ @@ -190,11 +183,20 @@ static void loopback_setup(struct net_device *dev) | NETIF_F_NETNS_LOCAL | NETIF_F_VLAN_CHALLENGED | NETIF_F_LOOPBACK; - dev->ethtool_ops = &loopback_ethtool_ops; - dev->header_ops = ð_header_ops; - dev->netdev_ops = &loopback_ops; + dev->ethtool_ops = eth_ops; + dev->header_ops = hdr_ops; + dev->netdev_ops = dev_ops; dev->needs_free_netdev = true; - dev->priv_destructor = loopback_dev_free; + dev->priv_destructor = dev_destructor; +} + +/* The loopback device is special. There is only one instance + * per network namespace. + */ +static void loopback_setup(struct net_device *dev) +{ + gen_lo_setup(dev, (64 * 1024), &loopback_ethtool_ops, ð_header_ops, + &loopback_ops, loopback_dev_free); } /* Setup and register the loopback device. */ @@ -229,3 +231,45 @@ out: struct pernet_operations __net_initdata loopback_net_ops = { .init = loopback_net_init, }; + +/* blackhole netdevice */ +static netdev_tx_t blackhole_netdev_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + kfree_skb(skb); + net_warn_ratelimited("%s(): Dropping skb.\n", __func__); + return NETDEV_TX_OK; +} + +static const struct net_device_ops blackhole_netdev_ops = { + .ndo_start_xmit = blackhole_netdev_xmit, +}; + +/* This is a dst-dummy device used specifically for invalidated + * DSTs and unlike loopback, this is not per-ns. + */ +static void blackhole_netdev_setup(struct net_device *dev) +{ + gen_lo_setup(dev, ETH_MIN_MTU, NULL, NULL, &blackhole_netdev_ops, NULL); +} + +/* Setup and register the blackhole_netdev. */ +static int __init blackhole_netdev_init(void) +{ + blackhole_netdev = alloc_netdev(0, "blackhole_dev", NET_NAME_UNKNOWN, + blackhole_netdev_setup); + if (!blackhole_netdev) + return -ENOMEM; + + rtnl_lock(); + dev_init_scheduler(blackhole_netdev); + dev_activate(blackhole_netdev); + rtnl_unlock(); + + blackhole_netdev->flags |= IFF_UP | IFF_RUNNING; + dev_net_set(blackhole_netdev, &init_net); + + return 0; +} + +device_initcall(blackhole_netdev_init); |