ia64/xen-unstable

view tools/vnet/vnet-module/tunnel.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/init.h>
23 #include <linux/net.h>
24 #include <linux/in.h>
25 #include <linux/inet.h>
26 #include <linux/netdevice.h>
28 #include <net/ip.h>
29 #include <net/protocol.h>
30 #include <net/route.h>
31 #include <linux/skbuff.h>
33 #include <tunnel.h>
34 #include <vnet.h>
35 #include <varp.h>
36 #include "hash_table.h"
38 #define MODULE_NAME "VNET"
39 #define DEBUG 1
40 #undef DEBUG
41 #include "debug.h"
43 void Tunnel_print(Tunnel *tunnel){
44 if(tunnel){
45 printk("Tunnel<%p base=%p ref=%02d type=%s>\n",
46 tunnel,
47 tunnel->base,
48 atomic_read(&tunnel->refcount),
49 tunnel->type->name);
50 if(tunnel->base){
51 Tunnel_print(tunnel->base);
52 }
53 } else {
54 printk("Tunnel<%p base=%p ref=%02d type=%s>\n",
55 NULL, NULL, 0, "ip");
56 }
57 }
59 int Tunnel_create(TunnelType *type, VnetId *vnet, VarpAddr *addr, Tunnel *base, Tunnel **val){
60 int err = 0;
61 Tunnel *tunnel = NULL;
62 if(!type || !type->open || !type->send || !type->close){
63 err = -EINVAL;
64 goto exit;
65 }
66 tunnel = kmalloc(sizeof(Tunnel), GFP_ATOMIC);
67 if(!tunnel){
68 err = -ENOMEM;
69 goto exit;
70 }
71 atomic_set(&tunnel->refcount, 1);
72 tunnel->key.vnet = *vnet;
73 tunnel->key.addr = *addr;
74 tunnel->type = type;
75 tunnel->data = NULL;
76 tunnel->send_stats = (TunnelStats){};
77 Tunnel_incref(base);
78 tunnel->base = base;
79 err = type->open(tunnel);
80 exit:
81 if(err && tunnel){
82 Tunnel_decref(tunnel);
83 tunnel = NULL;
84 }
85 *val = tunnel;
86 dprintf("< err=%d\n", err);
87 return err;
88 }
90 int Tunnel_open(TunnelType *type, VnetId *vnet, VarpAddr *addr, Tunnel *base, Tunnel **tunnel){
91 int err = 0;
93 dprintf(">\n");
94 err = Tunnel_create(type, vnet, addr, base, tunnel);
95 if(err) goto exit;
96 err = Tunnel_add(*tunnel);
97 exit:
98 if(err){
99 Tunnel_decref(*tunnel);
100 *tunnel = NULL;
101 }
102 dprintf("< err=%d\n", err);
103 return err;
104 }
106 void TunnelStats_update(TunnelStats *stats, int len, int err){
107 dprintf(">len=%d err=%d\n", len, err);
108 if(err){
109 stats->dropped_bytes += len;
110 stats->dropped_packets++;
111 } else {
112 stats->bytes += len;
113 stats->packets++;
114 }
115 dprintf("<\n");
116 }
118 /** Table of tunnels, indexed by vnet and addr. */
119 HashTable *tunnel_table = NULL;
121 static inline Hashcode tunnel_table_key_hash_fn(void *k){
122 TunnelKey *key = k;
123 Hashcode h = 0;
124 h = VnetId_hash(h, &key->vnet);
125 h = VarpAddr_hash(h, &key->addr);
126 return h;
127 }
129 static int tunnel_table_key_equal_fn(void *k1, void *k2){
130 TunnelKey *key1 = k1;
131 TunnelKey *key2 = k2;
132 return VnetId_eq(&key1->vnet, &key2->vnet) &&
133 VarpAddr_eq(&key1->addr, &key2->addr);
134 }
136 static void tunnel_table_entry_free_fn(HashTable *table, HTEntry *entry){
137 Tunnel *tunnel;
138 if(!entry) return;
139 tunnel = entry->value;
140 //dprintf(">\n"); Tunnel_print(tunnel);
141 Tunnel_decref(tunnel);
142 HTEntry_free(entry);
143 }
145 int Tunnel_init(void){
146 int err = 0;
147 dprintf(">\n");
148 tunnel_table = HashTable_new(0);
149 if(!tunnel_table){
150 err = -ENOMEM;
151 goto exit;
152 }
153 tunnel_table->entry_free_fn = tunnel_table_entry_free_fn;
154 tunnel_table->key_hash_fn = tunnel_table_key_hash_fn;
155 tunnel_table->key_equal_fn = tunnel_table_key_equal_fn;
156 exit:
157 dprintf("< err=%d\n", err);
158 return err;
159 }
161 /** Lookup tunnel state by vnet and destination.
162 *
163 * @param vnet vnet
164 * @param addr destination address
165 * @return tunnel state or NULL
166 */
167 Tunnel * Tunnel_lookup(VnetId *vnet, VarpAddr *addr){
168 Tunnel *tunnel = NULL;
169 TunnelKey key = {.vnet = *vnet, .addr = *addr };
170 dprintf(">\n");
171 tunnel = HashTable_get(tunnel_table, &key);
172 Tunnel_incref(tunnel);
173 dprintf("< tunnel=%p\n", tunnel);
174 return tunnel;
175 }
177 int Tunnel_add(Tunnel *tunnel){
178 int err = 0;
179 dprintf(">\n");
180 if(HashTable_add(tunnel_table, tunnel, tunnel)){
181 Tunnel_incref(tunnel);
182 } else {
183 err = -ENOMEM;
184 }
185 dprintf("< err=%d\n", err);
186 return err;
187 }
189 int Tunnel_del(Tunnel *tunnel){
190 return HashTable_remove(tunnel_table, tunnel);
191 }
193 /** Do tunnel send processing on a packet.
194 *
195 * @param tunnel tunnel state
196 * @param skb packet
197 * @return 0 on success, error code otherwise
198 */
199 int Tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
200 int err = 0;
201 dprintf("> tunnel=%p skb=%p\n", tunnel, skb);
202 if(tunnel){
203 int len = skb->len;
204 dprintf("> type=%s type->send...\n", tunnel->type->name);
205 // Must not refer to skb after sending - might have been freed.
206 err = tunnel->type->send(tunnel, skb);
207 TunnelStats_update(&tunnel->send_stats, len, err);
208 } else {
209 err = skb_xmit(skb);
210 }
211 dprintf("< err=%d\n", err);
212 return err;
213 }
215 int __init tunnel_module_init(void){
216 return Tunnel_init();
217 }
219 void __exit tunnel_module_exit(void){
220 if(tunnel_table){
221 HashTable_free(tunnel_table);
222 tunnel_table = NULL;
223 }
224 }