ia64/xen-unstable

view tools/vnet/vnet-module/vnet_dev.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents 06d84bf87159
children 71b0f00f6344
line source
1 /*
2 * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free software Foundation, Inc.,
16 * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19 #include <linux/config.h>
20 #include <linux/module.h>
21 #include <linux/types.h>
22 #include <linux/sched.h>
23 #include <linux/kernel.h>
25 #include <linux/skbuff.h>
26 #include <linux/netdevice.h>
27 #include <linux/in.h>
28 #include <linux/tcp.h>
29 #include <linux/udp.h>
31 #include <net/ip.h>
32 #include <net/protocol.h>
34 #include <linux/if_arp.h>
35 #include <linux/in6.h>
36 #include <linux/inetdevice.h>
37 #include <linux/arcdevice.h>
38 #include <linux/if_bridge.h>
40 #include <etherip.h>
41 #include <vnet.h>
42 #include <varp.h>
43 #include <vif.h>
44 #include <vnet_dev.h>
46 #define MODULE_NAME "VNET"
47 #define DEBUG 1
48 #undef DEBUG
49 #include "debug.h"
51 #ifndef CONFIG_BRIDGE
52 #error Must configure ethernet bridging in Network Options
53 #endif
55 static void vnet_dev_destructor(struct net_device *dev){
56 dprintf(">\n");
57 dev->open = NULL;
58 dev->stop = NULL;
59 dev->uninit = NULL;
60 dev->destructor = NULL;
61 dev->hard_start_xmit = NULL;
62 dev->get_stats = NULL;
63 dev->do_ioctl = NULL;
64 dev->change_mtu = NULL;
66 dev->tx_timeout = NULL;
67 dev->set_multicast_list = NULL;
68 dev->flags = 0;
70 dev->priv = NULL;
71 }
73 static void vnet_dev_uninit(struct net_device *dev){
74 //Vnet *vnet = dev->priv;
75 dprintf(">\n");
76 //dev_put(dev);
77 dprintf("<\n");
78 }
80 static struct net_device_stats *vnet_dev_get_stats(struct net_device *dev){
81 Vnet *vnet = dev->priv;
82 //dprintf(">\n");
83 return &vnet->stats;
84 }
86 static int vnet_dev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){
87 int err = 0;
89 dprintf(">\n");
90 return err;
91 }
93 static int vnet_dev_change_mtu(struct net_device *dev, int mtu){
94 int err = 0;
95 Vnet *vnet = dev->priv;
96 if (mtu < 68 || mtu > 1500 - vnet->header_n){
97 err = -EINVAL;
98 goto exit;
99 }
100 dev->mtu = mtu;
101 exit:
102 return err;
103 }
105 static int vnet_dev_set_name(struct net_device *dev){
106 int err = 0;
107 Vnet *vnet = (void*)dev->priv;
109 dprintf(">\n");
110 if(__dev_get_by_name(vnet->device)){
111 err = -ENOMEM;
112 wprintf("> vnet device name in use: %s\n", vnet->device);
113 }
114 strcpy(dev->name, vnet->device);
115 dprintf("< err=%d\n", err);
116 return err;
117 }
119 /** Create the virtual interface for a vnet.
120 *
121 * @param info vnet
122 * @return 0 on success, error code otherwise
123 */
124 int Vnet_create(Vnet *info){
125 int err = 0;
127 err = vnet_dev_add(info);
128 if(err) goto exit;
129 err = Vnet_add(info);
130 exit:
131 return err;
132 }
134 /** Remove the net device for a vnet.
135 * Clears the dev field of the vnet.
136 * Safe to call if the vnet or its dev are null.
137 *
138 * @param vnet vnet
139 */
140 void vnet_dev_remove(Vnet *vnet){
141 if(!vnet) return;
142 if(vnet->dev){
143 //dev_put(vnet->dev);
144 dprintf("> unregister_netdev(%s)\n", vnet->dev->name);
145 unregister_netdev(vnet->dev);
146 vnet->dev = NULL;
147 }
148 }
150 static int vnet_dev_open(struct net_device *dev){
151 int err = 0;
152 dprintf(">\n");
153 netif_start_queue(dev);
154 dprintf("<\n");
155 return err;
156 }
158 static int vnet_dev_stop(struct net_device *dev){
159 int err = 0;
160 dprintf(">\n");
161 netif_stop_queue(dev);
162 dprintf("<\n");
163 return err;
164 }
166 static int vnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev){
167 int err = 0;
168 Vnet *vnet = dev->priv;
169 int len = 0;
171 dprintf("> skb=%p\n", skb);
172 if(vnet->recursion++) {
173 vnet->stats.collisions++;
174 vnet->stats.tx_errors++;
175 wprintf("> recursion!\n");
176 dev_kfree_skb(skb);
177 goto exit;
178 }
179 if(!skb){
180 err = -EINVAL;
181 wprintf("> skb NULL!\n");
182 goto exit;
183 }
184 dprintf("> skb->data=%p skb->mac.raw=%p\n", skb->data, skb->mac.raw);
185 if(skb->mac.raw < skb->data || skb->mac.raw > skb->nh.raw){
186 wprintf("> skb mac duff!\n");
187 skb->mac.raw = skb->data;
188 }
189 //dev->trans_start = jiffies;
190 len = skb->len;
191 // Must not use skb pointer after vnet_skb_send().
192 err = vnet_skb_send(skb, &vnet->vnet);
193 if(err < 0){
194 vnet->stats.tx_errors++;
195 } else {
196 vnet->stats.tx_packets++;
197 vnet->stats.tx_bytes += len;
198 }
199 exit:
200 vnet->recursion--;
201 dprintf("<\n");
202 return 0;
203 }
205 void vnet_dev_tx_timeout(struct net_device *dev){
206 dprintf(">\n");
207 //dev->trans_start = jiffies;
208 //netif_wake_queue(dev);
209 }
211 void vnet_dev_set_multicast_list(struct net_device *dev){
212 dprintf(">\n");
213 }
215 static int (*eth_hard_header)(struct sk_buff *skb,
216 struct net_device *dev, unsigned short type,
217 void *daddr, void *saddr, unsigned len) = NULL;
219 static int vnet_dev_hard_header(struct sk_buff *skb,
220 struct net_device *dev, unsigned short type,
221 void *daddr, void *saddr, unsigned len){
222 int err = 0;
224 err = eth_hard_header(skb, dev, type, daddr, saddr, len);
225 if(err) goto exit;
226 skb->mac.raw = skb->data;
227 exit:
228 return err;
229 }
231 void vnet_default_mac(unsigned char *mac)
232 {
233 static unsigned val = 1;
234 mac[0] = 0xAA;
235 mac[1] = 0xFF;
236 mac[2] = (unsigned char)((val >> 24) & 0xff);
237 mac[3] = (unsigned char)((val >> 16) & 0xff);
238 mac[4] = (unsigned char)((val >> 8) & 0xff);
239 mac[5] = (unsigned char)((val ) & 0xff);
240 val++;
241 }
243 int vnet_device_mac(const char *device, unsigned char *mac){
244 int err;
245 struct net_device *dev;
247 err = vnet_get_device(device, &dev);
248 if(err) goto exit;
249 memcpy(mac, dev->dev_addr, ETH_ALEN);
250 dev_put(dev);
251 exit:
252 return err;
253 }
255 void vnet_dev_mac(unsigned char *mac){
256 const char *devices[] = { "eth0", "eth1", "eth2", NULL };
257 const char **pdev;
258 int err = -ENODEV;
260 for(pdev = devices; err && *pdev; pdev++){
261 err = vnet_device_mac(*pdev, mac);
262 }
263 if(err){
264 vnet_default_mac(mac);
265 }
266 }
268 static int vnet_dev_init(struct net_device *dev){
269 int err = 0;
270 Vnet *vnet = (void*)dev->priv;
272 dprintf(">\n");
273 ether_setup(dev);
275 if(!eth_hard_header){
276 eth_hard_header = dev->hard_header;
277 }
278 dev->hard_header = vnet_dev_hard_header;
280 dev->open = vnet_dev_open;
281 dev->stop = vnet_dev_stop;
282 dev->uninit = vnet_dev_uninit;
283 dev->destructor = vnet_dev_destructor;
284 dev->hard_start_xmit = vnet_dev_hard_start_xmit;
285 dev->get_stats = vnet_dev_get_stats;
286 dev->do_ioctl = vnet_dev_do_ioctl;
287 dev->change_mtu = vnet_dev_change_mtu;
289 dev->tx_timeout = vnet_dev_tx_timeout;
290 dev->watchdog_timeo = TX_TIMEOUT;
291 dev->set_multicast_list = vnet_dev_set_multicast_list;
293 dev->hard_header_len += vnet->header_n;
294 dev->mtu -= vnet->header_n;
296 vnet_dev_mac(dev->dev_addr);
298 dev->flags |= IFF_DEBUG;
299 dev->flags |= IFF_PROMISC;
300 dev->flags |= IFF_ALLMULTI;
302 dprintf("<\n");
303 return err;
304 }
306 /** Add the interface (net device) for a vnet.
307 * Sets the dev field of the vnet on success.
308 * Does nothing if the vif already has an interface.
309 *
310 * @param vif vif
311 * @return 0 on success, error code otherwise
312 */
313 int vnet_dev_add(Vnet *vnet){
314 int err = 0;
315 struct net_device *dev = NULL;
317 dprintf("> vnet=%p\n", vnet);
318 if(vnet->dev) goto exit;
319 vnet->header_n = sizeof(struct iphdr) + sizeof(struct etheriphdr);
320 dev = kmalloc(sizeof(struct net_device), GFP_ATOMIC);
321 if(!dev){
322 err = -ENOMEM;
323 goto exit;
324 }
325 *dev = (struct net_device){};
326 dev->priv = vnet;
327 vnet->dev = dev;
329 err = vnet_dev_set_name(dev);
330 if(err) goto exit;
331 vnet_dev_init(dev);
332 err = register_netdev(dev);
333 if(err){
334 wprintf("> register_netdev(%s) = %d\n", dev->name, err);
335 }
336 if(err) goto exit;
337 rtnl_lock();
338 dev_open(dev);
339 rtnl_unlock();
341 //dev_hold(dev);
342 exit:
343 if(err){
344 if(dev) kfree(dev);
345 vnet->dev = NULL;
346 }
347 dprintf("< err=%d\n", err);
348 return err;
349 }