Changeset 71235 in vbox for trunk/src/VBox
- Timestamp:
- Mar 6, 2018 11:09:36 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetLwf-win.cpp
r69500 r71235 178 178 /** MAC address of underlying adapter */ 179 179 RTMAC MacAddr; 180 /** Size of offload config structure */ 181 USHORT cbOffloadConfig; 180 182 /** Saved offload configuration */ 181 NDIS_OFFLOAD SavedOffloadConfig; 183 PNDIS_OFFLOAD pSavedOffloadConfig; 184 /** Temporary buffer for disabling offload configuration */ 185 PNDIS_OFFLOAD pDisabledOffloadConfig; 182 186 /** the cloned request we have passed down */ 183 187 PNDIS_OID_REQUEST pPendingRequest; … … 999 1003 } 1000 1004 1001 static void vboxNetLwfWinUpdateSavedOffloadConfig(PVBOXNETLWF_MODULE pModuleCtx, PNDIS_OFFLOAD pOffload)1002 {1003 pModuleCtx->SavedOffloadConfig = *pOffload;1004 pModuleCtx->fOffloadConfigValid = true;1005 }1006 1007 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS1008 static void vboxNetLwfWinFreePools(PVBOXNETLWF_MODULE pModuleCtx, int cPools)1009 {1010 for (int i = 0; i < cPools; ++i)1011 {1012 if (pModuleCtx->hPool[i])1013 {1014 NdisFreeNetBufferListPool(pModuleCtx->hPool[i]);1015 Log4(("vboxNetLwfWinAttach: freeed NBL+NB pool 0x%p\n", pModuleCtx->hPool[i]));1016 }1017 }1018 }1019 #endif /* VBOXNETLWF_FIXED_SIZE_POOLS */1020 1021 DECLARE_GLOBAL_CONST_UNICODE_STRING(g_strHostOnlyMiniportName, L"VirtualBox Host-Only");1022 1023 static NDIS_STATUS vboxNetLwfWinAttach(IN NDIS_HANDLE hFilter, IN NDIS_HANDLE hDriverCtx,1024 IN PNDIS_FILTER_ATTACH_PARAMETERS pParameters)1025 {1026 LogFlow(("==>vboxNetLwfWinAttach: filter=%p\n", hFilter));1027 1028 PVBOXNETLWFGLOBALS pGlobals = (PVBOXNETLWFGLOBALS)hDriverCtx;1029 if (!pGlobals)1030 {1031 vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 1);1032 return NDIS_STATUS_FAILURE;1033 }1034 1035 /*1036 * We need a copy of NDIS_STRING structure as we are going to modify length1037 * of the base miniport instance name since RTL does not support comparing1038 * first n characters of two strings. We check if miniport names start with1039 * "Virtual Host-Only" to detect host-only adapters. It is a waste of resources1040 * to bind our filter to host-only adapters since they now operate independently.1041 */1042 NDIS_STRING strTruncatedInstanceName = *pParameters->BaseMiniportInstanceName; /* Do not copy data, only the structure itself */1043 strTruncatedInstanceName.Length = g_strHostOnlyMiniportName.Length; /* Truncate instance name */1044 if (RtlEqualUnicodeString(&strTruncatedInstanceName, &g_strHostOnlyMiniportName, TRUE /* Case insensitive */))1045 {1046 DbgPrint("vboxNetLwfWinAttach: won't attach to %wZ\n", pParameters->BaseMiniportInstanceName);1047 return NDIS_STATUS_FAILURE;1048 }1049 1050 ANSI_STRING strMiniportName;1051 /* We use the miniport name to associate this filter module with the netflt instance */1052 NTSTATUS rc = RtlUnicodeStringToAnsiString(&strMiniportName,1053 pParameters->BaseMiniportName,1054 TRUE);1055 if (rc != STATUS_SUCCESS)1056 {1057 LogError(("vboxNetLwfWinAttach: RtlUnicodeStringToAnsiString(%ls) failed with 0x%x\n",1058 pParameters->BaseMiniportName, rc));1059 vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 2);1060 return NDIS_STATUS_FAILURE;1061 }1062 DbgPrint("vboxNetLwfWinAttach: friendly name=%wZ\n", pParameters->BaseMiniportInstanceName);1063 DbgPrint("vboxNetLwfWinAttach: name=%Z\n", &strMiniportName);1064 1065 UINT cbModuleWithNameExtra = sizeof(VBOXNETLWF_MODULE) + strMiniportName.Length;1066 PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)NdisAllocateMemoryWithTagPriority(hFilter,1067 cbModuleWithNameExtra,1068 VBOXNETLWF_MEM_TAG,1069 LowPoolPriority);1070 if (!pModuleCtx)1071 {1072 LogError(("vboxNetLwfWinAttach: Failed to allocate module context for %ls\n", pParameters->BaseMiniportName));1073 RtlFreeAnsiString(&strMiniportName);1074 vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 3);1075 return NDIS_STATUS_RESOURCES;1076 }1077 Log4(("vboxNetLwfWinAttach: allocated module context 0x%p\n", pModuleCtx));1078 1079 NdisZeroMemory(pModuleCtx, cbModuleWithNameExtra);1080 NdisMoveMemory(pModuleCtx->szMiniportName, strMiniportName.Buffer, strMiniportName.Length);1081 RtlFreeAnsiString(&strMiniportName);1082 1083 pModuleCtx->hWorkItem = NdisAllocateIoWorkItem(g_VBoxNetLwfGlobals.hFilterDriver);1084 if (!pModuleCtx->hWorkItem)1085 {1086 LogError(("vboxNetLwfWinAttach: Failed to allocate work item for %ls\n",1087 pParameters->BaseMiniportName));1088 NdisFreeMemory(pModuleCtx, 0, 0);1089 vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 4);1090 return NDIS_STATUS_RESOURCES;1091 }1092 1093 Assert(pParameters->MacAddressLength == sizeof(RTMAC));1094 NdisMoveMemory(&pModuleCtx->MacAddr, pParameters->CurrentMacAddress, RT_MIN(sizeof(RTMAC), pParameters->MacAddressLength));1095 if (pParameters->DefaultOffloadConfiguration)1096 vboxNetLwfWinUpdateSavedOffloadConfig(pModuleCtx, pParameters->DefaultOffloadConfiguration);1097 1098 pModuleCtx->pGlobals = pGlobals;1099 pModuleCtx->hFilter = hFilter;1100 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Attaching);1101 /* Initialize transmission mutex and events */1102 NDIS_INIT_MUTEX(&pModuleCtx->InTransmit);1103 #ifdef VBOXNETLWF_SYNC_SEND1104 KeInitializeEvent(&pModuleCtx->EventWire, SynchronizationEvent, FALSE);1105 KeInitializeEvent(&pModuleCtx->EventHost, SynchronizationEvent, FALSE);1106 #else /* !VBOXNETLWF_SYNC_SEND */1107 NdisInitializeEvent(&pModuleCtx->EventSendComplete);1108 pModuleCtx->cPendingBuffers = 0;1109 #endif /* !VBOXNETLWF_SYNC_SEND */1110 1111 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS1112 for (int i = 0; i < RT_ELEMENTS(g_cbPool); ++i)1113 {1114 /* Allocate buffer pools */1115 NET_BUFFER_LIST_POOL_PARAMETERS PoolParams;1116 NdisZeroMemory(&PoolParams, sizeof(PoolParams));1117 PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;1118 PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;1119 PoolParams.Header.Size = sizeof(PoolParams);1120 PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;1121 PoolParams.fAllocateNetBuffer = TRUE;1122 PoolParams.ContextSize = 0; /** @todo Do we need to consider underlying drivers? I think not. */1123 PoolParams.PoolTag = VBOXNETLWF_MEM_TAG;1124 PoolParams.DataSize = g_cbPool[i];1125 pModuleCtx->hPool[i] = NdisAllocateNetBufferListPool(hFilter, &PoolParams);1126 if (!pModuleCtx->hPool[i])1127 {1128 LogError(("vboxNetLwfWinAttach: NdisAllocateNetBufferListPool failed\n"));1129 vboxNetLwfWinFreePools(pModuleCtx, i);1130 NdisFreeIoWorkItem(pModuleCtx->hWorkItem);1131 NdisFreeMemory(pModuleCtx, 0, 0);1132 vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 7);1133 return NDIS_STATUS_RESOURCES;1134 }1135 Log4(("vboxNetLwfWinAttach: allocated NBL+NB pool (data size=%u) 0x%p\n",1136 PoolParams.DataSize, pModuleCtx->hPool[i]));1137 }1138 #else /* !VBOXNETLWF_FIXED_SIZE_POOLS */1139 /* Allocate buffer pools */1140 NET_BUFFER_LIST_POOL_PARAMETERS PoolParams;1141 NdisZeroMemory(&PoolParams, sizeof(PoolParams));1142 PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;1143 PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;1144 PoolParams.Header.Size = sizeof(PoolParams);1145 PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT;1146 PoolParams.fAllocateNetBuffer = TRUE;1147 PoolParams.ContextSize = 0; /** @todo Do we need to consider underlying drivers? I think not. */1148 PoolParams.PoolTag = VBOXNETLWF_MEM_TAG;1149 pModuleCtx->hPool = NdisAllocateNetBufferListPool(hFilter, &PoolParams);1150 if (!pModuleCtx->hPool)1151 {1152 LogError(("vboxNetLwfWinAttach: NdisAllocateNetBufferListPool failed\n"));1153 NdisFreeIoWorkItem(pModuleCtx->hWorkItem);1154 NdisFreeMemory(pModuleCtx, 0, 0);1155 vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 7);1156 return NDIS_STATUS_RESOURCES;1157 }1158 Log4(("vboxNetLwfWinAttach: allocated NBL+NB pool 0x%p\n", pModuleCtx->hPool));1159 #endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */1160 1161 NDIS_FILTER_ATTRIBUTES Attributes;1162 NdisZeroMemory(&Attributes, sizeof(Attributes));1163 Attributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;1164 Attributes.Header.Size = sizeof(Attributes);1165 Attributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;1166 Attributes.Flags = 0;1167 NDIS_STATUS Status = NdisFSetAttributes(hFilter, pModuleCtx, &Attributes);1168 if (Status != NDIS_STATUS_SUCCESS)1169 {1170 LogError(("vboxNetLwfWinAttach: NdisFSetAttributes failed with 0x%x\n", Status));1171 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS1172 vboxNetLwfWinFreePools(pModuleCtx, RT_ELEMENTS(g_cbPool));1173 #else /* !VBOXNETLWF_FIXED_SIZE_POOLS */1174 NdisFreeNetBufferListPool(pModuleCtx->hPool);1175 Log4(("vboxNetLwfWinAttach: freed NBL+NB pool 0x%p\n", pModuleCtx->hPool));1176 #endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */1177 NdisFreeIoWorkItem(pModuleCtx->hWorkItem);1178 NdisFreeMemory(pModuleCtx, 0, 0);1179 vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_RESOURCES, 5);1180 return NDIS_STATUS_RESOURCES;1181 }1182 /* Insert into module chain */1183 NdisAcquireSpinLock(&pGlobals->Lock);1184 RTListPrepend(&pGlobals->listModules, &pModuleCtx->node);1185 NdisReleaseSpinLock(&pGlobals->Lock);1186 1187 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused);1188 1189 /// @todo Somehow the packet filter is 0 at this point: Status = vboxNetLwfWinGetPacketFilter(pModuleCtx);1190 /// @todo We actually update it later in status handler, perhaps we should not do anything here.1191 1192 LogFlow(("<==vboxNetLwfWinAttach: Status = 0x%x\n", Status));1193 return Status;1194 }1195 1196 static VOID vboxNetLwfWinDetach(IN NDIS_HANDLE hModuleCtx)1197 {1198 LogFlow(("==>vboxNetLwfWinDetach: module=%p\n", hModuleCtx));1199 PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;1200 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Detached, LwfState_Paused);1201 1202 /* Remove from module chain */1203 NdisAcquireSpinLock(&pModuleCtx->pGlobals->Lock);1204 RTListNodeRemove(&pModuleCtx->node);1205 NdisReleaseSpinLock(&pModuleCtx->pGlobals->Lock);1206 1207 PVBOXNETFLTINS pNetFltIns = pModuleCtx->pNetFlt; /// @todo Atomic?1208 if (pNetFltIns && vboxNetFltTryRetainBusyNotDisconnected(pNetFltIns))1209 {1210 /*1211 * Set hModuleCtx to null now in order to prevent filter restart,1212 * OID requests and other stuff associated with NetFlt deactivation.1213 */1214 pNetFltIns->u.s.WinIf.hModuleCtx = NULL;1215 /* Notify NetFlt that we are going down */1216 pNetFltIns->pSwitchPort->pfnDisconnect(pNetFltIns->pSwitchPort, &pNetFltIns->MyPort, vboxNetFltPortReleaseBusy);1217 /* We do not 'release' netflt instance since it has been done by pfnDisconnect */1218 }1219 pModuleCtx->pNetFlt = NULL;1220 1221 /*1222 * We have to make sure that all NET_BUFFER_LIST structures have been freed by now, but1223 * it does not require us to do anything here since it has already been taken care of1224 * by vboxNetLwfWinPause().1225 */1226 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS1227 vboxNetLwfWinFreePools(pModuleCtx, RT_ELEMENTS(g_cbPool));1228 #else /* !VBOXNETLWF_FIXED_SIZE_POOLS */1229 if (pModuleCtx->hPool)1230 {1231 NdisFreeNetBufferListPool(pModuleCtx->hPool);1232 Log4(("vboxNetLwfWinDetach: freed NBL+NB pool 0x%p\n", pModuleCtx->hPool));1233 }1234 #endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */1235 NdisFreeIoWorkItem(pModuleCtx->hWorkItem);1236 NdisFreeMemory(hModuleCtx, 0, 0);1237 Log4(("vboxNetLwfWinDetach: freed module context 0x%p\n", pModuleCtx));1238 LogFlow(("<==vboxNetLwfWinDetach\n"));1239 }1240 1241 1242 static NDIS_STATUS vboxNetLwfWinPause(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_PAUSE_PARAMETERS pParameters)1243 {1244 RT_NOREF1(pParameters);1245 LogFlow(("==>vboxNetLwfWinPause: module=%p\n", hModuleCtx));1246 PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;1247 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Pausing, LwfState_Running);1248 /* Wait for pending send/indication operations to complete. */1249 NDIS_WAIT_FOR_MUTEX(&pModuleCtx->InTransmit);1250 #ifndef VBOXNETLWF_SYNC_SEND1251 NdisWaitEvent(&pModuleCtx->EventSendComplete, 1000 /* ms */);1252 #endif /* !VBOXNETLWF_SYNC_SEND */1253 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused, LwfState_Pausing);1254 NDIS_RELEASE_MUTEX(&pModuleCtx->InTransmit);1255 LogFlow(("<==vboxNetLwfWinPause\n"));1256 return NDIS_STATUS_SUCCESS; /* Failure is not an option */1257 }1258 1259 1260 static void vboxNetLwfWinIndicateOffload(PVBOXNETLWF_MODULE pModuleCtx, PNDIS_OFFLOAD pOffload)1261 {1262 Log5(("vboxNetLwfWinIndicateOffload: offload config changed to:\n"));1263 vboxNetLwfWinDumpOffloadSettings(pOffload);1264 NDIS_STATUS_INDICATION OffloadingIndication;1265 NdisZeroMemory(&OffloadingIndication, sizeof(OffloadingIndication));1266 OffloadingIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;1267 OffloadingIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;1268 OffloadingIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;1269 OffloadingIndication.SourceHandle = pModuleCtx->hFilter;1270 OffloadingIndication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;1271 OffloadingIndication.StatusBuffer = pOffload;1272 OffloadingIndication.StatusBufferSize = sizeof(NDIS_OFFLOAD);1273 NdisFIndicateStatus(pModuleCtx->hFilter, &OffloadingIndication);1274 }1275 1276 1277 static NDIS_STATUS vboxNetLwfWinRestart(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_RESTART_PARAMETERS pParameters)1278 {1279 RT_NOREF1(pParameters);1280 LogFlow(("==>vboxNetLwfWinRestart: module=%p\n", hModuleCtx));1281 PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx;1282 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Restarting, LwfState_Paused);1283 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Running, LwfState_Restarting);1284 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;1285 LogFlow(("<==vboxNetLwfWinRestart: Status = 0x%x\n", Status));1286 return Status;1287 }1288 1289 1290 static void vboxNetLwfWinDestroySG(PINTNETSG pSG)1291 {1292 NdisFreeMemory(pSG, 0, 0);1293 Log4(("vboxNetLwfWinDestroySG: freed SG 0x%p\n", pSG));1294 }1295 1296 DECLINLINE(ULONG) vboxNetLwfWinCalcSegments(PNET_BUFFER pNetBuf)1297 {1298 ULONG cSegs = 0;1299 for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf); pMdl; pMdl = NDIS_MDL_LINKAGE(pMdl))1300 cSegs++;1301 return cSegs;1302 }1303 1304 DECLINLINE(void) vboxNetLwfWinFreeMdlChain(PMDL pMdl)1305 {1306 #ifndef VBOXNETLWF_FIXED_SIZE_POOLS1307 PMDL pMdlNext;1308 while (pMdl)1309 {1310 pMdlNext = pMdl->Next;1311 # ifndef VBOXNETLWF_SYNC_SEND1312 PUCHAR pDataBuf;1313 ULONG cb = 0;1314 NdisQueryMdl(pMdl, &pDataBuf, &cb, NormalPagePriority);1315 # endif /* !VBOXNETLWF_SYNC_SEND */1316 NdisFreeMdl(pMdl);1317 Log4(("vboxNetLwfWinFreeMdlChain: freed MDL 0x%p\n", pMdl));1318 # ifndef VBOXNETLWF_SYNC_SEND1319 NdisFreeMemory(pDataBuf, 0, 0);1320 Log4(("vboxNetLwfWinFreeMdlChain: freed data buffer 0x%p\n", pDataBuf));1321 # endif /* !VBOXNETLWF_SYNC_SEND */1322 pMdl = pMdlNext;1323 }1324 #else /* VBOXNETLWF_FIXED_SIZE_POOLS */1325 RT_NOREF1(pMdl);1326 #endif /* VBOXNETLWF_FIXED_SIZE_POOLS */1327 }1328 1329 /** @todo1330 * 1) Copy data from SG to MDL (if we decide to complete asynchronously).1331 * 2) Provide context/backfill space. Nobody does it, should we?1332 * 3) We always get a single segment from intnet. Simplify?1333 */1334 static PNET_BUFFER_LIST vboxNetLwfWinSGtoNB(PVBOXNETLWF_MODULE pModule, PINTNETSG pSG)1335 {1336 AssertReturn(pSG->cSegsUsed >= 1, NULL);1337 LogFlow(("==>vboxNetLwfWinSGtoNB: segments=%d hPool=%p cb=%u\n", pSG->cSegsUsed,1338 pModule->hPool, pSG->cbTotal));1339 AssertReturn(pModule->hPool, NULL);1340 1341 #ifdef VBOXNETLWF_SYNC_SEND1342 PINTNETSEG pSeg = pSG->aSegs;1343 PMDL pMdl = NdisAllocateMdl(pModule->hFilter, pSeg->pv, pSeg->cb);1344 if (!pMdl)1345 {1346 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an MDL\n"));1347 LogFlow(("<==vboxNetLwfWinSGtoNB: return NULL\n"));1348 return NULL;1349 }1350 Log4(("vboxNetLwfWinSGtoNB: allocated Mdl 0x%p\n", pMdl));1351 PMDL pMdlCurr = pMdl;1352 for (int i = 1; i < pSG->cSegsUsed; i++)1353 {1354 pSeg = &pSG->aSegs[i];1355 pMdlCurr->Next = NdisAllocateMdl(pModule->hFilter, pSeg->pv, pSeg->cb);1356 if (!pMdlCurr->Next)1357 {1358 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an MDL\n"));1359 /* Tear down all MDL we chained so far */1360 vboxNetLwfWinFreeMdlChain(pMdl);1361 return NULL;1362 }1363 pMdlCurr = pMdlCurr->Next;1364 Log4(("vboxNetLwfWinSGtoNB: allocated Mdl 0x%p\n", pMdlCurr));1365 }1366 PNET_BUFFER_LIST pBufList = NdisAllocateNetBufferAndNetBufferList(pModule->hPool,1367 0 /* ContextSize */,1368 0 /* ContextBackFill */,1369 pMdl,1370 0 /* DataOffset */,1371 pSG->cbTotal);1372 if (pBufList)1373 {1374 Log4(("vboxNetLwfWinSGtoNB: allocated NBL+NB 0x%p\n", pBufList));1375 pBufList->SourceHandle = pModule->hFilter;1376 /** @todo Do we need to initialize anything else? */1377 }1378 else1379 {1380 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an NBL+NB\n"));1381 vboxNetLwfWinFreeMdlChain(pMdl);1382 }1383 #else /* !VBOXNETLWF_SYNC_SEND */1384 1385 # ifdef VBOXNETLWF_FIXED_SIZE_POOLS1386 int iPool = 0;1387 ULONG cbFrame = VBOXNETLWF_MAX_FRAME_SIZE(pSG->cbTotal);1388 /* Let's find the appropriate pool first */1389 for (iPool = 0; iPool < RT_ELEMENTS(g_cbPool); ++iPool)1390 if (cbFrame <= g_cbPool[iPool])1391 break;1392 if (iPool >= RT_ELEMENTS(g_cbPool))1393 {1394 LogError(("vboxNetLwfWinSGtoNB: frame is too big (%u > %u), drop it.\n", cbFrame, g_cbPool[RT_ELEMENTS(g_cbPool)-1]));1395 LogFlow(("<==vboxNetLwfWinSGtoNB: return NULL\n"));1396 return NULL;1397 }1398 PNET_BUFFER_LIST pBufList = NdisAllocateNetBufferList(pModule->hPool[iPool],1399 0 /** @todo ContextSize */,1400 0 /** @todo ContextBackFill */);1401 if (!pBufList)1402 {1403 LogError(("vboxNetLwfWinSGtoNB: failed to allocate netbuffer (cb=%u) from pool %d\n", cbFrame, iPool));1404 LogFlow(("<==vboxNetLwfWinSGtoNB: return NULL\n"));1405 return NULL;1406 }1407 const ULONG cbAlignmentMask = sizeof(USHORT) - 1; /* Microsoft LB/FO provider expects packets to be aligned at word boundary. */1408 ULONG cbAlignedFrame = (pSG->cbTotal + cbAlignmentMask) & ~cbAlignmentMask;1409 Assert(cbAlignedFrame >= pSG->cbTotal);1410 Assert(cbFrame >= cbAlignedFrame);1411 NET_BUFFER *pBuffer = NET_BUFFER_LIST_FIRST_NB(pBufList);1412 NDIS_STATUS Status = NdisRetreatNetBufferDataStart(pBuffer, cbAlignedFrame, 0 /** @todo DataBackfill */, NULL);1413 if (Status == NDIS_STATUS_SUCCESS)1414 {1415 uint8_t *pDst = (uint8_t*)NdisGetDataBuffer(pBuffer, pSG->cbTotal, NULL, 1, 0);1416 if (pDst)1417 {1418 for (int i = 0; i < pSG->cSegsUsed; i++)1419 {1420 NdisMoveMemory(pDst, pSG->aSegs[i].pv, pSG->aSegs[i].cb);1421 pDst += pSG->aSegs[i].cb;1422 }1423 if (cbAlignedFrame > pSG->cbTotal)1424 {1425 Log4(("vboxNetLwfWinSGtoNB: padding %d-byte packet with %d zero bytes", pSG->cbTotal, cbAlignedFrame - pSG->cbTotal));1426 NdisZeroMemory(pDst, cbAlignedFrame - pSG->cbTotal);1427 }1428 Log4(("vboxNetLwfWinSGtoNB: allocated NBL+NB 0x%p\n", pBufList));1429 pBufList->SourceHandle = pModule->hFilter;1430 }1431 else1432 {1433 LogError(("vboxNetLwfWinSGtoNB: failed to obtain the buffer pointer (size=%u)\n", pSG->cbTotal));1434 NdisAdvanceNetBufferDataStart(pBuffer, cbAlignedFrame, false, NULL); /** @todo why bother? */1435 NdisFreeNetBufferList(pBufList);1436 pBufList = NULL;1437 }1438 }1439 else1440 {1441 LogError(("vboxNetLwfWinSGtoNB: NdisRetreatNetBufferDataStart failed with 0x%x (size=%u)\n", Status, pSG->cbTotal));1442 NdisFreeNetBufferList(pBufList);1443 pBufList = NULL;1444 }1445 # else /* !VBOXNETLWF_FIXED_SIZE_POOLS */1446 PNET_BUFFER_LIST pBufList = NULL;1447 ULONG cbMdl = VBOXNETLWF_MAX_FRAME_SIZE(pSG->cbTotal);1448 ULONG uDataOffset = cbMdl - pSG->cbTotal;1449 PUCHAR pDataBuf = (PUCHAR)NdisAllocateMemoryWithTagPriority(pModule->hFilter, cbMdl,1450 VBOXNETLWF_MEM_TAG, NormalPoolPriority);1451 if (pDataBuf)1452 {1453 Log4(("vboxNetLwfWinSGtoNB: allocated data buffer (cb=%u) 0x%p\n", cbMdl, pDataBuf));1454 PMDL pMdl = NdisAllocateMdl(pModule->hFilter, pDataBuf, cbMdl);1455 if (!pMdl)1456 {1457 NdisFreeMemory(pDataBuf, 0, 0);1458 Log4(("vboxNetLwfWinSGtoNB: freed data buffer 0x%p\n", pDataBuf));1459 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an MDL (cb=%u)\n", cbMdl));1460 LogFlow(("<==vboxNetLwfWinSGtoNB: return NULL\n"));1461 return NULL;1462 }1463 PUCHAR pDst = pDataBuf + uDataOffset;1464 for (int i = 0; i < pSG->cSegsUsed; i++)1465 {1466 NdisMoveMemory(pDst, pSG->aSegs[i].pv, pSG->aSegs[i].cb);1467 pDst += pSG->aSegs[i].cb;1468 }1469 pBufList = NdisAllocateNetBufferAndNetBufferList(pModule->hPool,1470 0 /* ContextSize */,1471 0 /* ContextBackFill */,1472 pMdl,1473 uDataOffset,1474 pSG->cbTotal);1475 if (pBufList)1476 {1477 Log4(("vboxNetLwfWinSGtoNB: allocated NBL+NB 0x%p\n", pBufList));1478 pBufList->SourceHandle = pModule->hFilter;1479 /** @todo Do we need to initialize anything else? */1480 }1481 else1482 {1483 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an NBL+NB\n"));1484 vboxNetLwfWinFreeMdlChain(pMdl);1485 }1486 }1487 else1488 {1489 LogError(("vboxNetLwfWinSGtoNB: failed to allocate data buffer (size=%u)\n", cbMdl));1490 }1491 # endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */1492 1493 #endif /* !VBOXNETLWF_SYNC_SEND */1494 LogFlow(("<==vboxNetLwfWinSGtoNB: return %p\n", pBufList));1495 return pBufList;1496 }1497 1498 static PINTNETSG vboxNetLwfWinNBtoSG(PVBOXNETLWF_MODULE pModule, PNET_BUFFER pNetBuf)1499 {1500 ULONG cbPacket = NET_BUFFER_DATA_LENGTH(pNetBuf);1501 UINT cSegs = vboxNetLwfWinCalcSegments(pNetBuf);1502 /* Allocate and initialize SG */1503 PINTNETSG pSG = (PINTNETSG)NdisAllocateMemoryWithTagPriority(pModule->hFilter,1504 RT_OFFSETOF(INTNETSG, aSegs[cSegs]),1505 VBOXNETLWF_MEM_TAG,1506 NormalPoolPriority);1507 AssertReturn(pSG, pSG);1508 Log4(("vboxNetLwfWinNBtoSG: allocated SG 0x%p\n", pSG));1509 IntNetSgInitTempSegs(pSG, cbPacket /*cbTotal*/, cSegs, cSegs /*cSegsUsed*/);1510 1511 int rc = NDIS_STATUS_SUCCESS;1512 ULONG uOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pNetBuf);1513 cSegs = 0;1514 for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf);1515 pMdl != NULL && cbPacket > 0;1516 pMdl = NDIS_MDL_LINKAGE(pMdl))1517 {1518 PUCHAR pSrc = (PUCHAR)MmGetSystemAddressForMdlSafe(pMdl, LowPagePriority);1519 if (!pSrc)1520 {1521 rc = NDIS_STATUS_RESOURCES;1522 break;1523 }1524 ULONG cbSrc = MmGetMdlByteCount(pMdl);1525 if (uOffset)1526 {1527 Assert(uOffset < cbSrc);1528 pSrc += uOffset;1529 cbSrc -= uOffset;1530 uOffset = 0;1531 }1532 1533 if (cbSrc > cbPacket)1534 cbSrc = cbPacket;1535 1536 pSG->aSegs[cSegs].pv = pSrc;1537 pSG->aSegs[cSegs].cb = cbSrc;1538 pSG->aSegs[cSegs].Phys = NIL_RTHCPHYS;1539 cSegs++;1540 cbPacket -= cbSrc;1541 }1542 1543 Assert(cSegs <= pSG->cSegsAlloc);1544 1545 if (RT_FAILURE(rc))1546 {1547 vboxNetLwfWinDestroySG(pSG);1548 pSG = NULL;1549 }1550 else1551 {1552 Assert(cbPacket == 0);1553 Assert(pSG->cSegsUsed == cSegs);1554 }1555 return pSG;1556 }1557 1558 1005 static void vboxNetLwfWinDisableOffloading(PNDIS_OFFLOAD pOffloadConfig) 1559 1006 { … … 1576 1023 pOffloadConfig->LsoV2.IPv6.IpExtensionHeadersSupported = NDIS_OFFLOAD_NOT_SUPPORTED; 1577 1024 pOffloadConfig->LsoV2.IPv6.TcpOptionsSupported = NDIS_OFFLOAD_NOT_SUPPORTED; 1025 } 1026 1027 static void vboxNetLwfWinUpdateSavedOffloadConfig(PVBOXNETLWF_MODULE pModuleCtx, PNDIS_OFFLOAD pOffload) 1028 { 1029 if (pModuleCtx->cbOffloadConfig < pOffload->Header.Size) 1030 { 1031 vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, STATUS_SUCCESS, 10); 1032 return; 1033 } 1034 1035 NdisMoveMemory(pModuleCtx->pSavedOffloadConfig, pOffload, pOffload->Header.Size); 1036 NdisMoveMemory(pModuleCtx->pDisabledOffloadConfig, pOffload, pOffload->Header.Size); 1037 vboxNetLwfWinDisableOffloading(pModuleCtx->pDisabledOffloadConfig); 1038 pModuleCtx->fOffloadConfigValid = true; 1039 } 1040 1041 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS 1042 static void vboxNetLwfWinFreePools(PVBOXNETLWF_MODULE pModuleCtx, int cPools) 1043 { 1044 for (int i = 0; i < cPools; ++i) 1045 { 1046 if (pModuleCtx->hPool[i]) 1047 { 1048 NdisFreeNetBufferListPool(pModuleCtx->hPool[i]); 1049 Log4(("vboxNetLwfWinFreePools: freed NBL+NB pool 0x%p\n", pModuleCtx->hPool[i])); 1050 } 1051 } 1052 } 1053 #endif /* VBOXNETLWF_FIXED_SIZE_POOLS */ 1054 1055 1056 static void vboxNetLwfWinFreeModuleResources(PVBOXNETLWF_MODULE pModuleCtx) 1057 { 1058 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS 1059 vboxNetLwfWinFreePools(pModuleCtx, RT_ELEMENTS(g_cbPool)); 1060 #else /* !VBOXNETLWF_FIXED_SIZE_POOLS */ 1061 if (pModuleCtx->hPool) 1062 { 1063 NdisFreeNetBufferListPool(pModuleCtx->hPool); 1064 Log4(("vboxNetLwfWinFreeModuleResources: freed NBL+NB pool 0x%p\n", pModuleCtx->hPool)); 1065 } 1066 #endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */ 1067 if (pModuleCtx->pDisabledOffloadConfig) 1068 NdisFreeMemory(pModuleCtx->pDisabledOffloadConfig, 0, 0); 1069 if (pModuleCtx->pSavedOffloadConfig) 1070 NdisFreeMemory(pModuleCtx->pSavedOffloadConfig, 0, 0); 1071 if (pModuleCtx->hWorkItem) 1072 NdisFreeIoWorkItem(pModuleCtx->hWorkItem); 1073 NdisFreeMemory(pModuleCtx, 0, 0); 1074 } 1075 1076 1077 DECLARE_GLOBAL_CONST_UNICODE_STRING(g_strHostOnlyMiniportName, L"VirtualBox Host-Only"); 1078 1079 static NDIS_STATUS vboxNetLwfWinAttach(IN NDIS_HANDLE hFilter, IN NDIS_HANDLE hDriverCtx, 1080 IN PNDIS_FILTER_ATTACH_PARAMETERS pParameters) 1081 { 1082 LogFlow(("==>vboxNetLwfWinAttach: filter=%p\n", hFilter)); 1083 1084 PVBOXNETLWFGLOBALS pGlobals = (PVBOXNETLWFGLOBALS)hDriverCtx; 1085 if (!pGlobals) 1086 { 1087 vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 1); 1088 return NDIS_STATUS_FAILURE; 1089 } 1090 1091 /* 1092 * We need a copy of NDIS_STRING structure as we are going to modify length 1093 * of the base miniport instance name since RTL does not support comparing 1094 * first n characters of two strings. We check if miniport names start with 1095 * "Virtual Host-Only" to detect host-only adapters. It is a waste of resources 1096 * to bind our filter to host-only adapters since they now operate independently. 1097 */ 1098 NDIS_STRING strTruncatedInstanceName = *pParameters->BaseMiniportInstanceName; /* Do not copy data, only the structure itself */ 1099 strTruncatedInstanceName.Length = g_strHostOnlyMiniportName.Length; /* Truncate instance name */ 1100 if (RtlEqualUnicodeString(&strTruncatedInstanceName, &g_strHostOnlyMiniportName, TRUE /* Case insensitive */)) 1101 { 1102 DbgPrint("vboxNetLwfWinAttach: won't attach to %wZ\n", pParameters->BaseMiniportInstanceName); 1103 return NDIS_STATUS_FAILURE; 1104 } 1105 1106 ANSI_STRING strMiniportName; 1107 /* We use the miniport name to associate this filter module with the netflt instance */ 1108 NTSTATUS rc = RtlUnicodeStringToAnsiString(&strMiniportName, 1109 pParameters->BaseMiniportName, 1110 TRUE); 1111 if (rc != STATUS_SUCCESS) 1112 { 1113 LogError(("vboxNetLwfWinAttach: RtlUnicodeStringToAnsiString(%ls) failed with 0x%x\n", 1114 pParameters->BaseMiniportName, rc)); 1115 vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_FAILURE, 2); 1116 return NDIS_STATUS_FAILURE; 1117 } 1118 DbgPrint("vboxNetLwfWinAttach: friendly name=%wZ\n", pParameters->BaseMiniportInstanceName); 1119 DbgPrint("vboxNetLwfWinAttach: name=%Z\n", &strMiniportName); 1120 1121 UINT cbModuleWithNameExtra = sizeof(VBOXNETLWF_MODULE) + strMiniportName.Length; 1122 PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)NdisAllocateMemoryWithTagPriority(hFilter, 1123 cbModuleWithNameExtra, 1124 VBOXNETLWF_MEM_TAG, 1125 LowPoolPriority); 1126 if (!pModuleCtx) 1127 { 1128 LogError(("vboxNetLwfWinAttach: Failed to allocate module context for %ls\n", pParameters->BaseMiniportName)); 1129 RtlFreeAnsiString(&strMiniportName); 1130 vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 3); 1131 return NDIS_STATUS_RESOURCES; 1132 } 1133 Log4(("vboxNetLwfWinAttach: allocated module context 0x%p\n", pModuleCtx)); 1134 1135 NdisZeroMemory(pModuleCtx, cbModuleWithNameExtra); 1136 NdisMoveMemory(pModuleCtx->szMiniportName, strMiniportName.Buffer, strMiniportName.Length); 1137 RtlFreeAnsiString(&strMiniportName); 1138 1139 pModuleCtx->hWorkItem = NdisAllocateIoWorkItem(g_VBoxNetLwfGlobals.hFilterDriver); 1140 if (!pModuleCtx->hWorkItem) 1141 { 1142 LogError(("vboxNetLwfWinAttach: Failed to allocate work item for %ls\n", 1143 pParameters->BaseMiniportName)); 1144 NdisFreeMemory(pModuleCtx, 0, 0); 1145 vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 4); 1146 return NDIS_STATUS_RESOURCES; 1147 } 1148 1149 Assert(pParameters->MacAddressLength == sizeof(RTMAC)); 1150 NdisMoveMemory(&pModuleCtx->MacAddr, pParameters->CurrentMacAddress, RT_MIN(sizeof(RTMAC), pParameters->MacAddressLength)); 1151 1152 pModuleCtx->cbOffloadConfig = sizeof(NDIS_OFFLOAD) * 2; /* Best guess to accomodate future expansion. */ 1153 /* Get the exact size, if possible. */ 1154 if (pParameters->DefaultOffloadConfiguration) 1155 pModuleCtx->cbOffloadConfig = pParameters->DefaultOffloadConfiguration->Header.Size; 1156 else 1157 vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, STATUS_SUCCESS, 8); 1158 1159 pModuleCtx->pSavedOffloadConfig = 1160 (PNDIS_OFFLOAD)NdisAllocateMemoryWithTagPriority(hFilter, pModuleCtx->cbOffloadConfig, 1161 VBOXNETLWF_MEM_TAG, LowPoolPriority); 1162 pModuleCtx->pDisabledOffloadConfig = 1163 (PNDIS_OFFLOAD)NdisAllocateMemoryWithTagPriority(hFilter, pModuleCtx->cbOffloadConfig, 1164 VBOXNETLWF_MEM_TAG, LowPoolPriority); 1165 if (!pModuleCtx->pSavedOffloadConfig || !pModuleCtx->pDisabledOffloadConfig) 1166 { 1167 LogError(("vboxNetLwfWinAttach: Failed to allocate offload config buffers for %ls\n", 1168 pParameters->BaseMiniportName)); 1169 vboxNetLwfWinFreeModuleResources(pModuleCtx); 1170 vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 9); 1171 return NDIS_STATUS_RESOURCES; 1172 } 1173 1174 if (pParameters->DefaultOffloadConfiguration) 1175 vboxNetLwfWinUpdateSavedOffloadConfig(pModuleCtx, pParameters->DefaultOffloadConfiguration); 1176 else 1177 { 1178 NdisZeroMemory(pModuleCtx->pDisabledOffloadConfig, pModuleCtx->cbOffloadConfig); 1179 pModuleCtx->pDisabledOffloadConfig->Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; 1180 pModuleCtx->pDisabledOffloadConfig->Header.Revision = NDIS_OFFLOAD_REVISION_1; 1181 pModuleCtx->pDisabledOffloadConfig->Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1; 1182 } 1183 1184 pModuleCtx->pGlobals = pGlobals; 1185 pModuleCtx->hFilter = hFilter; 1186 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Attaching); 1187 /* Initialize transmission mutex and events */ 1188 NDIS_INIT_MUTEX(&pModuleCtx->InTransmit); 1189 #ifdef VBOXNETLWF_SYNC_SEND 1190 KeInitializeEvent(&pModuleCtx->EventWire, SynchronizationEvent, FALSE); 1191 KeInitializeEvent(&pModuleCtx->EventHost, SynchronizationEvent, FALSE); 1192 #else /* !VBOXNETLWF_SYNC_SEND */ 1193 NdisInitializeEvent(&pModuleCtx->EventSendComplete); 1194 pModuleCtx->cPendingBuffers = 0; 1195 #endif /* !VBOXNETLWF_SYNC_SEND */ 1196 1197 #ifdef VBOXNETLWF_FIXED_SIZE_POOLS 1198 for (int i = 0; i < RT_ELEMENTS(g_cbPool); ++i) 1199 { 1200 /* Allocate buffer pools */ 1201 NET_BUFFER_LIST_POOL_PARAMETERS PoolParams; 1202 NdisZeroMemory(&PoolParams, sizeof(PoolParams)); 1203 PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; 1204 PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; 1205 PoolParams.Header.Size = sizeof(PoolParams); 1206 PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT; 1207 PoolParams.fAllocateNetBuffer = TRUE; 1208 PoolParams.ContextSize = 0; /** @todo Do we need to consider underlying drivers? I think not. */ 1209 PoolParams.PoolTag = VBOXNETLWF_MEM_TAG; 1210 PoolParams.DataSize = g_cbPool[i]; 1211 pModuleCtx->hPool[i] = NdisAllocateNetBufferListPool(hFilter, &PoolParams); 1212 if (!pModuleCtx->hPool[i]) 1213 { 1214 LogError(("vboxNetLwfWinAttach: NdisAllocateNetBufferListPool failed\n")); 1215 vboxNetLwfWinFreeModuleResources(pModuleCtx); 1216 vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 7); 1217 return NDIS_STATUS_RESOURCES; 1218 } 1219 Log4(("vboxNetLwfWinAttach: allocated NBL+NB pool (data size=%u) 0x%p\n", 1220 PoolParams.DataSize, pModuleCtx->hPool[i])); 1221 } 1222 #else /* !VBOXNETLWF_FIXED_SIZE_POOLS */ 1223 /* Allocate buffer pools */ 1224 NET_BUFFER_LIST_POOL_PARAMETERS PoolParams; 1225 NdisZeroMemory(&PoolParams, sizeof(PoolParams)); 1226 PoolParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; 1227 PoolParams.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; 1228 PoolParams.Header.Size = sizeof(PoolParams); 1229 PoolParams.ProtocolId = NDIS_PROTOCOL_ID_DEFAULT; 1230 PoolParams.fAllocateNetBuffer = TRUE; 1231 PoolParams.ContextSize = 0; /** @todo Do we need to consider underlying drivers? I think not. */ 1232 PoolParams.PoolTag = VBOXNETLWF_MEM_TAG; 1233 pModuleCtx->hPool = NdisAllocateNetBufferListPool(hFilter, &PoolParams); 1234 if (!pModuleCtx->hPool) 1235 { 1236 LogError(("vboxNetLwfWinAttach: NdisAllocateNetBufferListPool failed\n")); 1237 vboxNetLwfWinFreeModuleResources(pModuleCtx); 1238 vboxNetLwfLogErrorEvent(IO_ERR_INSUFFICIENT_RESOURCES, NDIS_STATUS_RESOURCES, 7); 1239 return NDIS_STATUS_RESOURCES; 1240 } 1241 Log4(("vboxNetLwfWinAttach: allocated NBL+NB pool 0x%p\n", pModuleCtx->hPool)); 1242 #endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */ 1243 1244 NDIS_FILTER_ATTRIBUTES Attributes; 1245 NdisZeroMemory(&Attributes, sizeof(Attributes)); 1246 Attributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1; 1247 Attributes.Header.Size = sizeof(Attributes); 1248 Attributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES; 1249 Attributes.Flags = 0; 1250 NDIS_STATUS Status = NdisFSetAttributes(hFilter, pModuleCtx, &Attributes); 1251 if (Status != NDIS_STATUS_SUCCESS) 1252 { 1253 LogError(("vboxNetLwfWinAttach: NdisFSetAttributes failed with 0x%x\n", Status)); 1254 vboxNetLwfWinFreeModuleResources(pModuleCtx); 1255 vboxNetLwfLogErrorEvent(IO_ERR_INTERNAL_ERROR, NDIS_STATUS_RESOURCES, 5); 1256 return NDIS_STATUS_RESOURCES; 1257 } 1258 /* Insert into module chain */ 1259 NdisAcquireSpinLock(&pGlobals->Lock); 1260 RTListPrepend(&pGlobals->listModules, &pModuleCtx->node); 1261 NdisReleaseSpinLock(&pGlobals->Lock); 1262 1263 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused); 1264 1265 /// @todo Somehow the packet filter is 0 at this point: Status = vboxNetLwfWinGetPacketFilter(pModuleCtx); 1266 /// @todo We actually update it later in status handler, perhaps we should not do anything here. 1267 1268 LogFlow(("<==vboxNetLwfWinAttach: Status = 0x%x\n", Status)); 1269 return Status; 1270 } 1271 1272 static VOID vboxNetLwfWinDetach(IN NDIS_HANDLE hModuleCtx) 1273 { 1274 LogFlow(("==>vboxNetLwfWinDetach: module=%p\n", hModuleCtx)); 1275 PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx; 1276 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Detached, LwfState_Paused); 1277 1278 /* Remove from module chain */ 1279 NdisAcquireSpinLock(&pModuleCtx->pGlobals->Lock); 1280 RTListNodeRemove(&pModuleCtx->node); 1281 NdisReleaseSpinLock(&pModuleCtx->pGlobals->Lock); 1282 1283 PVBOXNETFLTINS pNetFltIns = pModuleCtx->pNetFlt; /// @todo Atomic? 1284 if (pNetFltIns && vboxNetFltTryRetainBusyNotDisconnected(pNetFltIns)) 1285 { 1286 /* 1287 * Set hModuleCtx to null now in order to prevent filter restart, 1288 * OID requests and other stuff associated with NetFlt deactivation. 1289 */ 1290 pNetFltIns->u.s.WinIf.hModuleCtx = NULL; 1291 /* Notify NetFlt that we are going down */ 1292 pNetFltIns->pSwitchPort->pfnDisconnect(pNetFltIns->pSwitchPort, &pNetFltIns->MyPort, vboxNetFltPortReleaseBusy); 1293 /* We do not 'release' netflt instance since it has been done by pfnDisconnect */ 1294 } 1295 pModuleCtx->pNetFlt = NULL; 1296 1297 /* 1298 * We have to make sure that all NET_BUFFER_LIST structures have been freed by now, but 1299 * it does not require us to do anything here since it has already been taken care of 1300 * by vboxNetLwfWinPause(). 1301 */ 1302 vboxNetLwfWinFreeModuleResources(pModuleCtx); 1303 Log4(("vboxNetLwfWinDetach: freed module context 0x%p\n", pModuleCtx)); 1304 LogFlow(("<==vboxNetLwfWinDetach\n")); 1305 } 1306 1307 1308 static NDIS_STATUS vboxNetLwfWinPause(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_PAUSE_PARAMETERS pParameters) 1309 { 1310 RT_NOREF1(pParameters); 1311 LogFlow(("==>vboxNetLwfWinPause: module=%p\n", hModuleCtx)); 1312 PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx; 1313 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Pausing, LwfState_Running); 1314 /* Wait for pending send/indication operations to complete. */ 1315 NDIS_WAIT_FOR_MUTEX(&pModuleCtx->InTransmit); 1316 #ifndef VBOXNETLWF_SYNC_SEND 1317 NdisWaitEvent(&pModuleCtx->EventSendComplete, 1000 /* ms */); 1318 #endif /* !VBOXNETLWF_SYNC_SEND */ 1319 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Paused, LwfState_Pausing); 1320 NDIS_RELEASE_MUTEX(&pModuleCtx->InTransmit); 1321 LogFlow(("<==vboxNetLwfWinPause\n")); 1322 return NDIS_STATUS_SUCCESS; /* Failure is not an option */ 1323 } 1324 1325 1326 static void vboxNetLwfWinIndicateOffload(PVBOXNETLWF_MODULE pModuleCtx, PNDIS_OFFLOAD pOffload) 1327 { 1328 Log5(("vboxNetLwfWinIndicateOffload: offload config changed to:\n")); 1329 vboxNetLwfWinDumpOffloadSettings(pOffload); 1330 NDIS_STATUS_INDICATION OffloadingIndication; 1331 NdisZeroMemory(&OffloadingIndication, sizeof(OffloadingIndication)); 1332 OffloadingIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION; 1333 OffloadingIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1; 1334 OffloadingIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1; 1335 OffloadingIndication.SourceHandle = pModuleCtx->hFilter; 1336 OffloadingIndication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG; 1337 OffloadingIndication.StatusBuffer = pOffload; 1338 OffloadingIndication.StatusBufferSize = sizeof(NDIS_OFFLOAD); 1339 NdisFIndicateStatus(pModuleCtx->hFilter, &OffloadingIndication); 1340 } 1341 1342 1343 static NDIS_STATUS vboxNetLwfWinRestart(IN NDIS_HANDLE hModuleCtx, IN PNDIS_FILTER_RESTART_PARAMETERS pParameters) 1344 { 1345 RT_NOREF1(pParameters); 1346 LogFlow(("==>vboxNetLwfWinRestart: module=%p\n", hModuleCtx)); 1347 PVBOXNETLWF_MODULE pModuleCtx = (PVBOXNETLWF_MODULE)hModuleCtx; 1348 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Restarting, LwfState_Paused); 1349 vboxNetLwfWinChangeState(pModuleCtx, LwfState_Running, LwfState_Restarting); 1350 NDIS_STATUS Status = NDIS_STATUS_SUCCESS; 1351 LogFlow(("<==vboxNetLwfWinRestart: Status = 0x%x\n", Status)); 1352 return Status; 1353 } 1354 1355 1356 static void vboxNetLwfWinDestroySG(PINTNETSG pSG) 1357 { 1358 NdisFreeMemory(pSG, 0, 0); 1359 Log4(("vboxNetLwfWinDestroySG: freed SG 0x%p\n", pSG)); 1360 } 1361 1362 DECLINLINE(ULONG) vboxNetLwfWinCalcSegments(PNET_BUFFER pNetBuf) 1363 { 1364 ULONG cSegs = 0; 1365 for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf); pMdl; pMdl = NDIS_MDL_LINKAGE(pMdl)) 1366 cSegs++; 1367 return cSegs; 1368 } 1369 1370 DECLINLINE(void) vboxNetLwfWinFreeMdlChain(PMDL pMdl) 1371 { 1372 #ifndef VBOXNETLWF_FIXED_SIZE_POOLS 1373 PMDL pMdlNext; 1374 while (pMdl) 1375 { 1376 pMdlNext = pMdl->Next; 1377 # ifndef VBOXNETLWF_SYNC_SEND 1378 PUCHAR pDataBuf; 1379 ULONG cb = 0; 1380 NdisQueryMdl(pMdl, &pDataBuf, &cb, NormalPagePriority); 1381 # endif /* !VBOXNETLWF_SYNC_SEND */ 1382 NdisFreeMdl(pMdl); 1383 Log4(("vboxNetLwfWinFreeMdlChain: freed MDL 0x%p\n", pMdl)); 1384 # ifndef VBOXNETLWF_SYNC_SEND 1385 NdisFreeMemory(pDataBuf, 0, 0); 1386 Log4(("vboxNetLwfWinFreeMdlChain: freed data buffer 0x%p\n", pDataBuf)); 1387 # endif /* !VBOXNETLWF_SYNC_SEND */ 1388 pMdl = pMdlNext; 1389 } 1390 #else /* VBOXNETLWF_FIXED_SIZE_POOLS */ 1391 RT_NOREF1(pMdl); 1392 #endif /* VBOXNETLWF_FIXED_SIZE_POOLS */ 1393 } 1394 1395 /** @todo 1396 * 1) Copy data from SG to MDL (if we decide to complete asynchronously). 1397 * 2) Provide context/backfill space. Nobody does it, should we? 1398 * 3) We always get a single segment from intnet. Simplify? 1399 */ 1400 static PNET_BUFFER_LIST vboxNetLwfWinSGtoNB(PVBOXNETLWF_MODULE pModule, PINTNETSG pSG) 1401 { 1402 AssertReturn(pSG->cSegsUsed >= 1, NULL); 1403 LogFlow(("==>vboxNetLwfWinSGtoNB: segments=%d hPool=%p cb=%u\n", pSG->cSegsUsed, 1404 pModule->hPool, pSG->cbTotal)); 1405 AssertReturn(pModule->hPool, NULL); 1406 1407 #ifdef VBOXNETLWF_SYNC_SEND 1408 PINTNETSEG pSeg = pSG->aSegs; 1409 PMDL pMdl = NdisAllocateMdl(pModule->hFilter, pSeg->pv, pSeg->cb); 1410 if (!pMdl) 1411 { 1412 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an MDL\n")); 1413 LogFlow(("<==vboxNetLwfWinSGtoNB: return NULL\n")); 1414 return NULL; 1415 } 1416 Log4(("vboxNetLwfWinSGtoNB: allocated Mdl 0x%p\n", pMdl)); 1417 PMDL pMdlCurr = pMdl; 1418 for (int i = 1; i < pSG->cSegsUsed; i++) 1419 { 1420 pSeg = &pSG->aSegs[i]; 1421 pMdlCurr->Next = NdisAllocateMdl(pModule->hFilter, pSeg->pv, pSeg->cb); 1422 if (!pMdlCurr->Next) 1423 { 1424 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an MDL\n")); 1425 /* Tear down all MDL we chained so far */ 1426 vboxNetLwfWinFreeMdlChain(pMdl); 1427 return NULL; 1428 } 1429 pMdlCurr = pMdlCurr->Next; 1430 Log4(("vboxNetLwfWinSGtoNB: allocated Mdl 0x%p\n", pMdlCurr)); 1431 } 1432 PNET_BUFFER_LIST pBufList = NdisAllocateNetBufferAndNetBufferList(pModule->hPool, 1433 0 /* ContextSize */, 1434 0 /* ContextBackFill */, 1435 pMdl, 1436 0 /* DataOffset */, 1437 pSG->cbTotal); 1438 if (pBufList) 1439 { 1440 Log4(("vboxNetLwfWinSGtoNB: allocated NBL+NB 0x%p\n", pBufList)); 1441 pBufList->SourceHandle = pModule->hFilter; 1442 /** @todo Do we need to initialize anything else? */ 1443 } 1444 else 1445 { 1446 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an NBL+NB\n")); 1447 vboxNetLwfWinFreeMdlChain(pMdl); 1448 } 1449 #else /* !VBOXNETLWF_SYNC_SEND */ 1450 1451 # ifdef VBOXNETLWF_FIXED_SIZE_POOLS 1452 int iPool = 0; 1453 ULONG cbFrame = VBOXNETLWF_MAX_FRAME_SIZE(pSG->cbTotal); 1454 /* Let's find the appropriate pool first */ 1455 for (iPool = 0; iPool < RT_ELEMENTS(g_cbPool); ++iPool) 1456 if (cbFrame <= g_cbPool[iPool]) 1457 break; 1458 if (iPool >= RT_ELEMENTS(g_cbPool)) 1459 { 1460 LogError(("vboxNetLwfWinSGtoNB: frame is too big (%u > %u), drop it.\n", cbFrame, g_cbPool[RT_ELEMENTS(g_cbPool)-1])); 1461 LogFlow(("<==vboxNetLwfWinSGtoNB: return NULL\n")); 1462 return NULL; 1463 } 1464 PNET_BUFFER_LIST pBufList = NdisAllocateNetBufferList(pModule->hPool[iPool], 1465 0 /** @todo ContextSize */, 1466 0 /** @todo ContextBackFill */); 1467 if (!pBufList) 1468 { 1469 LogError(("vboxNetLwfWinSGtoNB: failed to allocate netbuffer (cb=%u) from pool %d\n", cbFrame, iPool)); 1470 LogFlow(("<==vboxNetLwfWinSGtoNB: return NULL\n")); 1471 return NULL; 1472 } 1473 const ULONG cbAlignmentMask = sizeof(USHORT) - 1; /* Microsoft LB/FO provider expects packets to be aligned at word boundary. */ 1474 ULONG cbAlignedFrame = (pSG->cbTotal + cbAlignmentMask) & ~cbAlignmentMask; 1475 Assert(cbAlignedFrame >= pSG->cbTotal); 1476 Assert(cbFrame >= cbAlignedFrame); 1477 NET_BUFFER *pBuffer = NET_BUFFER_LIST_FIRST_NB(pBufList); 1478 NDIS_STATUS Status = NdisRetreatNetBufferDataStart(pBuffer, cbAlignedFrame, 0 /** @todo DataBackfill */, NULL); 1479 if (Status == NDIS_STATUS_SUCCESS) 1480 { 1481 uint8_t *pDst = (uint8_t*)NdisGetDataBuffer(pBuffer, pSG->cbTotal, NULL, 1, 0); 1482 if (pDst) 1483 { 1484 for (int i = 0; i < pSG->cSegsUsed; i++) 1485 { 1486 NdisMoveMemory(pDst, pSG->aSegs[i].pv, pSG->aSegs[i].cb); 1487 pDst += pSG->aSegs[i].cb; 1488 } 1489 if (cbAlignedFrame > pSG->cbTotal) 1490 { 1491 Log4(("vboxNetLwfWinSGtoNB: padding %d-byte packet with %d zero bytes", pSG->cbTotal, cbAlignedFrame - pSG->cbTotal)); 1492 NdisZeroMemory(pDst, cbAlignedFrame - pSG->cbTotal); 1493 } 1494 Log4(("vboxNetLwfWinSGtoNB: allocated NBL+NB 0x%p\n", pBufList)); 1495 pBufList->SourceHandle = pModule->hFilter; 1496 } 1497 else 1498 { 1499 LogError(("vboxNetLwfWinSGtoNB: failed to obtain the buffer pointer (size=%u)\n", pSG->cbTotal)); 1500 NdisAdvanceNetBufferDataStart(pBuffer, cbAlignedFrame, false, NULL); /** @todo why bother? */ 1501 NdisFreeNetBufferList(pBufList); 1502 pBufList = NULL; 1503 } 1504 } 1505 else 1506 { 1507 LogError(("vboxNetLwfWinSGtoNB: NdisRetreatNetBufferDataStart failed with 0x%x (size=%u)\n", Status, pSG->cbTotal)); 1508 NdisFreeNetBufferList(pBufList); 1509 pBufList = NULL; 1510 } 1511 # else /* !VBOXNETLWF_FIXED_SIZE_POOLS */ 1512 PNET_BUFFER_LIST pBufList = NULL; 1513 ULONG cbMdl = VBOXNETLWF_MAX_FRAME_SIZE(pSG->cbTotal); 1514 ULONG uDataOffset = cbMdl - pSG->cbTotal; 1515 PUCHAR pDataBuf = (PUCHAR)NdisAllocateMemoryWithTagPriority(pModule->hFilter, cbMdl, 1516 VBOXNETLWF_MEM_TAG, NormalPoolPriority); 1517 if (pDataBuf) 1518 { 1519 Log4(("vboxNetLwfWinSGtoNB: allocated data buffer (cb=%u) 0x%p\n", cbMdl, pDataBuf)); 1520 PMDL pMdl = NdisAllocateMdl(pModule->hFilter, pDataBuf, cbMdl); 1521 if (!pMdl) 1522 { 1523 NdisFreeMemory(pDataBuf, 0, 0); 1524 Log4(("vboxNetLwfWinSGtoNB: freed data buffer 0x%p\n", pDataBuf)); 1525 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an MDL (cb=%u)\n", cbMdl)); 1526 LogFlow(("<==vboxNetLwfWinSGtoNB: return NULL\n")); 1527 return NULL; 1528 } 1529 PUCHAR pDst = pDataBuf + uDataOffset; 1530 for (int i = 0; i < pSG->cSegsUsed; i++) 1531 { 1532 NdisMoveMemory(pDst, pSG->aSegs[i].pv, pSG->aSegs[i].cb); 1533 pDst += pSG->aSegs[i].cb; 1534 } 1535 pBufList = NdisAllocateNetBufferAndNetBufferList(pModule->hPool, 1536 0 /* ContextSize */, 1537 0 /* ContextBackFill */, 1538 pMdl, 1539 uDataOffset, 1540 pSG->cbTotal); 1541 if (pBufList) 1542 { 1543 Log4(("vboxNetLwfWinSGtoNB: allocated NBL+NB 0x%p\n", pBufList)); 1544 pBufList->SourceHandle = pModule->hFilter; 1545 /** @todo Do we need to initialize anything else? */ 1546 } 1547 else 1548 { 1549 LogError(("vboxNetLwfWinSGtoNB: failed to allocate an NBL+NB\n")); 1550 vboxNetLwfWinFreeMdlChain(pMdl); 1551 } 1552 } 1553 else 1554 { 1555 LogError(("vboxNetLwfWinSGtoNB: failed to allocate data buffer (size=%u)\n", cbMdl)); 1556 } 1557 # endif /* !VBOXNETLWF_FIXED_SIZE_POOLS */ 1558 1559 #endif /* !VBOXNETLWF_SYNC_SEND */ 1560 LogFlow(("<==vboxNetLwfWinSGtoNB: return %p\n", pBufList)); 1561 return pBufList; 1562 } 1563 1564 static PINTNETSG vboxNetLwfWinNBtoSG(PVBOXNETLWF_MODULE pModule, PNET_BUFFER pNetBuf) 1565 { 1566 ULONG cbPacket = NET_BUFFER_DATA_LENGTH(pNetBuf); 1567 UINT cSegs = vboxNetLwfWinCalcSegments(pNetBuf); 1568 /* Allocate and initialize SG */ 1569 PINTNETSG pSG = (PINTNETSG)NdisAllocateMemoryWithTagPriority(pModule->hFilter, 1570 RT_OFFSETOF(INTNETSG, aSegs[cSegs]), 1571 VBOXNETLWF_MEM_TAG, 1572 NormalPoolPriority); 1573 AssertReturn(pSG, pSG); 1574 Log4(("vboxNetLwfWinNBtoSG: allocated SG 0x%p\n", pSG)); 1575 IntNetSgInitTempSegs(pSG, cbPacket /*cbTotal*/, cSegs, cSegs /*cSegsUsed*/); 1576 1577 int rc = NDIS_STATUS_SUCCESS; 1578 ULONG uOffset = NET_BUFFER_CURRENT_MDL_OFFSET(pNetBuf); 1579 cSegs = 0; 1580 for (PMDL pMdl = NET_BUFFER_CURRENT_MDL(pNetBuf); 1581 pMdl != NULL && cbPacket > 0; 1582 pMdl = NDIS_MDL_LINKAGE(pMdl)) 1583 { 1584 PUCHAR pSrc = (PUCHAR)MmGetSystemAddressForMdlSafe(pMdl, LowPagePriority); 1585 if (!pSrc) 1586 { 1587 rc = NDIS_STATUS_RESOURCES; 1588 break; 1589 } 1590 ULONG cbSrc = MmGetMdlByteCount(pMdl); 1591 if (uOffset) 1592 { 1593 Assert(uOffset < cbSrc); 1594 pSrc += uOffset; 1595 cbSrc -= uOffset; 1596 uOffset = 0; 1597 } 1598 1599 if (cbSrc > cbPacket) 1600 cbSrc = cbPacket; 1601 1602 pSG->aSegs[cSegs].pv = pSrc; 1603 pSG->aSegs[cSegs].cb = cbSrc; 1604 pSG->aSegs[cSegs].Phys = NIL_RTHCPHYS; 1605 cSegs++; 1606 cbPacket -= cbSrc; 1607 } 1608 1609 Assert(cSegs <= pSG->cSegsAlloc); 1610 1611 if (RT_FAILURE(rc)) 1612 { 1613 vboxNetLwfWinDestroySG(pSG); 1614 pSG = NULL; 1615 } 1616 else 1617 { 1618 Assert(cbPacket == 0); 1619 Assert(pSG->cSegsUsed == cSegs); 1620 } 1621 return pSG; 1578 1622 } 1579 1623 … … 2371 2415 /* Disable offloading temporarily by indicating offload config change. */ 2372 2416 /** @todo Be sure to revise this when implementing offloading support! */ 2373 NDIS_OFFLOAD OffloadConfig; 2374 if (pModuleCtx->fOffloadConfigValid) 2375 { 2376 OffloadConfig = pModuleCtx->SavedOffloadConfig; 2377 vboxNetLwfWinDisableOffloading(&OffloadConfig); 2378 } 2379 else 2380 { 2381 DbgPrint("VBoxNetLwf: no saved offload config to modify for %s\n", pModuleCtx->szMiniportName); 2382 NdisZeroMemory(&OffloadConfig, sizeof(OffloadConfig)); 2383 OffloadConfig.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD; 2384 OffloadConfig.Header.Revision = NDIS_OFFLOAD_REVISION_1; 2385 OffloadConfig.Header.Size = NDIS_SIZEOF_NDIS_OFFLOAD_REVISION_1; 2386 } 2387 vboxNetLwfWinIndicateOffload(pModuleCtx, &OffloadConfig); 2417 vboxNetLwfWinIndicateOffload(pModuleCtx, pModuleCtx->pDisabledOffloadConfig); 2388 2418 Log(("vboxNetLwfWinToggleOffloading: set offloading off\n")); 2389 2419 } … … 2393 2423 if (pModuleCtx->fOffloadConfigValid) 2394 2424 { 2395 vboxNetLwfWinIndicateOffload(pModuleCtx, &pModuleCtx->SavedOffloadConfig);2425 vboxNetLwfWinIndicateOffload(pModuleCtx, pModuleCtx->pSavedOffloadConfig); 2396 2426 Log(("vboxNetLwfWinToggleOffloading: restored offloading config\n")); 2397 2427 }
Note:
See TracChangeset
for help on using the changeset viewer.