VirtualBox

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

Last change on this file since 79812 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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