source: trunk/packages/xen-3.1/xen-3.1/tools/vnet/vnet-module/vnet_dev.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 7.5 KB
Line 
1/*
2 * Copyright (C) 2004, 2005 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>
24
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>
30
31#include <net/ip.h>
32#include <net/protocol.h>
33
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>
39
40#include <etherip.h>
41#include <vnet.h>
42#include <varp.h>
43#include <vif.h>
44#include <vnet_dev.h>
45#include <random.h>
46
47#define MODULE_NAME "VNET"
48#define DEBUG 1
49#undef DEBUG
50#include "debug.h"
51
52#if !defined(CONFIG_BRIDGE) && !defined(CONFIG_BRIDGE_MODULE)
53#warning Should configure Ethernet Bridging in kernel Network Options
54#endif
55
56#ifndef CONFIG_BRIDGE_NETFILTER
57#warning Should configure CONFIG_BRIDGE_NETFILTER in kernel
58#endif
59
60static void vnet_dev_destructor(struct net_device *dev){
61    Vnet *vnet = dev->priv;
62    if(vnet){
63        if(vnet->dev == dev){
64            vnet->dev = NULL;
65        }
66        dev->priv = NULL;
67        Vnet_decref(vnet);
68    }
69    free_netdev(dev);
70}
71
72static struct net_device_stats *vnet_dev_get_stats(struct net_device *dev){
73    static struct net_device_stats stats = {};
74    Vnet *vnet = dev->priv;
75    return (vnet ? &vnet->stats : &stats);
76}
77
78static int vnet_dev_change_mtu(struct net_device *dev, int mtu){
79    int err = 0;
80    Vnet *vnet = dev->priv;
81    if (mtu < 68 || mtu > (vnet ? vnet->mtu : 1500)){
82        err = -EINVAL;
83        goto exit;
84    }
85    dev->mtu = mtu;
86  exit:
87    return err;
88}
89
90/** Remove the net device for a vnet.
91 * Safe to call if the vnet or its dev are null.
92 *
93 * @param vnet vnet
94 */
95void vnet_dev_remove(Vnet *vnet){
96    if(vnet && vnet->dev){
97        iprintf("> Removing vnet device %s\n", vnet->dev->name);
98        unregister_netdev(vnet->dev);
99    }
100}
101
102static int vnet_dev_open(struct net_device *dev){
103    int err = 0;
104
105    netif_start_queue(dev);
106    return err;
107}
108
109static int vnet_dev_stop(struct net_device *dev){
110    int err = 0;
111
112    netif_stop_queue(dev);
113    return err;
114}
115
116static int vnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev){
117    int err = 0;
118    Vnet *vnet = dev->priv;
119    int len = 0;
120
121    if(!skb){
122        wprintf("> skb NULL!\n");
123        return -EINVAL;
124    }
125    if(!vnet){
126        return -ENOTCONN;
127    }
128    if(vnet->recursion++) {
129        extern void print_skb(const char *msg, int count, struct sk_buff *skb);
130        char vnetbuf[VNET_ID_BUF];
131       
132        vnet->stats.collisions++;
133        vnet->stats.tx_errors++;
134        wprintf("> recursion! vnet=%s\n", VnetId_ntoa(&vnet->vnet, vnetbuf));
135        print_skb("RECURSION", 0, skb);
136        varp_print(iostdout);
137        kfree_skb(skb);
138        goto exit;
139    }
140    if(!skb->mac.raw){
141        skb->mac.raw = skb->data;
142    }       
143    len = skb->len;
144    // Must not use skb pointer after vnet_skb_send().
145    err = vnet_skb_send(skb, &vnet->vnet);
146    if(err < 0){
147        vnet->stats.tx_errors++;
148    } else {
149        vnet->stats.tx_packets++;
150        vnet->stats.tx_bytes += len;
151    }
152  exit:
153    vnet->recursion--;
154    return 0;
155}
156
157void vnet_dev_set_multicast_list(struct net_device *dev){
158}
159
160#if 0
161static int vnet_dev_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){
162    int err = 0;
163   
164    return err;
165}
166
167void vnet_dev_tx_timeout(struct net_device *dev){
168    //dev->trans_start = jiffies;
169    //netif_wake_queue(dev);
170}
171
172static int (*eth_hard_header)(struct sk_buff *skb,
173                              struct net_device *dev, unsigned short type,
174                              void *daddr, void *saddr, unsigned len) = NULL;
175
176static int vnet_dev_hard_header(struct sk_buff *skb,
177                                struct net_device *dev, unsigned short type,
178                                void *daddr, void *saddr, unsigned len){
179    int err = 0;
180
181    err = eth_hard_header(skb, dev, type, daddr, saddr, len);
182    if(err) goto exit;
183    skb->mac.raw = skb->data;
184  exit:
185    return err;
186}
187#endif
188
189int vnet_device_mac(const char *device, unsigned char *mac){
190    int err;
191    struct net_device *dev;
192
193    err = vnet_get_device(device, &dev);
194    if(err) goto exit;
195    memcpy(mac, dev->dev_addr, ETH_ALEN);
196    dev_put(dev);
197  exit:
198    return err;
199}
200
201void vnet_dev_mac(unsigned char *mac){
202    mac[0] = 0xAA;
203    mac[1] = 0xFF;
204    get_random_bytes(mac + 2, 4);
205}
206
207/** Initial setup of the device for a vnet.
208 */
209static void vnet_dev_init(struct net_device *dev){
210    ether_setup(dev);
211
212#if 0
213    if(!eth_hard_header){
214        eth_hard_header = dev->hard_header;
215    }
216    dev->hard_header          = vnet_dev_hard_header;
217    //dev->do_ioctl             = vnet_dev_do_ioctl;
218    //dev->tx_timeout           = vnet_dev_tx_timeout;
219    //dev->watchdog_timeo       = TX_TIMEOUT;
220   
221#endif
222
223    dev->open                 = vnet_dev_open;
224    dev->stop                 = vnet_dev_stop;
225    dev->destructor           = vnet_dev_destructor;
226    dev->hard_start_xmit      = vnet_dev_hard_start_xmit;
227    dev->get_stats            = vnet_dev_get_stats;
228    dev->change_mtu           = vnet_dev_change_mtu;
229    dev->set_multicast_list   = vnet_dev_set_multicast_list;
230
231    dev->flags |= IFF_DEBUG;
232    dev->flags |= IFF_PROMISC;
233    dev->flags |= IFF_ALLMULTI;
234
235    vnet_dev_mac(dev->dev_addr);
236}
237
238/** Complete the setup of the device for a vnet.
239 * Associate the device and the vnet and set mtu etc.
240 */
241static int vnet_dev_setup(Vnet *vnet, struct net_device *dev){
242    int err;
243
244    Vnet_incref(vnet);
245    dev->priv = vnet;
246    vnet->dev = dev;
247    dev->hard_header_len += vnet->header_n;
248    if(!etherip_in_udp){
249        dev->mtu -= vnet->header_n;
250    }
251    vnet->mtu = dev->mtu;
252    iprintf("> Adding vnet device %s\n", dev->name);
253    err = register_netdev(dev);
254    if(err){
255        eprintf("> register_netdev(%s) = %d\n", dev->name, err);
256        vnet_dev_destructor(dev);
257    }
258    return err;
259}
260
261static inline int roundupto(int n, int k){
262    return k * ((n + k - 1) / k);
263}
264
265/** Add the interface (net device) for a vnet.
266 * Sets the dev field of the vnet on success.
267 * Does nothing if the vnet already has an interface.
268 *
269 * @param vnet vnet
270 * @return 0 on success, error code otherwise
271 */
272int vnet_dev_add(Vnet *vnet){
273    int err = 0;
274    struct net_device *dev = NULL;
275
276    if(vnet->dev) goto exit;
277    vnet->header_n = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct etheriphdr);
278    if(etherip_in_udp){
279        vnet->header_n += sizeof(struct VnetMsgHdr);
280        vnet->header_n += sizeof(struct udphdr);
281    }
282    vnet->header_n = roundupto(vnet->header_n, 4);
283    dev = alloc_netdev(0, vnet->device, vnet_dev_init);
284    if(!dev){
285        err = -ENOMEM;
286        goto exit;
287    }
288    err = vnet_dev_setup(vnet, dev);
289    if(err) goto exit;
290    rtnl_lock();
291    dev_open(dev);
292    rtnl_unlock();
293
294  exit:
295    return err;
296}
Note: See TracBrowser for help on using the repository browser.