- Timestamp:
- Jan 10, 2022 4:39:58 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r93115 r93165 1104 1104 Log7Func(("[%s] LOAD EXEC (LEGACY)!!\n", pThis->szInst)); 1105 1105 1106 if (memcmp(&uMacLoaded.au8, &pThis->macConfigured.au8, sizeof(uMacLoaded)) 1107 && (uPass == 0 || !PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns))) 1106 if ( memcmp(&uMacLoaded.au8, &pThis->macConfigured.au8, sizeof(uMacLoaded)) 1107 && ( uPass == 0 1108 || !PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns))) 1108 1109 LogRelFunc(("[%s]: The mac address differs: config=%RTmac saved=%RTmac\n", 1109 1110 pThis->szInst, &pThis->macConfigured, &uMacLoaded)); 1110 1111 1111 if (uPass == SSM_PASS_FINAL) 1112 if (uPass == SSM_PASS_FINAL) 1113 { 1114 /* Call the virtio core to have it load legacy device state */ 1115 rc = virtioCoreR3LegacyDeviceLoadExec(&pThis->Virtio, pDevIns->pHlpR3, pSSM, uVersion, VIRTIONET_SAVEDSTATE_VERSION_3_1_BETA1_LEGACY); 1116 AssertRCReturn(rc, rc); 1117 /* 1118 * Scan constructor-determined virtqs to determine if they are all valid-as-restored. 1119 * If so, nudge them with a signal, otherwise destroy the unusable queue(s) 1120 * to avoid tripping up the other queue processing logic. 1121 */ 1122 int cVirtqsToRemove = 0; 1123 for (int uVirtqNbr = 0; uVirtqNbr < pThis->cVirtqs; uVirtqNbr++) 1112 1124 { 1113 /* Call the virtio core to have it load legacy device state */ 1114 rc = virtioCoreR3LegacyDeviceLoadExec(&pThis->Virtio, pDevIns->pHlpR3, pSSM, uVersion, VIRTIONET_SAVEDSTATE_VERSION_3_1_BETA1_LEGACY); 1115 AssertRCReturn(rc, rc); 1116 /* 1117 * Scan constructor-determined virtqs to determine if they are all valid-as-restored. 1118 * If so, nudge them with a signal, otherwise destroy the unusable queue(s) 1119 * to avoid tripping up the other queue processing logic. 1120 */ 1121 int cVirtqsToRemove = 0; 1122 for (int uVirtqNbr = 0; uVirtqNbr < pThis->cVirtqs; uVirtqNbr++) 1125 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[uVirtqNbr]; 1126 if (pVirtq->fHasWorker) 1123 1127 { 1124 PVIRTIONETVIRTQ pVirtq = &pThis->aVirtqs[uVirtqNbr]; 1125 if (pVirtq->fHasWorker) 1128 if (!virtioCoreR3VirtqIsEnabled(&pThis->Virtio, uVirtqNbr)) 1126 1129 { 1127 if (!virtioCoreR3VirtqIsEnabled(&pThis->Virtio, uVirtqNbr)) 1130 virtioNetR3VirtqDestroy(&pThis->Virtio, pVirtq); 1131 ++cVirtqsToRemove; 1132 } 1133 else 1134 { 1135 if (virtioCoreR3VirtqIsAttached(&pThis->Virtio, uVirtqNbr)) 1128 1136 { 1129 virtioNetR3VirtqDestroy(&pThis->Virtio, pVirtq); 1130 ++cVirtqsToRemove; 1131 } 1132 else 1133 { 1134 if (virtioCoreR3VirtqIsAttached(&pThis->Virtio, uVirtqNbr)) 1135 { 1136 Log7Func(("[%s] Waking %s worker.\n", pThis->szInst, pVirtq->szName)); 1137 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[pVirtq->uIdx].hEvtProcess); 1138 AssertRCReturn(rc, rc); 1139 } 1137 Log7Func(("[%s] Waking %s worker.\n", pThis->szInst, pVirtq->szName)); 1138 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[pVirtq->uIdx].hEvtProcess); 1139 AssertRCReturn(rc, rc); 1140 1140 } 1141 1141 } 1142 1142 } 1143 AssertMsg(cVirtqsToRemove < 2, ("Multiple unusable queues in saved state unexpected\n")); 1144 pThis->cVirtqs -= cVirtqsToRemove; 1145 1146 pThis->virtioNetConfig.uStatus = pThis->Virtio.fDeviceStatus; 1147 pThis->fVirtioReady = pThis->Virtio.fDeviceStatus & VIRTIO_STATUS_DRIVER_OK; 1148 1149 rc = pHlp->pfnSSMGetMem(pSSM, pThis->virtioNetConfig.uMacAddress.au8, sizeof(pThis->virtioNetConfig.uMacAddress)); 1143 } 1144 AssertMsg(cVirtqsToRemove < 2, ("Multiple unusable queues in saved state unexpected\n")); 1145 pThis->cVirtqs -= cVirtqsToRemove; 1146 1147 pThis->virtioNetConfig.uStatus = pThis->Virtio.fDeviceStatus; 1148 pThis->fVirtioReady = pThis->Virtio.fDeviceStatus & VIRTIO_STATUS_DRIVER_OK; 1149 1150 rc = pHlp->pfnSSMGetMem(pSSM, pThis->virtioNetConfig.uMacAddress.au8, sizeof(pThis->virtioNetConfig.uMacAddress)); 1151 AssertRCReturn(rc, rc); 1152 1153 if (uVersion > VIRTIONET_SAVEDSTATE_VERSION_3_1_BETA1_LEGACY) 1154 { 1155 rc = pHlp->pfnSSMGetU8( pSSM, &pThis->fPromiscuous); 1150 1156 AssertRCReturn(rc, rc); 1151 1152 if (uVersion > VIRTIONET_SAVEDSTATE_VERSION_3_1_BETA1_LEGACY) 1153 { 1154 rc = pHlp->pfnSSMGetU8( pSSM, &pThis->fPromiscuous); 1155 AssertRCReturn(rc, rc); 1156 rc = pHlp->pfnSSMGetU8( pSSM, &pThis->fAllMulticast); 1157 AssertRCReturn(rc, rc); 1158 /* 1159 * The 0.95 legacy virtio spec defines a control queue command VIRTIO_NET_CTRL_MAC_TABLE_SET, 1160 * wherein guest driver configures two variable length mac filter tables: A unicast filter, 1161 * and a multicast filter. However original VBox virtio-net saved both sets of filter entries 1162 * in a single table, abandoning the distinction between unicast and multicast filters. It preserved 1163 * only *one* filter's table length, leaving no way to separate table back out into respective unicast 1164 * and multicast tables this device implementation preserves. Deduced from legacy code, the original 1165 * assumption was that the both MAC filters are whitelists that can be processed identically 1166 * (from the standpoint of a *single* host receiver), such that the distinction between unicast and 1167 * multicast doesn't matter in any one VM's context. Little choice here but to save the undifferentiated 1168 * unicast & multicast MACs to the unicast filter table and leave multicast table empty/unused. 1169 */ 1170 uint32_t cCombinedUnicastMulticastEntries; 1171 rc = pHlp->pfnSSMGetU32(pSSM, &cCombinedUnicastMulticastEntries); 1172 AssertRCReturn(rc, rc); 1173 AssertReturn(cCombinedUnicastMulticastEntries <= VIRTIONET_MAC_FILTER_LEN, VERR_OUT_OF_RANGE); 1174 pThis->cUnicastFilterMacs = cCombinedUnicastMulticastEntries; 1175 rc = pHlp->pfnSSMGetMem(pSSM, pThis->aMacUnicastFilter, cCombinedUnicastMulticastEntries * sizeof(RTMAC)); 1176 AssertRCReturn(rc, rc); 1177 /* Zero-out the remainder of the Unicast/Multicast filter table */ 1178 memset(&pThis->aMacUnicastFilter[pThis->cUnicastFilterMacs], 0, VIRTIONET_MAC_FILTER_LEN * sizeof(RTMAC)); 1179 rc = pHlp->pfnSSMGetMem(pSSM, pThis->aVlanFilter, sizeof(pThis->aVlanFilter)); 1180 AssertRCReturn(rc, rc); 1157 rc = pHlp->pfnSSMGetU8( pSSM, &pThis->fAllMulticast); 1158 AssertRCReturn(rc, rc); 1159 /* 1160 * The 0.95 legacy virtio spec defines a control queue command VIRTIO_NET_CTRL_MAC_TABLE_SET, 1161 * wherein guest driver configures two variable length mac filter tables: A unicast filter, 1162 * and a multicast filter. However original VBox virtio-net saved both sets of filter entries 1163 * in a single table, abandoning the distinction between unicast and multicast filters. It preserved 1164 * only *one* filter's table length, leaving no way to separate table back out into respective unicast 1165 * and multicast tables this device implementation preserves. Deduced from legacy code, the original 1166 * assumption was that the both MAC filters are whitelists that can be processed identically 1167 * (from the standpoint of a *single* host receiver), such that the distinction between unicast and 1168 * multicast doesn't matter in any one VM's context. Little choice here but to save the undifferentiated 1169 * unicast & multicast MACs to the unicast filter table and leave multicast table empty/unused. 1170 */ 1171 uint32_t cCombinedUnicastMulticastEntries; 1172 rc = pHlp->pfnSSMGetU32(pSSM, &cCombinedUnicastMulticastEntries); 1173 AssertRCReturn(rc, rc); 1174 AssertReturn(cCombinedUnicastMulticastEntries <= VIRTIONET_MAC_FILTER_LEN, VERR_OUT_OF_RANGE); 1175 pThis->cUnicastFilterMacs = cCombinedUnicastMulticastEntries; 1176 rc = pHlp->pfnSSMGetMem(pSSM, pThis->aMacUnicastFilter, cCombinedUnicastMulticastEntries * sizeof(RTMAC)); 1177 AssertRCReturn(rc, rc); 1178 /* Zero-out the remainder of the Unicast/Multicast filter table */ 1179 memset(&pThis->aMacUnicastFilter[pThis->cUnicastFilterMacs], 0, VIRTIONET_MAC_FILTER_LEN * sizeof(RTMAC)); 1180 rc = pHlp->pfnSSMGetMem(pSSM, pThis->aVlanFilter, sizeof(pThis->aVlanFilter)); 1181 AssertRCReturn(rc, rc); 1181 1182 } 1182 1183 else … … 1212 1213 pThis->cMulticastFilterMacs = 0; 1213 1214 memset(&pThis->aMacMulticastFilter, 0, VIRTIONET_MAC_FILTER_LEN * sizeof(RTMAC)); 1214 1215 1215 } 1216 1216 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.