xref: /openbmc/linux/drivers/net/dummy.c (revision a7b862ab)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* dummy.c: a dummy net driver
3 
4 	The purpose of this driver is to provide a device to point a
5 	route through, but not to actually transmit packets.
6 
7 	Why?  If you have a machine whose only connection is an occasional
8 	PPP/SLIP/PLIP link, you can only connect to your own hostname
9 	when the link is up.  Otherwise you have to use localhost.
10 	This isn't very consistent.
11 
12 	One solution is to set up a dummy link using PPP/SLIP/PLIP,
13 	but this seems (to me) too much overhead for too little gain.
14 	This driver provides a small alternative. Thus you can do
15 
16 	[when not running slip]
17 		ifconfig dummy slip.addr.ess.here up
18 	[to go to slip]
19 		ifconfig dummy down
20 		dip whatever
21 
22 	This was written by looking at Donald Becker's skeleton driver
23 	and the loopback driver.  I then threw away anything that didn't
24 	apply!	Thanks to Alan Cox for the key clue on what to do with
25 	misguided packets.
26 
27 			Nick Holloway, 27th May 1994
28 	[I tweaked this explanation a little but that's all]
29 			Alan Cox, 30th May 1994
30 */
31 
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/netdevice.h>
35 #include <linux/etherdevice.h>
36 #include <linux/ethtool.h>
37 #include <linux/init.h>
38 #include <linux/moduleparam.h>
39 #include <linux/rtnetlink.h>
40 #include <linux/net_tstamp.h>
41 #include <net/rtnetlink.h>
42 #include <linux/u64_stats_sync.h>
43 
44 #define DRV_NAME	"dummy"
45 
46 static int numdummies = 1;
47 
48 /* fake multicast ability */
set_multicast_list(struct net_device * dev)49 static void set_multicast_list(struct net_device *dev)
50 {
51 }
52 
dummy_get_stats64(struct net_device * dev,struct rtnl_link_stats64 * stats)53 static void dummy_get_stats64(struct net_device *dev,
54 			      struct rtnl_link_stats64 *stats)
55 {
56 	dev_lstats_read(dev, &stats->tx_packets, &stats->tx_bytes);
57 }
58 
dummy_xmit(struct sk_buff * skb,struct net_device * dev)59 static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
60 {
61 	dev_lstats_add(dev, skb->len);
62 
63 	skb_tx_timestamp(skb);
64 	dev_kfree_skb(skb);
65 	return NETDEV_TX_OK;
66 }
67 
dummy_dev_init(struct net_device * dev)68 static int dummy_dev_init(struct net_device *dev)
69 {
70 	dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
71 	if (!dev->lstats)
72 		return -ENOMEM;
73 
74 	netdev_lockdep_set_classes(dev);
75 	return 0;
76 }
77 
dummy_dev_uninit(struct net_device * dev)78 static void dummy_dev_uninit(struct net_device *dev)
79 {
80 	free_percpu(dev->lstats);
81 }
82 
dummy_change_carrier(struct net_device * dev,bool new_carrier)83 static int dummy_change_carrier(struct net_device *dev, bool new_carrier)
84 {
85 	if (new_carrier)
86 		netif_carrier_on(dev);
87 	else
88 		netif_carrier_off(dev);
89 	return 0;
90 }
91 
92 static const struct net_device_ops dummy_netdev_ops = {
93 	.ndo_init		= dummy_dev_init,
94 	.ndo_uninit		= dummy_dev_uninit,
95 	.ndo_start_xmit		= dummy_xmit,
96 	.ndo_validate_addr	= eth_validate_addr,
97 	.ndo_set_rx_mode	= set_multicast_list,
98 	.ndo_set_mac_address	= eth_mac_addr,
99 	.ndo_get_stats64	= dummy_get_stats64,
100 	.ndo_change_carrier	= dummy_change_carrier,
101 };
102 
103 static const struct ethtool_ops dummy_ethtool_ops = {
104 	.get_ts_info		= ethtool_op_get_ts_info,
105 };
106 
dummy_setup(struct net_device * dev)107 static void dummy_setup(struct net_device *dev)
108 {
109 	ether_setup(dev);
110 
111 	/* Initialize the device structure. */
112 	dev->netdev_ops = &dummy_netdev_ops;
113 	dev->ethtool_ops = &dummy_ethtool_ops;
114 	dev->needs_free_netdev = true;
115 
116 	/* Fill in device structure with ethernet-generic values. */
117 	dev->flags |= IFF_NOARP;
118 	dev->flags &= ~IFF_MULTICAST;
119 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
120 	dev->features	|= NETIF_F_SG | NETIF_F_FRAGLIST;
121 	dev->features	|= NETIF_F_GSO_SOFTWARE;
122 	dev->features	|= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
123 	dev->features	|= NETIF_F_GSO_ENCAP_ALL;
124 	dev->hw_features |= dev->features;
125 	dev->hw_enc_features |= dev->features;
126 	eth_hw_addr_random(dev);
127 
128 	dev->min_mtu = 0;
129 	dev->max_mtu = 0;
130 }
131 
dummy_validate(struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)132 static int dummy_validate(struct nlattr *tb[], struct nlattr *data[],
133 			  struct netlink_ext_ack *extack)
134 {
135 	if (tb[IFLA_ADDRESS]) {
136 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
137 			return -EINVAL;
138 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
139 			return -EADDRNOTAVAIL;
140 	}
141 	return 0;
142 }
143 
144 static struct rtnl_link_ops dummy_link_ops __read_mostly = {
145 	.kind		= DRV_NAME,
146 	.setup		= dummy_setup,
147 	.validate	= dummy_validate,
148 };
149 
150 /* Number of dummy devices to be set up by this module. */
151 module_param(numdummies, int, 0);
152 MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
153 
dummy_init_one(void)154 static int __init dummy_init_one(void)
155 {
156 	struct net_device *dev_dummy;
157 	int err;
158 
159 	dev_dummy = alloc_netdev(0, "dummy%d", NET_NAME_ENUM, dummy_setup);
160 	if (!dev_dummy)
161 		return -ENOMEM;
162 
163 	dev_dummy->rtnl_link_ops = &dummy_link_ops;
164 	err = register_netdevice(dev_dummy);
165 	if (err < 0)
166 		goto err;
167 	return 0;
168 
169 err:
170 	free_netdev(dev_dummy);
171 	return err;
172 }
173 
dummy_init_module(void)174 static int __init dummy_init_module(void)
175 {
176 	int i, err = 0;
177 
178 	down_write(&pernet_ops_rwsem);
179 	rtnl_lock();
180 	err = __rtnl_link_register(&dummy_link_ops);
181 	if (err < 0)
182 		goto out;
183 
184 	for (i = 0; i < numdummies && !err; i++) {
185 		err = dummy_init_one();
186 		cond_resched();
187 	}
188 	if (err < 0)
189 		__rtnl_link_unregister(&dummy_link_ops);
190 
191 out:
192 	rtnl_unlock();
193 	up_write(&pernet_ops_rwsem);
194 
195 	return err;
196 }
197 
dummy_cleanup_module(void)198 static void __exit dummy_cleanup_module(void)
199 {
200 	rtnl_link_unregister(&dummy_link_ops);
201 }
202 
203 module_init(dummy_init_module);
204 module_exit(dummy_cleanup_module);
205 MODULE_LICENSE("GPL");
206 MODULE_ALIAS_RTNL_LINK(DRV_NAME);
207