ia64/xen-unstable

view tools/vnet/vnet-module/tunnel.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/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 }