Blame view

drivers/net/dummy.c 5.55 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
  /* dummy.c: a dummy net driver
  
  	The purpose of this driver is to provide a device to point a
  	route through, but not to actually transmit packets.
  
  	Why?  If you have a machine whose only connection is an occasional
  	PPP/SLIP/PLIP link, you can only connect to your own hostname
  	when the link is up.  Otherwise you have to use localhost.
  	This isn't very consistent.
  
  	One solution is to set up a dummy link using PPP/SLIP/PLIP,
  	but this seems (to me) too much overhead for too little gain.
  	This driver provides a small alternative. Thus you can do
6aa20a223   Jeff Garzik   drivers/net: Trim...
14

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  	[when not running slip]
  		ifconfig dummy slip.addr.ess.here up
  	[to go to slip]
  		ifconfig dummy down
  		dip whatever
  
  	This was written by looking at Donald Becker's skeleton driver
  	and the loopback driver.  I then threw away anything that didn't
  	apply!	Thanks to Alan Cox for the key clue on what to do with
  	misguided packets.
  
  			Nick Holloway, 27th May 1994
  	[I tweaked this explanation a little but that's all]
  			Alan Cox, 30th May 1994
  */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
35
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/init.h>
  #include <linux/moduleparam.h>
206c9fb26   Patrick McHardy   [DUMMY]: Keep dum...
36
  #include <linux/rtnetlink.h>
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
37
  #include <net/rtnetlink.h>
6d81f41c5   Eric Dumazet   dummy: percpu sta...
38
  #include <linux/u64_stats_sync.h>
206c9fb26   Patrick McHardy   [DUMMY]: Keep dum...
39

c19be735c   Flavio Leitner   dummy: add suppor...
40
41
  #define DRV_NAME	"dummy"
  #define DRV_VERSION	"1.0"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  static int numdummies = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
  /* fake multicast ability */
  static void set_multicast_list(struct net_device *dev)
  {
  }
6d81f41c5   Eric Dumazet   dummy: percpu sta...
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  struct pcpu_dstats {
  	u64			tx_packets;
  	u64			tx_bytes;
  	struct u64_stats_sync	syncp;
  };
  
  static struct rtnl_link_stats64 *dummy_get_stats64(struct net_device *dev,
  						   struct rtnl_link_stats64 *stats)
  {
  	int i;
  
  	for_each_possible_cpu(i) {
  		const struct pcpu_dstats *dstats;
  		u64 tbytes, tpackets;
  		unsigned int start;
  
  		dstats = per_cpu_ptr(dev->dstats, i);
  		do {
57a7744e0   Eric W. Biederman   net: Replace u64_...
65
  			start = u64_stats_fetch_begin_irq(&dstats->syncp);
6d81f41c5   Eric Dumazet   dummy: percpu sta...
66
67
  			tbytes = dstats->tx_bytes;
  			tpackets = dstats->tx_packets;
57a7744e0   Eric W. Biederman   net: Replace u64_...
68
  		} while (u64_stats_fetch_retry_irq(&dstats->syncp, start));
6d81f41c5   Eric Dumazet   dummy: percpu sta...
69
70
71
72
73
  		stats->tx_bytes += tbytes;
  		stats->tx_packets += tpackets;
  	}
  	return stats;
  }
424efe9ca   Stephen Hemminger   netdev: convert p...
74
75
76
  
  static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
  {
6d81f41c5   Eric Dumazet   dummy: percpu sta...
77
78
79
80
81
82
  	struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
  
  	u64_stats_update_begin(&dstats->syncp);
  	dstats->tx_packets++;
  	dstats->tx_bytes += skb->len;
  	u64_stats_update_end(&dstats->syncp);
424efe9ca   Stephen Hemminger   netdev: convert p...
83
84
85
86
  
  	dev_kfree_skb(skb);
  	return NETDEV_TX_OK;
  }
6d81f41c5   Eric Dumazet   dummy: percpu sta...
87
88
  static int dummy_dev_init(struct net_device *dev)
  {
1c213bd24   WANG Cong   net: introduce ne...
89
  	dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
6d81f41c5   Eric Dumazet   dummy: percpu sta...
90
91
92
93
94
  	if (!dev->dstats)
  		return -ENOMEM;
  
  	return 0;
  }
890fdf2a0   Hiroaki SHIMODA   dummy: Add ndo_un...
95
  static void dummy_dev_uninit(struct net_device *dev)
6d81f41c5   Eric Dumazet   dummy: percpu sta...
96
97
  {
  	free_percpu(dev->dstats);
6d81f41c5   Eric Dumazet   dummy: percpu sta...
98
  }
210ab6656   Jiri Pirko   dummy: implement ...
99
100
101
102
103
104
105
106
  static int dummy_change_carrier(struct net_device *dev, bool new_carrier)
  {
  	if (new_carrier)
  		netif_carrier_on(dev);
  	else
  		netif_carrier_off(dev);
  	return 0;
  }
aa18e9e88   Stephen Hemminger   dummy: convert to...
107
  static const struct net_device_ops dummy_netdev_ops = {
6d81f41c5   Eric Dumazet   dummy: percpu sta...
108
  	.ndo_init		= dummy_dev_init,
890fdf2a0   Hiroaki SHIMODA   dummy: Add ndo_un...
109
  	.ndo_uninit		= dummy_dev_uninit,
aa18e9e88   Stephen Hemminger   dummy: convert to...
110
111
  	.ndo_start_xmit		= dummy_xmit,
  	.ndo_validate_addr	= eth_validate_addr,
afc4b13df   Jiri Pirko   net: remove use o...
112
  	.ndo_set_rx_mode	= set_multicast_list,
0d1632b46   Jiri Pirko   dummy: use IFF_LI...
113
  	.ndo_set_mac_address	= eth_mac_addr,
6d81f41c5   Eric Dumazet   dummy: percpu sta...
114
  	.ndo_get_stats64	= dummy_get_stats64,
210ab6656   Jiri Pirko   dummy: implement ...
115
  	.ndo_change_carrier	= dummy_change_carrier,
aa18e9e88   Stephen Hemminger   dummy: convert to...
116
  };
c19be735c   Flavio Leitner   dummy: add suppor...
117
118
119
120
121
122
123
124
125
126
  static void dummy_get_drvinfo(struct net_device *dev,
  			      struct ethtool_drvinfo *info)
  {
  	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
  	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
  }
  
  static const struct ethtool_ops dummy_ethtool_ops = {
  	.get_drvinfo            = dummy_get_drvinfo,
  };
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
127
  static void dummy_setup(struct net_device *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  {
aa18e9e88   Stephen Hemminger   dummy: convert to...
129
  	ether_setup(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
  	/* Initialize the device structure. */
aa18e9e88   Stephen Hemminger   dummy: convert to...
131
  	dev->netdev_ops = &dummy_netdev_ops;
c19be735c   Flavio Leitner   dummy: add suppor...
132
  	dev->ethtool_ops = &dummy_ethtool_ops;
890fdf2a0   Hiroaki SHIMODA   dummy: Add ndo_un...
133
  	dev->destructor = free_netdev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  
  	/* Fill in device structure with ethernet-generic values. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
  	dev->flags |= IFF_NOARP;
  	dev->flags &= ~IFF_MULTICAST;
ff42c02c0   Phil Sutter   net: dummy: conve...
138
  	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
8f3af2778   Eric Dumazet   net: dummy: add m...
139
140
  	dev->features	|= NETIF_F_SG | NETIF_F_FRAGLIST;
  	dev->features	|= NETIF_F_ALL_TSO | NETIF_F_UFO;
34324dc2b   Michał Mirosław   net: remove NETIF...
141
  	dev->features	|= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
8f3af2778   Eric Dumazet   net: dummy: add m...
142
143
144
  	dev->features	|= NETIF_F_GSO_ENCAP_ALL;
  	dev->hw_features |= dev->features;
  	dev->hw_enc_features |= dev->features;
7ce5d2221   Danny Kukawka   net: use eth_hw_a...
145
  	eth_hw_addr_random(dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  }
6d81f41c5   Eric Dumazet   dummy: percpu sta...
147

0e06877c6   Patrick McHardy   [RTNETLINK]: rtnl...
148
149
150
151
152
153
154
155
156
157
  static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
  {
  	if (tb[IFLA_ADDRESS]) {
  		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
  			return -EINVAL;
  		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
  			return -EADDRNOTAVAIL;
  	}
  	return 0;
  }
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
158
  static struct rtnl_link_ops dummy_link_ops __read_mostly = {
c19be735c   Flavio Leitner   dummy: add suppor...
159
  	.kind		= DRV_NAME,
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
160
  	.setup		= dummy_setup,
0e06877c6   Patrick McHardy   [RTNETLINK]: rtnl...
161
  	.validate	= dummy_validate,
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
162
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
  /* Number of dummy devices to be set up by this module. */
  module_param(numdummies, int, 0);
  MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
206c9fb26   Patrick McHardy   [DUMMY]: Keep dum...
166
  static int __init dummy_init_one(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
169
  {
  	struct net_device *dev_dummy;
  	int err;
c835a6773   Tom Gundersen   net: set name_ass...
170
  	dev_dummy = alloc_netdev(0, "dummy%d", NET_NAME_UNKNOWN, dummy_setup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
  	if (!dev_dummy)
  		return -ENOMEM;
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
173
174
175
176
  	dev_dummy->rtnl_link_ops = &dummy_link_ops;
  	err = register_netdevice(dev_dummy);
  	if (err < 0)
  		goto err;
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
177
  	return 0;
206c9fb26   Patrick McHardy   [DUMMY]: Keep dum...
178

5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
179
180
181
  err:
  	free_netdev(dev_dummy);
  	return err;
6aa20a223   Jeff Garzik   drivers/net: Trim...
182
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
  
  static int __init dummy_init_module(void)
6aa20a223   Jeff Garzik   drivers/net: Trim...
185
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  	int i, err = 0;
206c9fb26   Patrick McHardy   [DUMMY]: Keep dum...
187

5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
188
189
  	rtnl_lock();
  	err = __rtnl_link_register(&dummy_link_ops);
2c8a01894   dingtianhong   dummy: fix oops w...
190
191
  	if (err < 0)
  		goto out;
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
192

16b0dc29c   Eric Dumazet   dummy: fix rcu_sc...
193
  	for (i = 0; i < numdummies && !err; i++) {
206c9fb26   Patrick McHardy   [DUMMY]: Keep dum...
194
  		err = dummy_init_one();
16b0dc29c   Eric Dumazet   dummy: fix rcu_sc...
195
196
  		cond_resched();
  	}
2d85cba2b   Patrick McHardy   [RTNETLINK]: rtnl...
197
  	if (err < 0)
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
198
  		__rtnl_link_unregister(&dummy_link_ops);
2c8a01894   dingtianhong   dummy: fix oops w...
199
200
  
  out:
5d5cb173d   Patrick McHardy   [DUMMY]: Use rtnl...
201
  	rtnl_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  	return err;
6aa20a223   Jeff Garzik   drivers/net: Trim...
203
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
  
  static void __exit dummy_cleanup_module(void)
  {
2d85cba2b   Patrick McHardy   [RTNETLINK]: rtnl...
207
  	rtnl_link_unregister(&dummy_link_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
211
212
  }
  
  module_init(dummy_init_module);
  module_exit(dummy_cleanup_module);
  MODULE_LICENSE("GPL");
c19be735c   Flavio Leitner   dummy: add suppor...
213
  MODULE_ALIAS_RTNL_LINK(DRV_NAME);
6c702fab6   Flavio Leitner   dummy: use MODULE...
214
  MODULE_VERSION(DRV_VERSION);