VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxTAP/instance.c@ 4642

Last change on this file since 4642 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.5 KB
Line 
1/*
2 * TAP-Win32 -- A kernel driver to provide virtual tap device
3 * functionality on Windows. Originally derived
4 * from the CIPE-Win32 project by Damion K. Wilson,
5 * with extensive modifications by James Yonan.
6 *
7 * All source code which derives from the CIPE-Win32 project is
8 * Copyright (C) Damion K. Wilson, 2003, and is released under the
9 * GPL version 2 (see below).
10 *
11 * All other source code is Copyright (C) 2002-2005 OpenVPN Solutions LLC,
12 * and is released under the GPL version 2 (see below).
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2
16 * as published by the Free Software Foundation.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program (see the file COPYING included with this
25 * distribution); if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 */
28
29#define INSTANCE_KEY(a) ((PVOID)((a)->m_Extension.m_TapDevice))
30
31#define N_INSTANCE_BUCKETS 256
32
33typedef struct _INSTANCE {
34 struct _INSTANCE *next;
35 TapAdapterPointer m_Adapter;
36} INSTANCE;
37
38typedef struct {
39 INSTANCE *list;
40 MUTEX lock;
41} INSTANCE_BUCKET;
42
43typedef struct {
44 INSTANCE_BUCKET buckets[N_INSTANCE_BUCKETS];
45} INSTANCE_HASH;
46
47INSTANCE_HASH *g_InstanceHash = NULL;
48
49// must return a hash >= 0 and < N_INSTANCE_BUCKETS
50int
51InstanceHashValue (PVOID addr)
52{
53 UCHAR *p = (UCHAR *) &addr;
54
55 if (sizeof (addr) == 4)
56 return p[0] ^ p[1] ^ p[2] ^ p[3];
57 else if (sizeof (addr) == 8)
58 return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ p[7];
59 else
60 {
61 MYASSERT (0);
62 }
63}
64
65BOOLEAN
66InitInstanceList (VOID)
67{
68 MYASSERT (g_InstanceHash == NULL);
69 g_InstanceHash = MemAlloc (sizeof (INSTANCE_HASH), TRUE);
70 if (g_InstanceHash)
71 {
72 int i;
73 for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
74 INIT_MUTEX (&g_InstanceHash->buckets[i].lock);
75 return TRUE;
76 }
77 else
78 return FALSE;
79}
80
81int
82NInstances (VOID)
83{
84 int i, n = 0;
85
86 if (g_InstanceHash)
87 {
88 for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
89 {
90 BOOLEAN got_lock;
91 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
92 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
93
94 if (got_lock)
95 {
96 INSTANCE *current;
97 for (current = ib->list; current != NULL; current = current->next)
98 ++n;
99 RELEASE_MUTEX (&ib->lock);
100 }
101 else
102 return -1;
103 }
104 }
105
106 return n;
107}
108
109int
110InstanceMaxBucketSize (VOID)
111{
112 int i, n = 0;
113
114 if (g_InstanceHash)
115 {
116 for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
117 {
118 BOOLEAN got_lock;
119 int bucket_size = 0;
120 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
121 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
122
123 if (got_lock)
124 {
125 INSTANCE *current;
126 for (current = ib->list; current != NULL; current = current->next)
127 ++bucket_size;
128 if (bucket_size > n)
129 n = bucket_size;
130 RELEASE_MUTEX (&ib->lock);
131 }
132 else
133 return -1;
134 }
135 }
136
137 return n;
138}
139
140VOID
141FreeInstanceList (VOID)
142{
143 if (g_InstanceHash)
144 {
145 MYASSERT (NInstances() == 0);
146 MemFree (g_InstanceHash, sizeof (INSTANCE_HASH));
147 g_InstanceHash = NULL;
148 }
149}
150
151BOOLEAN
152AddAdapterToInstanceList (TapAdapterPointer p_Adapter)
153{
154 BOOLEAN got_lock;
155 BOOLEAN ret = FALSE;
156 const int hash = InstanceHashValue(INSTANCE_KEY(p_Adapter));
157 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[hash];
158
159 DEBUGP (("[TAP] AddAdapterToInstanceList hash=%d\n", hash));
160
161 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
162
163 if (got_lock)
164 {
165 INSTANCE *i = MemAlloc (sizeof (INSTANCE), FALSE);
166 if (i)
167 {
168 MYASSERT (p_Adapter);
169 i->m_Adapter = p_Adapter;
170 i->next = ib->list;
171 ib->list = i;
172 ret = TRUE;
173 }
174 RELEASE_MUTEX (&ib->lock);
175 }
176
177 return ret;
178}
179
180BOOLEAN
181RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter)
182{
183 BOOLEAN got_lock;
184 BOOLEAN ret = FALSE;
185 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue(INSTANCE_KEY(p_Adapter))];
186
187 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
188
189 if (got_lock)
190 {
191 INSTANCE *current, *prev=NULL;
192 for (current = ib->list; current != NULL; current = current->next)
193 {
194 if (current->m_Adapter == p_Adapter) // found match
195 {
196 if (prev)
197 prev->next = current->next;
198 else
199 ib->list = current->next;
200 MemFree (current->m_Adapter, sizeof (TapAdapter));
201 MemFree (current, sizeof (INSTANCE));
202 ret = TRUE;
203 break;
204 }
205 prev = current;
206 }
207 RELEASE_MUTEX (&ib->lock);
208 }
209
210 return ret;
211}
212
213TapAdapterPointer
214LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject)
215{
216 BOOLEAN got_lock;
217 TapAdapterPointer ret = NULL;
218 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue((PVOID)p_DeviceObject)];
219
220 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
221
222 if (got_lock)
223 {
224 INSTANCE *current, *prev=NULL;
225 for (current = ib->list; current != NULL; current = current->next)
226 {
227 if (p_DeviceObject == INSTANCE_KEY (current->m_Adapter)) // found match
228 {
229 // move it to head of list
230 if (prev)
231 {
232 prev->next = current->next;
233 current->next = ib->list;
234 ib->list = current;
235 }
236 ret = ib->list->m_Adapter;
237 break;
238 }
239 prev = current;
240 }
241 RELEASE_MUTEX (&ib->lock);
242 }
243
244 return ret;
245}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette