ia64/xen-unstable

view tools/vnet/vnet-module/vnet_dev.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 3233e7ecfa9f
children 06d84bf87159
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 }