xen-vtx-unstable

annotate linux-2.6-xen-sparse/drivers/xen/netback/loopback.c @ 6774:4d899a738d59

merge?
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 15:05:49 2005 +0000 (2005-09-13)
parents 9ead08216805 cdfa7dd00c44
children e7c7196fa329 8ca0f98ba8e2
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 */