rev |
line source |
kaf24@4938
|
1 /******************************************************************************
|
kaf24@4938
|
2 * netback/loopback.c
|
kaf24@4938
|
3 *
|
kaf24@4938
|
4 * A two-interface loopback device to emulate a local netfront-netback
|
kaf24@4938
|
5 * connection. This ensures that local packet delivery looks identical
|
kaf24@4938
|
6 * to inter-domain delivery. Most importantly, packets delivered locally
|
kaf24@4938
|
7 * originating from other domains will get *copied* when they traverse this
|
kaf24@4938
|
8 * driver. This prevents unbounded delays in socket-buffer queues from
|
kaf24@4938
|
9 * causing the netback driver to "seize up".
|
kaf24@4938
|
10 *
|
kaf24@4938
|
11 * This driver creates a symmetric pair of loopback interfaces with names
|
kaf24@4938
|
12 * vif0.0 and veth0. The intention is that 'vif0.0' is bound to an Ethernet
|
kaf24@4938
|
13 * bridge, just like a proper netback interface, while a local IP interface
|
kaf24@4938
|
14 * is configured on 'veth0'.
|
kaf24@4938
|
15 *
|
kaf24@4938
|
16 * As with a real netback interface, vif0.0 is configured with a suitable
|
kaf24@4938
|
17 * dummy MAC address. No default is provided for veth0: a reasonable strategy
|
kaf24@4938
|
18 * is to transfer eth0's MAC address to veth0, and give eth0 a dummy address
|
kaf24@4938
|
19 * (to avoid confusing the Etherbridge).
|
kaf24@4938
|
20 *
|
kaf24@4938
|
21 * Copyright (c) 2005 K A Fraser
|
kaf24@4938
|
22 */
|
kaf24@4938
|
23
|
kaf24@4938
|
24 #include <linux/config.h>
|
kaf24@4938
|
25 #include <linux/module.h>
|
kaf24@4938
|
26 #include <linux/netdevice.h>
|
kaf24@4938
|
27 #include <linux/inetdevice.h>
|
kaf24@4938
|
28 #include <linux/etherdevice.h>
|
kaf24@4938
|
29 #include <linux/skbuff.h>
|
kaf24@4938
|
30 #include <net/dst.h>
|
kaf24@4938
|
31
|
kaf24@6694
|
32 static int nloopbacks = 1;
|
kaf24@6694
|
33 module_param(nloopbacks, int, 0);
|
kaf24@6694
|
34 MODULE_PARM_DESC(nloopbacks, "Number of netback-loopback devices to create");
|
kaf24@6694
|
35
|
kaf24@4938
|
36 struct net_private {
|
kaf24@6694
|
37 struct net_device *loopback_dev;
|
kaf24@6694
|
38 struct net_device_stats stats;
|
kaf24@4938
|
39 };
|
kaf24@4938
|
40
|
kaf24@4938
|
41 static int loopback_open(struct net_device *dev)
|
kaf24@4938
|
42 {
|
kaf24@6694
|
43 struct net_private *np = netdev_priv(dev);
|
kaf24@6694
|
44 memset(&np->stats, 0, sizeof(np->stats));
|
kaf24@6694
|
45 netif_start_queue(dev);
|
kaf24@6694
|
46 return 0;
|
kaf24@4938
|
47 }
|
kaf24@4938
|
48
|
kaf24@4938
|
49 static int loopback_close(struct net_device *dev)
|
kaf24@4938
|
50 {
|
kaf24@6694
|
51 netif_stop_queue(dev);
|
kaf24@6694
|
52 return 0;
|
kaf24@4938
|
53 }
|
kaf24@4938
|
54
|
kaf24@4938
|
55 static int loopback_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
kaf24@4938
|
56 {
|
kaf24@6694
|
57 struct net_private *np = netdev_priv(dev);
|
kaf24@4938
|
58
|
kaf24@6694
|
59 dst_release(skb->dst);
|
kaf24@6694
|
60 skb->dst = NULL;
|
kaf24@4938
|
61
|
kaf24@6694
|
62 skb_orphan(skb);
|
kaf24@4938
|
63
|
kaf24@6694
|
64 np->stats.tx_bytes += skb->len;
|
kaf24@6694
|
65 np->stats.tx_packets++;
|
kaf24@4938
|
66
|
kaf24@6694
|
67 /* Switch to loopback context. */
|
kaf24@6694
|
68 dev = np->loopback_dev;
|
kaf24@6694
|
69 np = netdev_priv(dev);
|
kaf24@4938
|
70
|
kaf24@6694
|
71 np->stats.rx_bytes += skb->len;
|
kaf24@6694
|
72 np->stats.rx_packets++;
|
kaf24@4938
|
73
|
kaf24@6694
|
74 if (skb->ip_summed == CHECKSUM_HW) {
|
kaf24@6694
|
75 /* Defer checksum calculation. */
|
kaf24@6694
|
76 skb->proto_csum_blank = 1;
|
kaf24@6694
|
77 /* Must be a local packet: assert its integrity. */
|
kaf24@6694
|
78 skb->proto_csum_valid = 1;
|
kaf24@6694
|
79 }
|
kaf24@5095
|
80
|
kaf24@6694
|
81 skb->ip_summed = skb->proto_csum_valid ?
|
kaf24@6694
|
82 CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
|
kaf24@5077
|
83
|
kaf24@6694
|
84 skb->pkt_type = PACKET_HOST; /* overridden by eth_type_trans() */
|
kaf24@6694
|
85 skb->protocol = eth_type_trans(skb, dev);
|
kaf24@6694
|
86 skb->dev = dev;
|
kaf24@6694
|
87 dev->last_rx = jiffies;
|
kaf24@6694
|
88 netif_rx(skb);
|
kaf24@4938
|
89
|
kaf24@6694
|
90 return 0;
|
kaf24@4938
|
91 }
|
kaf24@4938
|
92
|
kaf24@4938
|
93 static struct net_device_stats *loopback_get_stats(struct net_device *dev)
|
kaf24@4938
|
94 {
|
kaf24@6694
|
95 struct net_private *np = netdev_priv(dev);
|
kaf24@6694
|
96 return &np->stats;
|
kaf24@4938
|
97 }
|
kaf24@4938
|
98
|
kaf24@4938
|
99 static void loopback_construct(struct net_device *dev, struct net_device *lo)
|
kaf24@4938
|
100 {
|
kaf24@6694
|
101 struct net_private *np = netdev_priv(dev);
|
kaf24@6694
|
102
|
kaf24@6694
|
103 np->loopback_dev = lo;
|
kaf24@4938
|
104
|
kaf24@6694
|
105 dev->open = loopback_open;
|
kaf24@6694
|
106 dev->stop = loopback_close;
|
kaf24@6694
|
107 dev->hard_start_xmit = loopback_start_xmit;
|
kaf24@6694
|
108 dev->get_stats = loopback_get_stats;
|
kaf24@6694
|
109
|
kaf24@6694
|
110 dev->tx_queue_len = 0;
|
kaf24@6694
|
111
|
kaf24@6694
|
112 dev->features = NETIF_F_HIGHDMA | NETIF_F_LLTX;
|
kaf24@4938
|
113
|
kaf24@6694
|
114 /*
|
kaf24@6694
|
115 * We do not set a jumbo MTU on the interface. Otherwise the network
|
kaf24@6694
|
116 * stack will try to send large packets that will get dropped by the
|
kaf24@6694
|
117 * Ethernet bridge (unless the physical Ethernet interface is
|
kaf24@6694
|
118 * configured to transfer jumbo packets). If a larger MTU is desired
|
kaf24@6694
|
119 * then the system administrator can specify it using the 'ifconfig'
|
kaf24@6694
|
120 * command.
|
kaf24@6694
|
121 */
|
kaf24@6694
|
122 /*dev->mtu = 16*1024;*/
|
kaf24@6694
|
123 }
|
kaf24@4938
|
124
|
kaf24@6694
|
125 static int __init make_loopback(int i)
|
kaf24@6694
|
126 {
|
kaf24@6694
|
127 struct net_device *dev1, *dev2;
|
kaf24@6694
|
128 char dev_name[IFNAMSIZ];
|
kaf24@6694
|
129 int err = -ENOMEM;
|
kaf24@5006
|
130
|
kaf24@6694
|
131 sprintf(dev_name, "vif0.%d", i);
|
kaf24@6694
|
132 dev1 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
|
kaf24@6694
|
133 sprintf(dev_name, "veth%d", i);
|
kaf24@6694
|
134 dev2 = alloc_netdev(sizeof(struct net_private), dev_name, ether_setup);
|
kaf24@6694
|
135 if ((dev1 == NULL) || (dev2 == NULL))
|
kaf24@6694
|
136 goto fail;
|
kaf24@6694
|
137
|
kaf24@6694
|
138 loopback_construct(dev1, dev2);
|
kaf24@6694
|
139 loopback_construct(dev2, dev1);
|
kaf24@6694
|
140
|
kaf24@6694
|
141 dev1->features |= NETIF_F_NO_CSUM;
|
kaf24@6694
|
142 dev2->features |= NETIF_F_IP_CSUM;
|
kaf24@5077
|
143
|
kaf24@6694
|
144 /*
|
kaf24@6694
|
145 * Initialise a dummy MAC address for the 'dummy backend' interface. We
|
kaf24@6694
|
146 * choose the numerically largest non-broadcast address to prevent the
|
kaf24@6694
|
147 * address getting stolen by an Ethernet bridge for STP purposes.
|
kaf24@6694
|
148 */
|
kaf24@6694
|
149 memset(dev1->dev_addr, 0xFF, ETH_ALEN);
|
kaf24@6694
|
150 dev1->dev_addr[0] &= ~0x01;
|
kaf24@6694
|
151
|
kaf24@6694
|
152 if ((err = register_netdev(dev1)) != 0)
|
kaf24@6694
|
153 goto fail;
|
kaf24@6694
|
154
|
kaf24@6694
|
155 if ((err = register_netdev(dev2)) != 0) {
|
kaf24@6694
|
156 unregister_netdev(dev1);
|
kaf24@6694
|
157 goto fail;
|
kaf24@6694
|
158 }
|
kaf24@6694
|
159
|
kaf24@6694
|
160 return 0;
|
kaf24@6694
|
161
|
kaf24@6694
|
162 fail:
|
kaf24@6694
|
163 if (dev1 != NULL)
|
kaf24@6694
|
164 kfree(dev1);
|
kaf24@6694
|
165 if (dev2 != NULL)
|
kaf24@6694
|
166 kfree(dev2);
|
kaf24@6694
|
167 return err;
|
kaf24@4938
|
168 }
|
kaf24@4938
|
169
|
kaf24@4938
|
170 static int __init loopback_init(void)
|
kaf24@4938
|
171 {
|
kaf24@6694
|
172 int i, err = 0;
|
kaf24@5077
|
173
|
kaf24@6694
|
174 for (i = 0; i < nloopbacks; i++)
|
kaf24@6694
|
175 if ((err = make_loopback(i)) != 0)
|
kaf24@6694
|
176 break;
|
kaf24@4938
|
177
|
kaf24@6694
|
178 return err;
|
kaf24@4938
|
179 }
|
kaf24@4938
|
180
|
kaf24@4938
|
181 module_init(loopback_init);
|
kaf24@6694
|
182
|
kaf24@6694
|
183 /*
|
kaf24@6694
|
184 * Local variables:
|
kaf24@6694
|
185 * c-file-style: "linux"
|
kaf24@6694
|
186 * indent-tabs-mode: t
|
kaf24@6694
|
187 * c-indent-level: 8
|
kaf24@6694
|
188 * c-basic-offset: 8
|
kaf24@6694
|
189 * tab-width: 8
|
kaf24@6694
|
190 * End:
|
kaf24@6694
|
191 */
|