VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdp.c@ 67954

Last change on this file since 67954 was 62490, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.0 KB
Line 
1/* $Id: VBoxNetAdp.c 62490 2016-07-22 18:41:49Z vboxsync $ */
2/** @file
3 * VBoxNetAdp - Virtual Network Adapter Driver (Host), Common Code.
4 */
5
6/*
7 * Copyright (C) 2008-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/** @page pg_netadp VBoxNetAdp - Network Adapter
19 *
20 * This is a kernel module that creates a virtual interface that can be attached
21 * to an internal network.
22 *
23 * In the big picture we're one of the three trunk interface on the internal
24 * network, the one named "TAP Interface": @image html Networking_Overview.gif
25 *
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_NET_ADP_DRV
33#include "VBoxNetAdpInternal.h"
34
35#include <VBox/log.h>
36#include <VBox/err.h>
37#include <iprt/string.h>
38
39
40VBOXNETADP g_aAdapters[VBOXNETADP_MAX_INSTANCES];
41static uint8_t g_aUnits[VBOXNETADP_MAX_UNITS/8];
42
43
44DECLINLINE(int) vboxNetAdpGetUnitByName(const char *pcszName)
45{
46 uint32_t iUnit = RTStrToUInt32(pcszName + sizeof(VBOXNETADP_NAME) - 1);
47 bool fOld;
48
49 if (iUnit >= VBOXNETADP_MAX_UNITS)
50 return -1;
51
52 fOld = ASMAtomicBitTestAndSet(g_aUnits, iUnit);
53 return fOld ? -1 : (int)iUnit;
54}
55
56DECLINLINE(int) vboxNetAdpGetNextAvailableUnit(void)
57{
58 bool fOld;
59 int iUnit;
60 /* There is absolutely no chance that all units are taken */
61 do {
62 iUnit = ASMBitFirstClear(g_aUnits, VBOXNETADP_MAX_UNITS);
63 if (iUnit < 0)
64 break;
65 fOld = ASMAtomicBitTestAndSet(g_aUnits, iUnit);
66 } while (fOld);
67
68 return iUnit;
69}
70
71DECLINLINE(void) vboxNetAdpReleaseUnit(int iUnit)
72{
73 bool fSet = ASMAtomicBitTestAndClear(g_aUnits, iUnit);
74 NOREF(fSet);
75 Assert(fSet);
76}
77
78/**
79 * Generate a suitable MAC address.
80 *
81 * @param pThis The instance.
82 * @param pMac Where to return the MAC address.
83 */
84DECLHIDDEN(void) vboxNetAdpComposeMACAddress(PVBOXNETADP pThis, PRTMAC pMac)
85{
86 /* Use a locally administered version of the OUI we use for the guest NICs. */
87 pMac->au8[0] = 0x08 | 2;
88 pMac->au8[1] = 0x00;
89 pMac->au8[2] = 0x27;
90
91 pMac->au8[3] = 0; /* pThis->iUnit >> 16; */
92 pMac->au8[4] = 0; /* pThis->iUnit >> 8; */
93 pMac->au8[5] = pThis->iUnit;
94}
95
96int vboxNetAdpCreate(PVBOXNETADP *ppNew, const char *pcszName)
97{
98 int rc;
99 unsigned i;
100 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
101 {
102 PVBOXNETADP pThis = &g_aAdapters[i];
103
104 if (ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Transitional, kVBoxNetAdpState_Invalid))
105 {
106 RTMAC Mac;
107 /* Found an empty slot -- use it. */
108 Log(("vboxNetAdpCreate: found empty slot: %d\n", i));
109 if (pcszName)
110 {
111 Log(("vboxNetAdpCreate: using name: %s\n", pcszName));
112 pThis->iUnit = vboxNetAdpGetUnitByName(pcszName);
113 strncpy(pThis->szName, pcszName, sizeof(pThis->szName));
114 pThis->szName[sizeof(pThis->szName) - 1] = '\0';
115 }
116 else
117 {
118 pThis->iUnit = vboxNetAdpGetNextAvailableUnit();
119 pThis->szName[0] = '\0';
120 }
121 if (pThis->iUnit < 0)
122 rc = VERR_INVALID_PARAMETER;
123 else
124 {
125 vboxNetAdpComposeMACAddress(pThis, &Mac);
126 rc = vboxNetAdpOsCreate(pThis, &Mac);
127 Log(("vboxNetAdpCreate: pThis=%p pThis->iUnit=%d, pThis->szName=%s\n",
128 pThis, pThis->iUnit, pThis->szName));
129 }
130 if (RT_SUCCESS(rc))
131 {
132 *ppNew = pThis;
133 ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Active);
134 Log2(("VBoxNetAdpCreate: Created %s\n", g_aAdapters[i].szName));
135 }
136 else
137 {
138 ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Invalid);
139 Log(("vboxNetAdpCreate: vboxNetAdpOsCreate failed with '%Rrc'.\n", rc));
140 }
141 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
142 Log2(("VBoxNetAdpCreate: Scanning entry: state=%d unit=%d name=%s\n",
143 g_aAdapters[i].enmState, g_aAdapters[i].iUnit, g_aAdapters[i].szName));
144 return rc;
145 }
146 }
147 Log(("vboxNetAdpCreate: no empty slots!\n"));
148
149 /* All slots in adapter array are busy. */
150 return VERR_OUT_OF_RESOURCES;
151}
152
153int vboxNetAdpDestroy(PVBOXNETADP pThis)
154{
155 int rc = VINF_SUCCESS;
156
157 if (!ASMAtomicCmpXchgU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Transitional, kVBoxNetAdpState_Active))
158 return VERR_INTNET_FLT_IF_BUSY;
159
160 Assert(pThis->iUnit >= 0 && pThis->iUnit < VBOXNETADP_MAX_UNITS);
161 vboxNetAdpOsDestroy(pThis);
162 vboxNetAdpReleaseUnit(pThis->iUnit);
163 pThis->iUnit = -1;
164 pThis->szName[0] = '\0';
165
166 ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, kVBoxNetAdpState_Invalid);
167
168 return rc;
169}
170
171int vboxNetAdpInit(void)
172{
173 unsigned i;
174 /*
175 * Init common members and call OS-specific init.
176 */
177 memset(g_aUnits, 0, sizeof(g_aUnits));
178 memset(g_aAdapters, 0, sizeof(g_aAdapters));
179 LogFlow(("vboxnetadp: max host-only interfaces supported: %d (%d bytes)\n",
180 VBOXNETADP_MAX_INSTANCES, sizeof(g_aAdapters)));
181 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
182 {
183 g_aAdapters[i].enmState = kVBoxNetAdpState_Invalid;
184 g_aAdapters[i].iUnit = -1;
185 vboxNetAdpOsInit(&g_aAdapters[i]);
186 }
187
188 return VINF_SUCCESS;
189}
190
191/**
192 * Finds an adapter by its name.
193 *
194 * @returns Pointer to the instance by the given name. NULL if not found.
195 * @param pszName The name of the instance.
196 */
197PVBOXNETADP vboxNetAdpFindByName(const char *pszName)
198{
199 unsigned i;
200
201 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
202 {
203 PVBOXNETADP pThis = &g_aAdapters[i];
204 Log2(("VBoxNetAdp: Scanning entry: state=%d name=%s\n", pThis->enmState, pThis->szName));
205 if ( strcmp(pThis->szName, pszName) == 0
206 && ASMAtomicReadU32((uint32_t volatile *)&pThis->enmState) == kVBoxNetAdpState_Active)
207 return pThis;
208 }
209 return NULL;
210}
211
212void vboxNetAdpShutdown(void)
213{
214 unsigned i;
215
216 /* Remove virtual adapters */
217 for (i = 0; i < RT_ELEMENTS(g_aAdapters); i++)
218 vboxNetAdpDestroy(&g_aAdapters[i]);
219}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use