ia64/xen-unstable

view tools/vnet/vnet-module/vif.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 */
20 #include <linux/config.h>
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/string.h>
25 #include <linux/version.h>
27 #include <linux/net.h>
28 #include <linux/in.h>
29 #include <linux/inet.h>
30 #include <linux/netdevice.h>
31 #include <linux/udp.h>
33 #include <net/ip.h>
34 #include <net/protocol.h>
35 #include <net/route.h>
36 #include <linux/skbuff.h>
37 #include <linux/spinlock.h>
39 #include <etherip.h>
40 #include <if_varp.h>
41 #include <vnet_dev.h>
42 #include <vif.h>
43 #include <varp.h>
45 #include "allocate.h"
46 #include "hash_table.h"
47 #include "sys_net.h"
48 #include "sys_string.h"
50 #define MODULE_NAME "VNET"
51 #define DEBUG 1
52 #undef DEBUG
53 #include "debug.h"
55 /** Table of vifs indexed by VifKey. */
56 HashTable *vif_table = NULL;
57 rwlock_t vif_table_lock = RW_LOCK_UNLOCKED;
59 #define vif_read_lock(flags) read_lock_irqsave(&vif_table_lock, (flags))
60 #define vif_read_unlock(flags) read_unlock_irqrestore(&vif_table_lock, (flags))
61 #define vif_write_lock(flags) write_lock_irqsave(&vif_table_lock, (flags))
62 #define vif_write_unlock(flags) write_unlock_irqrestore(&vif_table_lock, (flags))
64 void vif_print(void){
65 HashTable_for_decl(entry);
66 Vif *vif;
67 unsigned long flags;
68 char vnetbuf[VNET_ID_BUF];
70 vif_read_lock(flags);
71 HashTable_for_each(entry, vif_table){
72 vif = entry->value;
73 printk(KERN_INFO "VIF(vnet=%s vmac=" MACFMT ")\n",
74 VnetId_ntoa(&vif->vnet, vnetbuf), MAC6TUPLE(vif->vmac.mac));
75 }
76 vif_read_unlock(flags);
77 }
79 void vif_decref(Vif *vif){
80 if(!vif) return;
81 if(atomic_dec_and_test(&vif->refcount)){
82 kfree(vif);
83 }
84 }
86 void vif_incref(Vif *vif){
87 if(!vif) return;
88 atomic_inc(&vif->refcount);
89 }
91 /** Hash function for keys in the vif table.
92 * Hashes the vnet id and mac.
93 *
94 * @param k key (VifKey)
95 * @return hashcode
96 */
97 Hashcode vif_key_hash_fn(void *k){
98 VifKey *key = k;
99 Hashcode h = 0;
100 h = VnetId_hash(h, &key->vnet);
101 h = Vmac_hash(h, &key->vmac);
102 return h;
103 }
105 /** Test equality for keys in the vif table.
106 * Compares vnet and mac.
107 *
108 * @param k1 key to compare (VifKey)
109 * @param k2 key to compare (VifKey)
110 * @return 1 if equal, 0 otherwise
111 */
112 int vif_key_equal_fn(void *k1, void *k2){
113 VifKey *key1 = k1;
114 VifKey *key2 = k2;
115 return (VnetId_eq(&key1->vnet , &key2->vnet) &&
116 Vmac_eq(&key1->vmac, &key2->vmac));
117 }
119 /** Free an entry in the vif table.
120 *
121 * @param table containing table
122 * @param entry entry to free
123 */
124 static void vif_entry_free_fn(HashTable *table, HTEntry *entry){
125 Vif *vif;
126 if(!entry) return;
127 vif = entry->value;
128 if(vif){
129 vif_decref(vif);
130 }
131 HTEntry_free(entry);
132 }
134 /** Lookup a vif.
135 *
136 * @param vnet vnet id
137 * @param mac MAC address
138 * @return 0 on success, -ENOENT otherwise
139 */
140 int vif_lookup(VnetId *vnet, Vmac *vmac, Vif **vif){
141 int err = 0;
142 VifKey key = { .vnet = *vnet, .vmac = *vmac };
143 HTEntry *entry = NULL;
144 unsigned long flags;
146 vif_read_lock(flags);
147 entry = HashTable_get_entry(vif_table, &key);
148 if(entry){
149 *vif = entry->value;
150 vif_incref(*vif);
151 } else {
152 *vif = NULL;
153 err = -ENOENT;
154 }
155 vif_read_unlock(flags);
156 return err;
157 }
159 /** Create a new vif.
160 *
161 * @param vnet vnet id
162 * @param mac MAC address
163 * @return 0 on success, negative error code otherwise
164 */
165 int vif_add(VnetId *vnet, Vmac *vmac, Vif **val){
166 int err = 0;
167 Vif *vif = NULL;
168 HTEntry *entry;
169 unsigned long flags;
171 dprintf("> vnet=%d\n", vnet);
172 vif = ALLOCATE(Vif);
173 if(!vif){
174 err = -ENOMEM;
175 goto exit;
176 }
177 atomic_set(&vif->refcount, 1);
178 vif->vnet = *vnet;
179 vif->vmac = *vmac;
180 vif_write_lock(flags);
181 entry = HashTable_add(vif_table, vif, vif);
182 vif_write_unlock(flags);
183 if(!entry){
184 err = -ENOMEM;
185 deallocate(vif);
186 vif = NULL;
187 goto exit;
188 }
189 vif_incref(vif);
190 exit:
191 *val = (err ? NULL : vif);
192 dprintf("< err=%d\n", err);
193 return err;
194 }
196 /** Delete an entry.
197 *
198 * @param vnet vnet id
199 * @param mac MAC address
200 * @param coaddr return parameter for care-of address
201 * @return number of entries deleted, or negative error code
202 */
203 int vif_remove(VnetId *vnet, Vmac *vmac){
204 int err = 0;
205 VifKey key = { .vnet = *vnet, .vmac = *vmac };
206 unsigned long flags;
208 vif_write_lock(flags);
209 err = HashTable_remove(vif_table, &key);
210 vif_write_unlock(flags);
211 return err;
212 }
214 void vif_purge(void){
215 HashTable_clear(vif_table);
216 }
218 int vif_create(VnetId *vnet, Vmac *vmac, Vif **vif){
219 int err = 0;
221 dprintf(">\n");
222 if(vif_lookup(vnet, vmac, vif) == 0){
223 vif_decref(*vif);
224 err = -EEXIST;
225 goto exit;
226 }
227 err = vif_add(vnet, vmac, vif);
228 exit:
229 if(err){
230 *vif = NULL;
231 }
232 dprintf("< err=%d\n", err);
233 return err;
234 }
236 /** Initialize the vif table.
237 *
238 * @return 0 on success, error code otherwise
239 */
240 int vif_init(void){
241 int err = 0;
242 dprintf(">\n");
243 vif_table = HashTable_new(0);
244 if(!vif_table){
245 err = -ENOMEM;
246 goto exit;
247 }
248 vif_table->entry_free_fn = vif_entry_free_fn;
249 vif_table->key_hash_fn = vif_key_hash_fn;
250 vif_table->key_equal_fn = vif_key_equal_fn;
252 exit:
253 if(err < 0) wprintf("< err=%d\n", err);
254 dprintf("< err=%d\n", err);
255 return err;
256 }
258 void vif_exit(void){
259 HashTable_free(vif_table);
260 }