Changeset 82775 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Jan 16, 2020 11:50:12 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 135728
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r82681 r82775 60 60 #include "VBoxDD.h" 61 61 62 /* 63 * GSO = Generic Segmentation Offload 64 * TSO = TCP Segmentation Offload 65 * UDP = UDP Fragmentation Offset 62 66 63 67 /********************************************************************************************************************************* … … 70 74 #define VIRTIONET_MAX_FRAME_SIZE 65535 + 18 /**< Max IP pkt size + Ethernet header with VLAN tag */ 71 75 #define VIRTIONET_MAC_FILTER_LEN 32 72 #define VIRTIONET_MAX_V ID(1 << 12)73 74 #define INSTANCE(a_pVirtio) ((a_pVirtio)->szInstanceName) 76 #define VIRTIONET_MAX_VLAN_ID (1 << 12) 77 #define VIRTIONET_PREALLOCATE_RX_SEG_COUNT 32 78 75 79 #define QUEUE_NAME(a_pVirtio, a_idxQueue) ((a_pVirtio)->virtqState[(a_idxQueue)].szVirtqName) 76 80 #define VIRTQNAME(qIdx) (pThis->aszVirtqNames[qIdx]) 77 81 #define CBVIRTQNAME(qIdx) RTStrNLen(VIRTQNAME(qIdx), sizeof(VIRTQNAME(qIdx))) 82 #define FEATURE_ENABLED(feature) (pThis->fNegotiatedFeatures & VIRTIONET_F_##feature) 83 #define FEATURE_DISABLED(feature) (!FEATURE_ENABLED(feature)) 78 84 79 85 /* Macros to calculate queue specific index number VirtIO 1.0, 5.1.2 */ … … 87 93 88 94 #define LUN0 0 95 96 97 /* 98 * Glossary of networking acronyms used in the following bit definitions: 99 * 100 * GSO = Generic Segmentation Offload 101 * TSO = TCP Segmentation Offload 102 * UFO = UDP Fragmentation Offload 103 * ECN = Explicit Congestion Notification 104 */ 105 89 106 /** @name VirtIO 1.0 NET Host feature bits (See VirtIO 1.0 specification, Section 5.6.3) 90 107 * @{ */ … … 106 123 #define VIRTIONET_F_CTRL_RX RT_BIT_64(18) /**< Control channel RX mode + MAC addr filtering */ 107 124 #define VIRTIONET_F_CTRL_VLAN RT_BIT_64(19) /**< Control channel VLAN filtering */ 125 #define VIRTIONET_F_CTRL_RX_EXTRA RT_BIT_64(20) /**< Control channel RX mode extra functions */ 108 126 #define VIRTIONET_F_GUEST_ANNOUNCE RT_BIT_64(21) /**< Driver can send gratuitous packets */ 109 127 #define VIRTIONET_F_MQ RT_BIT_64(22) /**< Support ultiqueue with auto receive steering */ … … 179 197 uint16_t uHdrLen; /**< hdr_len */ 180 198 uint16_t uGsoSize; /**< gso_size */ 181 uint16_t uC sumStart; /**< csum_start */182 uint16_t uC sumOffset; /**< csum_offset */199 uint16_t uChksumStart; /**< Chksum_start */ 200 uint16_t uChksumOffset; /**< Chksum_offset */ 183 201 uint16_t uNumBuffers; /**< num_buffers */ 184 202 }; 185 203 #pragma pack() 186 typedef virtio_net_hdr VIRTIONET_PKT_HDR , *PVIRTIONET_PKT_HDR;187 AssertCompileSize(VIRTIONET_PKT_HDR , 12);204 typedef virtio_net_hdr VIRTIONET_PKT_HDR_T, *PVIRTIONET_PKT_HDR_T; 205 AssertCompileSize(VIRTIONET_PKT_HDR_T, 12); 188 206 189 207 /* Control virtq: Command entry (VirtIO 1.0, 5.1.6.5) */ … … 192 210 uint8_t uClass; /**< class */ 193 211 uint8_t uCmd; /**< command */ 212 uint8_t uCmdSpecific; /**< command specific */ 194 213 }; 195 214 #pragma pack() 196 typedef virtio_net_ctrl_hdr VIRTIONET_CTRL_HDR , *PVIRTIONET_CTRL_HDR;197 198 typedef uint8_t VIRTIONET_CTRL_HDR_ ACK;215 typedef virtio_net_ctrl_hdr VIRTIONET_CTRL_HDR_T, *PVIRTIONET_CTRL_HDR_T; 216 217 typedef uint8_t VIRTIONET_CTRL_HDR_T_ACK; 199 218 200 219 /* Command entry fAck values */ 201 #define VIRTIO _NET_OK 0202 #define VIRTIO _NET_ERR1220 #define VIRTIONET_OK 0 221 #define VIRTIONET_ERROR 1 203 222 204 223 /** @name Control virtq: Receive filtering flags (VirtIO 1.0, 5.1.6.5.1) … … 213 232 /** @} */ 214 233 215 216 typedef uint32_t VIRTIONET_CTRL_MAC_ HDR;234 typedef uint8_t VIRTIONET_MAC_ADDRESS[6]; 235 typedef uint32_t VIRTIONET_CTRL_MAC_TABLE_LEN; 217 236 typedef uint8_t VIRTIONET_CTRL_MAC_ENTRIES[][6]; 218 237 … … 253 272 /** @name Offload State Configuration Flags (VirtIO 1.0, 5.1.6.5.6.1) 254 273 * @{ */ 255 //#define VIRTIONET_F_GUEST_CSUM 1 /**< Guest offloads C SUM*/274 //#define VIRTIONET_F_GUEST_CSUM 1 /**< Guest offloads Chksum */ 256 275 //#define VIRTIONET_F_GUEST_TSO4 7 /**< Guest offloads TSO4 */ 257 276 //#define VIRTIONET_F_GUEST_TSO6 8 /**< Guest Offloads TSO6 */ … … 323 342 /** Transmit Delay Timer. */ 324 343 TMTIMERHANDLE hTxTimer; 325 uint32_t u 32i;326 uint32_t u 32AvgDiff;327 uint32_t u 32MinDiff;328 uint32_t u 32MaxDiff;344 uint32_t ui; 345 uint32_t uAvgDiff; 346 uint32_t uMinDiff; 347 uint32_t uMaxDiff; 329 348 uint64_t u64NanoTS; 330 349 #else /* !VNET_TX_DELAY */ … … 336 355 uint32_t uIsTransmitting; 337 356 338 // /** PCI config area holding MAC address as well as TBD. */339 // struct VNetPCIConfig config;340 341 357 /** MAC address obtained from the configuration. */ 342 358 RTMAC macConfigured; 343 359 360 /** Default MAC address which rx filtering accepts */ 361 RTMAC rxFilterMacDefault; 362 344 363 /** True if physical cable is attached in configuration. */ 345 364 bool fCableConnected; … … 351 370 352 371 /** Number of packet being sent/received to show in debug log. */ 353 uint32_t u 32PktNo;372 uint32_t uPktNo; 354 373 355 374 /** N/A: */ 356 375 bool volatile fMaybeOutOfSpace; 357 376 377 /** Flags whether VirtIO core is in ready state */ 378 uint8_t fVirtioReady; 379 358 380 /** Resetting flag */ 359 boolfResetting;381 uint8_t fResetting; 360 382 361 383 /** Promiscuous mode -- RX filter accepts all packets. */ 362 bool fPromiscuous; 363 /** AllMulti mode -- RX filter accepts all multicast packets. */ 364 bool fAllMulti; 365 /** The number of actually used slots in aMacTable. */ 366 uint32_t cMacFilterEntries; 367 /** Array of MAC addresses accepted by RX filter. */ 368 RTMAC aMacFilter[VIRTIONET_MAC_FILTER_LEN]; 384 uint8_t fPromiscuous; 385 386 /** All multicast mode -- RX filter accepts all multicast packets. */ 387 uint8_t fAllMulticast; 388 389 /** All unicast mode -- RX filter accepts all unicast packets. */ 390 uint8_t fAllUnicast; 391 392 /** No multicast mode - Supresses multicast receive */ 393 uint8_t fNoMulticat; 394 395 /** No unicast mode - Suppresses unicast receive */ 396 uint8_t fNoUnicast; 397 398 /** No broadcast mode - Supresses broadcast receive */ 399 uint8_t fNoBroadcast; 400 401 /** The number of actually used slots in aMacMulticastFilter. */ 402 uint32_t cMulticastFilterMacs; 403 404 /** Array of MAC multicast addresses accepted by RX filter. */ 405 RTMAC aMacMulticastFilter[VIRTIONET_MAC_FILTER_LEN]; 406 407 /** The number of actually used slots in aMacUniicastFilter. */ 408 uint32_t cUnicastFilterMacs; 409 410 /** Array of MAC unicast addresses accepted by RX filter. */ 411 RTMAC aMacUnicastFilter[VIRTIONET_MAC_FILTER_LEN]; 412 369 413 /** Bit array of VLAN filter, one bit per VLAN ID. */ 370 414 uint8_t aVlanFilter[VIRTIONET_MAX_VID / sizeof(uint8_t)]; … … 385 429 STAMCOUNTER StatTransmitPackets; 386 430 STAMCOUNTER StatTransmitGSO; 387 STAMCOUNTER StatTransmitC Sum;431 STAMCOUNTER StatTransmitChksum; 388 432 #ifdef VBOX_WITH_STATISTICS 389 433 STAMPROFILE StatReceive; … … 554 598 DECLINLINE(bool) virtioNetValidateRequiredFeatures(uint32_t fFeatures) 555 599 { 556 uint32_t fGuestC sumRequired = fFeatures & VIRTIONET_F_GUEST_TSO4600 uint32_t fGuestChksumRequired = fFeatures & VIRTIONET_F_GUEST_TSO4 557 601 || fFeatures & VIRTIONET_F_GUEST_TSO6 558 602 || fFeatures & VIRTIONET_F_GUEST_UFO; 559 603 560 uint32_t fHostC sumRequired = fFeatures & VIRTIONET_F_HOST_TSO4604 uint32_t fHostChksumRequired = fFeatures & VIRTIONET_F_HOST_TSO4 561 605 || fFeatures & VIRTIONET_F_HOST_TSO6 562 606 || fFeatures & VIRTIONET_F_HOST_UFO; … … 568 612 || fFeatures & VIRTIONET_F_CTRL_MAC_ADDR; 569 613 570 if (fGuestC sumRequired && !(fFeatures & VIRTIONET_F_GUEST_CSUM))614 if (fGuestChksumRequired && !(fFeatures & VIRTIONET_F_GUEST_CSUM)) 571 615 return false; 572 616 573 if (fHostC sumRequired && !(fFeatures & VIRTIONET_F_CSUM))617 if (fHostChksumRequired && !(fFeatures & VIRTIONET_F_CSUM)) 574 618 return false; 575 619 … … 616 660 } 617 661 } 618 }619 620 /**621 * @callback_method_impl{VIRTIOCORER3,pfnStatusChanged}622 */623 static DECLCALLBACK(void) virtioNetR3StatusChanged(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint32_t fVirtioReady)624 {625 PVIRTIONET pThis = RT_FROM_MEMBER(pVirtio, VIRTIONET, Virtio);626 PVIRTIONETCC pThisCC = RT_FROM_MEMBER(pVirtioCC, VIRTIONETCC, Virtio);627 628 RT_NOREF5(pThis, pThisCC, pVirtio, pVirtioCC, fVirtioReady);629 662 } 630 663 … … 766 799 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 767 800 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 768 PCPDMDEVHLPR3 801 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 769 802 770 803 RT_NOREF(pThisCC); … … 778 811 for (int qIdx = 0; qIdx < pThis->cVirtQueues; qIdx++) 779 812 pHlp->pfnSSMGetBool(pSSM, &pThis->afQueueAttached[qIdx]); 780 781 813 782 814 /* … … 835 867 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 836 868 837 // if (ASMAtomicRead U32(&pThis->cActiveReqs))869 // if (ASMAtomicReadu(&pThis->cActiveReqs)) 838 870 // return false; 839 871 … … 866 898 867 899 /* If already quiesced invoke async callback. */ 868 // if (!ASMAtomicRead U32(&pThis->cActiveReqs))900 // if (!ASMAtomicReadu(&pThis->cActiveReqs)) 869 901 // PDMDevHlpAsyncNotificationCompleted(pDevIns); 870 902 } … … 951 983 } 952 984 953 static void virtioNetR3Ctrl(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, PVIRTIO_DESC_CHAIN_T pDescChain) 954 { 955 RT_NOREF4(pDevIns, pThis, pThisCC, pDescChain); 956 } 985 /* Device operation: Net header packet (VirtIO 1.0, 5.1.6) */ 986 #pragma pack(1) 987 struct virtio_net_hdr { 988 uint8_t uFlags; /**< flags */ 989 uint8_t uGsoType; /**< gso_type */ 990 uint16_t uHdrLen; /**< hdr_len */ 991 uint16_t uGsoSize; /**< gso_size */ 992 uint16_t uChksumStart; /**< csum_start */ 993 uint16_t uChksumOffset; /**< csum_offset */ 994 uint16_t uNumBuffers; /**< num_buffers */ 995 }; 996 #pragma pack() 997 typedef virtio_net_hdr VIRTIONET_PKT_HDR_T, *PVIRTIONET_PKT_HDR_T; 998 AssertCompileSize(VIRTIONET_PKT_HDR_T, 12); 999 1000 /** 1001 * Determines if the packet is to be delivered to upper layer. 1002 * 1003 * @returns true if packet is intended for this node. 1004 * @param pThis Pointer to the state structure. 1005 * @param pvBuf The ethernet packet. 1006 * @param cb Number of bytes available in the packet. 1007 */ 1008 static bool vnetR3AddressFilter(PVNETSTATE pThis, const void *pvBuf, size_t cb) 1009 { 1010 if (pThis->fPromiscuous) 1011 return true; 1012 1013 /* Ignore everything outside of our VLANs */ 1014 uint16_t *uPtr = (uint16_t*)pvBuf; 1015 /* Compare TPID with VLAN Ether Type */ 1016 if ( uPtr[6] == RT_H2BE_u(0x8100) 1017 && !ASMBitTest(pThis->aVlanFilter, RT_BE2H_u(uPtr[7]) & 0xFFF)) 1018 { 1019 Log4(("%s vnetR3AddressFilter: not our VLAN, returning false\n", INSTANCE(pThis))); 1020 return false; 1021 } 1022 1023 if (vnetR3IsBroadcast(pvBuf)) 1024 return true; 1025 1026 if (pThis->fAllMulti && vnetR3IsMulticast(pvBuf)) 1027 return true; 1028 1029 if (!memcmp(pThis->config.mac.au, pvBuf, sizeof(RTMAC))) 1030 return true; 1031 Log4(("%s vnetR3AddressFilter: %RTmac (conf) != %RTmac (dest)\n", INSTANCE(pThis), pThis->config.mac.au, pvBuf)); 1032 1033 for (unsigned i = 0; i < pThis->cMacFilterEntries; i++) 1034 if (!memcmp(&pThis->aMacFilter[i], pvBuf, sizeof(RTMAC))) 1035 return true; 1036 1037 Log2(("%s vnetR3AddressFilter: failed all tests, returning false, packet dump follows:\n", INSTANCE(pThis))); 1038 vnetR3PacketDump(pThis, (const uint8_t *)pvBuf, cb, "<-- Incoming"); 1039 1040 return false; 1041 } 1042 1043 /** 1044 * Pad and store received packet. 1045 * 1046 * @remarks Make sure that the packet appears to upper layer as one coming 1047 * from real Ethernet: pad it and insert FCS. 1048 * 1049 * @returns VBox status code. 1050 * @param pDevIns The device instance. 1051 * @param pThis The virtio-net shared instance data. 1052 * @param pvBuf The available data. 1053 * @param cb Number of bytes available in the buffer. 1054 * @thread RX 1055 */ 1056 static int virtioNetR3HandleRxPacket(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 1057 const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso) 1058 { 1059 VIRTIONET_PKT_HDR_T rxPktHdr; 1060 1061 if (pGso) 1062 { 1063 Log2Func(("%s gso type=%x cbPktHdrsTotal=%u cbPktHdrsSeg=%u mss=%u off1=0x%x off2=0x%x\n", 1064 pThis->szInstanceName, pGso->uType, pGso->cbHdrsTotal, 1065 pGso->cbHdrsSeg, pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2)); 1066 1067 rxPktHdr.uFlags = VIRTIONET_HDR_F_NEEDS_CSUM; 1068 switch (pGso->uType) 1069 { 1070 case PDMNETWORKGSOTYPE_IPV4_TCP: 1071 rxPktHdr.uGsoType = VIRTIONET_HDR_GSO_TCPV4; 1072 rxPktHdr.uCSumOffset = RT_OFFSETOF(RTNETTCP, th_sum); 1073 break; 1074 case PDMNETWORKGSOTYPE_IPV6_TCP: 1075 rxPktHdr.uGsoType = VIRTIONET_HDR_GSO_TCPV6; 1076 rxPktHdr.uCSumOffset = RT_OFFSETOF(RTNETTCP, th_sum); 1077 break; 1078 case PDMNETWORKGSOTYPE_IPV4_UDP: 1079 rxPktHdr.uGsoType = VIRTIONET_HDR_GSO_UDP; 1080 rxPktHdr.uCSumOffset = RT_OFFSETOF(RTNETUDP, uh_sum); 1081 break; 1082 default: 1083 return VERR_INVALID_PARAMETER; 1084 } 1085 rxPktHdr.uHdrLen = pGso->cbHdrsTotal; 1086 rxPktHdr.uGSOSize = pGso->cbMaxSeg; 1087 rxPktHdr.uCSumStart = pGso->offHdr2; 1088 STAM_REL_COUNTER_INC(&pThis->StatReceiveGSO); 1089 } 1090 else 1091 { 1092 rxPktHdr.uFlags = 0; 1093 rxPktHdr.uGsoType = VIRTIONET_HDR_GSO_NONE; 1094 } 1095 1096 virtioNetR3PacketDump(pThis, (const uint8_t *)pvBuf, cb, "<-- Incoming"); 1097 1098 PRTSGBUF pSegsBuf; 1099 PRTSGSEG paSegs = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 2); 1100 AssertReturn(paSegs, VERR_NO_MEMORY); 1101 RTSgBufInit(pSegsBuf, paSegs, cSegs); 1102 1103 uint16_t *pPhysPktHdrNumBufs, cDescs = 0; 1104 1105 uint8_t fFirstIteration = true; 1106 for (uint32_t uOffset = 0; uOffset < cb; fFirstIteration = false) 1107 { 1108 PVIRTIO_DESC_CHAIN_T pDescChain; 1109 int rc = virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, RXQIDX(0), &pDescChain, true); 1110 1111 AssertRC(rc == VINF_SUCCESS || rc == VERR_NOT_AVAILABLE, rc); 1112 1113 /* todo: Find a better way to deal with this */ 1114 AssertMsgReturn(rc == VINF_SUCCESS && pDescChain->cbPhysSend, 1115 ("Not enough Rx buffers in queue to accomodate ethernet packet\n"), 1116 VERR_INTERNAL_ERROR); 1117 1118 AssertMsgReturn(pDescChain->cbPhysReturn >= sizeof(VIRTIONET_PKT_HDR_T), 1119 ("Desc chain's phys segs have insufficient space for pkt header!\n"), 1120 VERR_INTERNAL_ERROR); 1121 1122 uint32_t cbDescChainLeft = pDescChain->cbPhysSend; 1123 1124 uint16_t cSegs = 0; 1125 if (fFirstIteration) 1126 { 1127 /* Lead with packet header */ 1128 paSegs[cSegs].cbSeg = sizeof(VIRTIONET_PKT_HDR_T); 1129 paSegs[cSegs].pvSeg = RTMemAlloc(paSegs[0].cb); 1130 AssertReturn(paSegs[0].pvSeg, VERR_NO_MEMORY); 1131 cbDescChainLeft -= paReqSegs[0].cb; 1132 *pPhysPktHdrNumBufs = ((uint8_t *)paSegs[cSegs].pvSeg) 1133 + RT_UOFFSETOF(VIRTIONET_PKT_HDR_T, uNumBuffers); 1134 cSegs++; 1135 } 1136 1137 /* Append remaining Rx pkt or as much current desc chain has room for */ 1138 uint32_t uSize = RT_MIN(cb, cbDescChainLeft); 1139 paSegs[cSegs].cbSeg = uSize; 1140 paSegs[cSegs++].pvSeg = ((uint8_t)pvBuf) + uOffset; 1141 uOffset += uSize; 1142 cDescs++; 1143 1144 virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, RXQIDX(0), pSegsBuf, pDescChain, true); 1145 1146 if (FEATURE_DISABLED(MRG_RXBUF)) 1147 break; 1148 } 1149 1150 /* Fix up pkt hdr (already in guest phys. memory) with number of descriptors to send */ 1151 1152 int rc = PDMDevHlpPCIPhysWrite(pDevIns, pPhysPktHdrNumBuffers, cDescs, sizeof(cDescs)); 1153 AssertMsgRCReturn(rc, "Failure updating descriptor count in pkt hdr in guest physical memory\n"); 1154 1155 virtioCoreQueueSync(pDevIns, &pThis->Virtio, RXQIDX(0)); 1156 1157 for (int i = 0; i < 2; i++) 1158 RTMemFree(paSegs[i].pvSeg); 1159 RTMemFree(paSegs); 1160 RTMemFree(pSegsBuf); 1161 1162 if (uOffset < cb) 1163 { 1164 Log(("%s vnetR3HandleRxPacket: Packet did not fit into RX queue (packet size=%u)!\n", INSTANCE(pThis), cb)); 1165 return VERR_TOO_MUCH_DATA; 1166 } 1167 1168 return VINF_SUCCESS; 1169 } 1170 1171 /** 1172 * @interface_method_impl{PDMINETWORKDOWN,pfnReceiveGso} 1173 */ 1174 static DECLCALLBACK(int) virtioNetR3ReceiveGso(PPDMINETWORKDOWN pInterface, const void *pvBuf, 1175 size_t cb, PCPDMNETWORKGSO pGso) 1176 { 1177 PVIRTIONETCC pThisCC = RT_FROM_MEMBER(pInterface, PVIRTIONETCC, INetworkDown); 1178 PPDMDEVINS pDevIns = pThisCC->pDevIns; 1179 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1180 1181 if (pGso) 1182 { 1183 uint32_t uFeatures = pThis->VPCI.uGuestFeatures; 1184 1185 switch (pGso->uType) 1186 { 1187 case PDMNETWORKGSOTYPE_IPV4_TCP: 1188 uFeatures &= VIRTIONET_F_GUEST_TSO4; 1189 break; 1190 case PDMNETWORKGSOTYPE_IPV6_TCP: 1191 uFeatures &= VIRTIONET_F_GUEST_TSO6; 1192 break; 1193 case PDMNETWORKGSOTYPE_IPV4_UDP: 1194 case PDMNETWORKGSOTYPE_IPV6_UDP: 1195 uFeatures &= VIRTIONET_F_GUEST_UFO; 1196 break; 1197 default: 1198 uFeatures = 0; 1199 break; 1200 } 1201 if (!uFeatures) 1202 { 1203 Log2Func((GSO type (0x%x) not supported\n", pThis->szInstanceName, pGso->uType)); 1204 return VERR_NOT_SUPPORTED; 1205 } 1206 } 1207 1208 Log2Func(("pvBuf=%p cb=%u pGso=%p\n", pThis->szInstanceName, pvBuf, cb, pGso)); 1209 1210 int rc = virtioR3CanReceive(pDevIns, pThis, pThisCC); 1211 if (RT_FAILURE(rc)) 1212 return rc; 1213 1214 /* Drop packets if VM is not running or cable is disconnected. */ 1215 VMSTATE enmVMState = PDMDevHlpVMState(pDevIns); 1216 if (( enmVMState != VMSTATE_RUNNING 1217 && enmVMState != VMSTATE_RUNNING_LS) 1218 || !(pThis->virtioNetConfig.uStatus & VIRTIONET_S_LINK_UP)) 1219 return VINF_SUCCESS; 1220 1221 STAM_PROFILE_START(&pThis->StatReceive, a); 1222 virtioNetR3SetReadLed(&pThisCC, true); 1223 if (virtioNetR3AddressFilter(pThis, pvBuf, cb)) 1224 { 1225 rc = virtioNetCsRxEnter(pThis, VERR_SEM_BUSY); 1226 if (RT_SUCCESS(rc)) 1227 { 1228 rc = virtioNetR3HandleRxPacket(pDevIns, pThis, pThisCC, pvBuf, cb, pGso); 1229 STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb); 1230 virtioNetCsRxLeave(pThis); 1231 } 1232 } 1233 virtioNetR3SetReadLed(&pThisCC, false); 1234 STAM_PROFILE_STOP(&pThis->StatReceive, a); 1235 return rc; 1236 } 1237 1238 1239 DECLINLINE(uint16_t) virtioNetR3Checkum16(const void *pvBuf, size_t cb) 1240 { 1241 uint32_t chksum = 0; 1242 uint16_t *pu = (uint16_t *)pvBuf; 1243 1244 while (cb > 1) 1245 { 1246 chksum += *pu++; 1247 cb -= 2; 1248 } 1249 if (cb) 1250 chksum += *(uint8_t*)pu; 1251 while (chksum >> 16) 1252 chksum = (chksum >> 16) + (chksum & 0xFFFF); 1253 return ~chksum; 1254 } 1255 1256 DECLINLINE(void) virtioNetR3CompleteChecksum(uint8_t *pBuf, size_t cbSize, uint16_t uStart, uint16_t uOffset) 1257 { 1258 AssertReturnVoid(uStart < cbSize); 1259 AssertReturnVoid(uStart + uOffset + sizeof(uint16_t) <= cbSize); 1260 *(uint16_t *)(pBuf + uStart + uOffset) = vnetR3Chksum16(pBuf + uStart, cbSize - uStart); 1261 } 1262 1263 /* Read physical bytes from the out segment(s) of descriptor chain */ 1264 static void virtioNetR3PullChain(PVIRTIO_DESC_CHAIN_T pDecChain, void *pv, uint16_t cb) 1265 { 1266 uint8_t *pb = (uint8_t *)pv; 1267 for (size_t cb = RT_MIN(pDescChain->cbPhysSend, sizeof(VIRTIONET_PKT_HDR_T)); cb; ) 1268 { 1269 size_t cbSeg = cb; 1270 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg); 1271 PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pb, cbSeg); 1272 pb += cbSeg; 1273 cb -= cbSeg; 1274 } 1275 } 1276 static bool virtioNetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONET_PKT_HDR_T pPktHdr, uint32_t cbMax) 1277 { 1278 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pPktHdr, sizeof(*pPktHdr)); 1279 if (RT_FAILURE(rc)) 1280 return false; 1281 1282 Log4(("virtio-net: header flags=%x gso-type=%x len=%x gso-size=%x Chksum-start=%x Chksum-offset=%x cb=%x\n", 1283 pPktHdr->uFlags, pPktHdr->uGsoType, pPktHdr->uHdrLen, pPktHdr->uGSOSize, pPktHdr->uChksumStart, pPktHdr->uChksumOffset, cbMax)); 1284 1285 if (pPktHdr->uGsoType) 1286 { 1287 uint32_t uMinHdrSize; 1288 1289 /* Segmentation offloading cannot be done without checksumming, and we do not support ECN */ 1290 if ( RT_UNLIKELY(!(pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM)) 1291 | RT_UNLIKELY(pPktHdr->uGsoType & VIRTIONET_HDR_GSO_ECN))) 1292 return false; 1293 1294 switch (pPktHdr->uGsoType) 1295 { 1296 case VIRTIONET_HDR_GSO_TCPV4: 1297 case VIRTIONET_HDR_GSO_TCPV6: 1298 uMinHdrSize = sizeof(RTNETTCP); 1299 break; 1300 case VIRTIONET_HDR_GSO_UDP: 1301 uMinHdrSize = 0; 1302 break; 1303 default: 1304 return false; 1305 } 1306 /* Header + MSS must not exceed the packet size. */ 1307 if (RT_UNLIKELY(uMinHdrSize + pPktHdr->uChksumStart + pPktHdr->uGSOSize > cbMax)) 1308 return false; 1309 } 1310 /* Checksum must fit into the frame (validating both checksum fields). */ 1311 if (( pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM) 1312 && sizeof(uint16_t) + pPktHdr->uChksumStart + pPktHdr->uChksumOffset > cbMax) 1313 return false; 1314 Log4func(("returning true\n")); 1315 return true; 1316 } 1317 1318 static uint8_t virtioNetR3CtrlRx(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 1319 PVIRTIONET_PKT_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain) 1320 { 1321 #define LOG_VIRTIONET_FLAG(field) LogFunc(("%s = %d\n", #field, pThis->field)); 1322 1323 LogFunc(("")); 1324 switch(pCtrlPktHdr->uCmd) 1325 { 1326 case VIRTIONET_CTRL_RX_PROMISC: 1327 break; 1328 case VIRTIONET_CTRL_RX_ALLMULTI: 1329 break; 1330 case VIRTIONET_CTRL_RX_ALLUNI: 1331 /* fallthrough */ 1332 case VIRTIONET_CTRL_RX_NOMULTI: 1333 /* fallthrough */ 1334 case VIRTIONET_CTRL_RX_NOUNI: 1335 /* fallthrough */ 1336 case VIRTIONET_CTRL_RX_NOBCAST: 1337 AssertMsgReturn(fFeatures & VIRTIONET_F_CTRL_RX_EXTRA, 1338 ("CTRL "extra" cmd w/o VIRTIONET_F_CTRL_RX_EXTRA feature negotiated - skipping\n"), 1339 VIRTIONET_ERROR); 1340 /* fall out */ 1341 } 1342 1343 uint8_t fOn, fPromiscChanged = false; 1344 virtioNetR3PullChain(pDescChain, &fOn, RT_MIN(pDescChain->cbPhysSend, sizeof(fOn))); 1345 1346 switch(pCtrlPktHdr->uCmd) 1347 { 1348 case VIRTIONET_CTRL_RX_PROMISC: 1349 pThis->fPromiscuous = !!fOn; 1350 fPromiscChanged = true; 1351 LOG_VIRTIONET_FLAG(fPromiscuous) 1352 break; 1353 case VIRTIONET_CTRL_RX_ALLMULTI: 1354 pThis->fAllMulticast = !!fOn; 1355 fPromiscChanged = true; 1356 LOG_VIRTIONET_FLAG(fAllMulticast); 1357 break; 1358 case VIRTIONET_CTRL_RX_ALLUNI: 1359 pThis->fAllUnicast = !!fOn; 1360 LOG_VIRTIONET_FLAG(fAllUnicast); 1361 break; 1362 case VIRTIONET_CTRL_RX_NOMULTI: 1363 pThis->fNoMulticast = !!fOn; 1364 LOG_VIRTIONET_FLAG(fNoMulticast); 1365 break; 1366 case VIRTIONET_CTRL_RX_NOUNI: 1367 pThis->fNoUnicast = !!fOn; 1368 LOG_VIRTIONET_FLAG(fNoUnicast); 1369 break; 1370 case VIRTIONET_CTRL_RX_NOBCAST: 1371 pThis->fNoBroadcast = !!fOn; 1372 LOG_VIRTIONET_FLAG(fNoBroadcast); 1373 break; 1374 } 1375 1376 if (pThisCC->pDrv && fPromiscChanged) 1377 { 1378 uint8_t fPromiscuous = pThis->fPromiscuous | pThis->fAllMulticast 1379 LogFunc(("Setting promiscuous state to %d\n", fPromiscuous)); 1380 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, fPromiscuous); 1381 } 1382 1383 return VIRTIONET_OK; 1384 } 1385 1386 static uint8_t virtioNetR3CtrlMac(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 1387 PVIRTIONET_PKT_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain) 1388 { 1389 #define ASSERT_CTRL_ADDR_SET(v) \ 1390 AssertMsgReturn((v), ("DESC chain too small to process CTRL_MAC_ADDR_SET cmd"), VIRTIONET_ERROR); 1391 1392 #define ASSERT_CTRL_TABLE_SET(v) \ 1393 AssertMsgReturn((v), ("DESC chain too small to process CTRL_MAC_TABLE_SET cmd"), VIRTIONET_ERROR); 1394 1395 int cbRemaining = pDescChain.cbPhysSend - sizeof(*pCtrlPktHdr); 1396 1397 switch(pCtrlPktHder->uCmd) 1398 { 1399 case VIRTIONET_CTRL_MAC_ADDR_SET: 1400 { 1401 /* Set default Rx filter MAC */ 1402 ASSERT_CTRL_ADDR_SET(cbRemaining >= sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN)); 1403 virtioNetR3PullChain(pDescChain, &pThis->rxFilterMacDefault, sizeof(VIRTIONET_CTRL_MAC_TABLE_LEN)); 1404 break; 1405 } 1406 case VIRTIONET_CTRL_MAC_TABLE_SET: 1407 { 1408 VIRTIONET_CTRL_MAC_TABLE_LEN cMacs; 1409 1410 /* Load unicast MAC filter table */ 1411 ASSERT_CTRL_TABLE_SET(cbRemaining >= sizeof(cMacs)); 1412 virtioNetR3PullChain(pDescChain, &cMacs, sizeof(cMacs)); 1413 cbRemaining -= sizeof(cMacs); 1414 uint32_t cbMacs = cMacs * sizeof(RTMAC); 1415 ASSERT_CTRL_TABLE_SET(cbRemaining >= cbMacs); 1416 virtioNetR3PullChain(pDescChain, &pThis->aMacUnicastFilter, cbMacs); 1417 cbRemaining -= cbMacs; 1418 pThis->cUnicastFilterMacs = cMacs; 1419 1420 /* Load multicast MAC filter table */ 1421 ASSERT_CTRL_TABLE_SET(cbRemaining >= sizeof(cMacs)); 1422 virtioNetR3PullChain(pDescChain, &cMacs, sizeof(cMacs)); 1423 cbRemaining -= sizeof(cMacs); 1424 cbMacs = cMacs * sizeof(RTMAC); 1425 ASSERT_CTRL_TABLE_SET(cbRemaining >= cbMacs); 1426 virtioNetR3PullChain(pDescChain, &pThis->aMacMulticastFilter, cbMacs); 1427 cbRemaining -= cbMacs; 1428 pThis->cMulticastFilterMacs = cMacs; 1429 1430 #ifdef LOG_ENABLED 1431 LogFunc(("%s: unicast MACs:\n", pThis->szInstanceName))); 1432 for(unsigned i = 0; i < nMacs; i++) 1433 LogFunc((" %RTmac\n", &pThis->aMacUnicastFilter[i])); 1434 1435 LogFunc(("%s: multicast MACs:\n", pThis->szInstanceName))); 1436 for(unsigned i = 0; i < nMacs; i++) 1437 LogFunc((" %RTmac\n", &pThis->aMacUnicastFilter[i])); 1438 #endif 1439 1440 } 1441 } 1442 return VIRTIONET_OK; 1443 } 1444 1445 static uint8_t virtioNetR3CtrlVlan(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 1446 PVIRTIONET_PKT_HDR_T pCtrlPktHdr, PVIRTIO_DESC_CHAIN_T pDescChain) 1447 { 1448 uint16_t uVlanId; 1449 int cbRemaining = pDescChain.cbPhysSend - sizeof(*pCtrlPktHdr); 1450 AssertMsgReturn(cbRemaining > sizeof(uVlanId), 1451 ("DESC chain too small for VIRTIO_NET_CTRL_VLAN cmd processing"), VIRTIONET_ERROR); 1452 virtioNetR3PullChain(pDescChain, &uVlanId, sizeof(uVlanId)); 1453 AssertMsgReturn(uVlanId > VIRTIONET_MAX_VLAN_ID, 1454 ("%s VLAN ID out of range (VLAN ID=%u)\n", pThis->szInstanceName, uVlanId), VIRTIONET_ERROR); 1455 LogFunc(("%s: uCommand=%u VLAN ID=%u\n", pThis->szInstanceName, pCtrlPktHdr->uCmd, uVlanId)); 1456 switch (pCtrlPktHdr->uCmd) 1457 { 1458 case VIRTIONET_CTRL_VLAN_ADD: 1459 ASMBitSet(pThis->aVlanFilter, uVlanId); 1460 break; 1461 case VIRTIONET_CTRL_VLAN_DEL: 1462 ASMBitClear(pThis->aVlanFilter, uVlanId); 1463 break; 1464 default: 1465 return VIRTIONET_ERROR; 1466 } 1467 return VIRTIONET_OK; 1468 } 1469 1470 static void virtioNetR3Ctrl(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, 1471 PVIRTIO_DESC_CHAIN_T pDescChain) 1472 { 1473 PVIRTIONET pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIONET); 1474 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 1475 1476 1477 if (pDescChain->cbPhysSend < 2) 1478 { 1479 LogFunc(("ctrl packet from guest driver incomplete. Skipping ctrl cmd\n")); 1480 return; 1481 } 1482 else if (pDescChain->cbPhysReturn < sizeof(VIRTIONET_CTRL_HDR_T_ACK)) 1483 { 1484 LogFunc(("Guest driver didn't allocate memory to receive ctrl pkt ACK. Skipping ctrl cmd\n")); 1485 return; 1486 } 1487 1488 /* 1489 * Allocate buffer and read in the control command 1490 */ 1491 PVIRTIONET_PKT_HDR_T pCtrlPktHdr = (PVIRTIONET_PKT_HDR_T)RTMemAllocZ(sizeof(VIRTIONET_PKT_HDR_T)); 1492 AssertPtrReturn(pCtrlPktHdr, VERR_NO_MEMORY /*ignored*/); 1493 1494 AssertMsgReturnVoid(pDescChain >= sizeof(*pCtrlPktHdr), ("DESC chain too small for CTRL pkt header")); 1495 virtioNetR3PullChain(pDescChain, pCtrlPktHdr, SIZEOF_SEND(pDescChain, VIRTIONET_PKT_HDR_T)); 1496 1497 uint8_t uAck; 1498 switch (pCtrlPktHdr->uClass) 1499 { 1500 case VIRTIONET_CTRL_RX: 1501 uAck = virtioNetR3CtrlRx(pDevIns, pThis, pThisCC, pCtrlPktHdr, pDescChain); 1502 break; 1503 case VIRTIONET_CTRL_MAC: 1504 uAck = virtioNetR3CtrlMac(pDevIns, pThis, pThisCC, pCtrlPktHdr, pDescChain); 1505 break; 1506 case VIRTIONET_CTRL_VLAN: 1507 uAck = virtioNetR3CtrlVlan(pDevIns, pThis, pThisCC, pCtrlPktHdr, pDescChain); 1508 break; 1509 default: 1510 uAck = VIRTIONET_ERROR; 1511 } 1512 1513 PRTSGSEG paReqSegs = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 2); 1514 AssertReturn(paReqSegs, VERR_NO_MEMORY); 1515 1516 RTSGSEG aSegs[] = { { &uAck, sizeof(uAck) } }; 1517 memcpy(paReqSegs, aSegs, sizeof(aSegs)); 1518 1519 PRTSGBUF pReqSegBuf = (PRTSGBUF)RTMemAllocZ(sizeof(RTSGBUF)); 1520 AssertReturn(pReqSegBuf, VERR_NO_MEMORY); 1521 1522 /* Copy segment data to malloc'd memory to avoid stack out-of-scope errors sanitizer doesn't detect */ 1523 for (int i = 0; i < cSegs; i++) 1524 { 1525 void *pv = paReqSegs[i].pvSeg; 1526 paReqSegs[i].pvSeg = RTMemAlloc(paReqSegs[i].cbSeg); 1527 AssertReturn(paReqSegs[i].pvSeg, VERR_NO_MEMORY); 1528 memcpy(paReqSegs[i].pvSeg, pv, paReqSegs[i].cbSeg); 1529 } 1530 1531 RTSgBufInit(pReqSegBuf, paReqSegs, cSegs); 1532 1533 virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, qIdx, pReqSegBuf, pDescChain, true); 1534 virtioCoreQueueSync(pDevIns, &pThis->Virtio, qIdx); 1535 1536 for (int i = 0; i < cSegs; i++) 1537 RTMemFree(paReqSegs[i].pvSeg); 1538 1539 RTMemFree(paReqSegs); 1540 RTMemFree(pReqSegBuf); 1541 1542 LogFunc(("Processed ctrl message class/cmd/subcmd = %u/%u/%u. Ack=%u.\n", 1543 pCtrlPktHdr.uClass, pCtrlPktHdr.uCmd, pCtrlPktHdr.uCmdSpecific, uAck); 1544 1545 } 1546 1547 957 1548 static void virtioNetR3Transmit(PPDMDEVINS pDevIns, PVIRTIONET pThis, PVIRTIONETCC pThisCC, uint16_t qIdx, PVIRTIO_DESC_CHAIN_T pDescChain) 958 1549 { … … 1038 1629 } 1039 1630 1631 #ifdef IN_RING3 1632 1633 /** Returns true if large packets are written into several RX buffers. */ 1634 DECLINLINE(bool) virtioNetR3MergeableRxBuffers(PVIRTIONET pThis) 1635 { 1636 return !!(pThis->fFeatures & VIRTIONET_F_MRG_RXBUF); 1637 } 1638 1639 DECLINLINE(int) virtioNetR3CsEnter(PPDMDEVINS pDevIns, PVIRTIONET pThis, int rcBusy) 1640 { 1641 /* Original DevVirtioNet uses CS in attach/detach/link-up timer/tx timer/transmit */ 1642 LogFunc("CS unimplemented. What does the critical section protect in orig driver??")); 1643 } 1644 1645 DECLINLINE(void) virtioNetR3CsLeave(PPDMDEVINS pDevIns, PVIRTIONET pThis) 1646 { 1647 LogFunc("CS unimplemented. What does the critical section protect in orig driver??")); 1648 } 1649 1650 /** 1651 * @callback_method_impl{VIRTIOCORER3,pfnStatusChanged} 1652 */ 1653 static DECLCALLBACK(void) virtioNetR3StatusChanged(PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, uint32_t fVirtioReady) 1654 { 1655 PVIRTIONET pThis = RT_FROM_MEMBER(pVirtio, VIRTIONET, Virtio); 1656 PVIRTIONETCC pThisCC = RT_FROM_MEMBER(pVirtioCC, VIRTIONETCC, Virtio); 1657 1658 LogFunc(("")); 1659 1660 pThis->fVirtioReady = fVirtioReady; 1661 1662 if (fVirtioReady) 1663 { 1664 LogFunc(("VirtIO ready\n-----------------------------------------------------------------------------------------\n")); 1665 uint64_t fFeatures = virtioCoreGetNegotiatedFeatures(&pThis->Virtio); 1666 pThis->fResetting = false; 1667 pThisCC->fQuiescing = false; 1668 1669 for (unsigned i = 0; i < VIRTIONET_MAX_QUEUES; i++) 1670 pThis->afQueueAttached[i] = true; 1671 } 1672 else 1673 { 1674 LogFunc(("VirtIO is resetting\n")); 1675 1676 pThis->virtioNetConfig.status = pThis->fCableConnected ? VIRTIONET_S_LINK_UP : 0; 1677 LogFunc(("%s Link is %s\n", pThis->szInstanceName, pThis->fCableConnected ? "up" : "down")); 1678 1679 pThis->fPromiscuous = true; 1680 pThis->fAllMulticast = false; 1681 pThis->fAllUnicast = false; 1682 pThis->fNoMulticat = false; 1683 pThis->fNoUnicast = false; 1684 pThis->fNoBroadcast = false; 1685 pThis->uIsTransmitting = 0; 1686 pThis->cUnicastFilterMacs = 0; 1687 pThis->cMulticastFilterMacs = 0; 1688 1689 memset(pThis->aMacMulticastFilter, 0, sizeof(pThis->aMacMulticastFilter)); 1690 memset(pThis->aMacUnicastFilter, 0, sizeof(pThis->aMacUnicastFilter)); 1691 memset(pThis->aVlanFilter, 0, sizeof(pThis->aVlanFilter)); 1692 1693 pThisCC->pDrv->pfnSetPromiscuousMode(pThisCC->pDrv, true); 1694 1695 for (unsigned i = 0; i < VIRTIONET_MAX_QUEUES; i++) 1696 pThis->afQueueAttached[i] = false; 1697 } 1698 } 1699 #endif /* IN_RING3 */ 1700 1040 1701 /** 1041 1702 * @interface_method_impl{PDMDEVREGR3,pfnDetach} … … 1050 1711 1051 1712 LogFunc(("")); 1052 1053 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, 1054 ("virtio-net: Device does not support hotplugging\n"));1055 RT_NOREF4(pThis, pThisCC, fFlags, iLUN);1713 AssertLogRelReturnVoid(iLUN == 0); 1714 1715 int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); 1716 AssertMsgRCReturn(rc, ("Failed to enter critical section"), rc); 1056 1717 1057 1718 /* 1058 * Zero allimportant members.1719 * Zero important members. 1059 1720 */ 1060 pThisCC->pDrvBase = NULL; 1721 pThisCC->pDrvBase = NULL; 1722 pThisCC->pDrv = NULL; 1723 1724 virtioNetR3CsLeave(pDevIns, pThis); 1061 1725 } 1062 1726 … … 1071 1735 PVIRTIONETCC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIONETCC); 1072 1736 1073 AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, 1074 ("virtio-net: Device does not support hotplugging\n"), 1075 VERR_INVALID_PARAMETER); 1737 RT_NOREF(fFlags); 1738 LogFunc(("%s", INSTANCE(pThis))); 1739 1740 AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN); 1741 1742 int rc = virtioNetR3CsEnter(pDevIns, pThis, VERR_SEM_BUSY); 1743 AssertMsgRCReturn(rc, ("Failed to enter critical section"), rc); 1744 1745 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pDevIns->IBase, &pThisCC->pDrvBase, "Network Port"); 1746 if (RT_SUCCESS(rc)) 1747 { 1748 pThisCC->pDrv = PDMIBASE_QUERY_INTERFACE(pThisCC->pDrvBase, PDMINETWORKUP); 1749 AssertMsgStmt(pThisCC->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"), 1750 rc = VERR_PDM_MISSING_INTERFACE_BELOW); 1751 } 1752 else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER 1753 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME) 1754 Log(("%s No attached driver!\n", INSTANCE(pThis))); 1755 1756 virtioNetR3CsLeave(pDevIns, pThis); 1757 return rc; 1076 1758 1077 1759 AssertRelease(!pThisCC->pDrvBase); 1078 1079 /*1080 * Try attach the NET driver and get the interfaces, required as well as optional.1081 */1082 int rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pDevIns->IBase, &pThisCC->pDrvBase, pThis->szInstanceName);1083 if (RT_FAILURE(rc))1084 AssertMsgFailed(("Failed to attach %s. rc=%Rrc\n", pThis->szInstanceName, rc));1085 1086 if (RT_FAILURE(rc))1087 pThisCC->pDrvBase = NULL;1088 1089 1760 return rc; 1090 1761 } … … 1190 1861 pThisCC->IBase.pfnQueryInterface = virtioNetR3QueryInterface; 1191 1862 pThisCC->ILeds.pfnQueryStatusLed = virtioNetR3QueryStatusLed; 1192 pThisCC->led.u 32Magic = PDMLED_MAGIC;1863 pThisCC->led.uMagic = PDMLED_MAGIC; 1193 1864 1194 1865 /* … … 1198 1869 1199 1870 /* Get config params */ 1200 int rc = pHlp->pfnCFGMQueryBytes(pCfg, "MAC", pThis->macConfigured.au 8, sizeof(pThis->macConfigured));1871 int rc = pHlp->pfnCFGMQueryBytes(pCfg, "MAC", pThis->macConfigured.au, sizeof(pThis->macConfigured)); 1201 1872 if (RT_FAILURE(rc)) 1202 1873 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to get MAC address")); … … 1206 1877 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to get the value of 'CableConnected'")); 1207 1878 1208 rc = pHlp->pfnCFGMQueryU32Def(pCfg, "LinkUpDelay", &pThis->cMsLinkUpDelay, 5000); /* ms */ 1879 uint32_t uStatNo = iInstance; 1880 rc = pHlp->pfnCFGMQueryuDef(pCfg, "StatNo", &uStatNo, iInstance); 1881 if (RT_FAILURE(rc)) 1882 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to get the \"StatNo\" value")); 1883 1884 rc = pHlp->pfnCFGMQueryuDef(pCfg, "LinkUpDelay", &pThis->cMsLinkUpDelay, 5000); /* ms */ 1209 1885 if (RT_FAILURE(rc)) 1210 1886 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to get the value of 'LinkUpDelay'")); 1887 1211 1888 Assert(pThis->cMsLinkUpDelay <= 300000); /* less than 5 minutes */ 1889 1212 1890 if (pThis->cMsLinkUpDelay > 5000 || pThis->cMsLinkUpDelay < 100) 1213 LogRel(("%s WARNING! Link up delay is set to %u seconds!\n", INSTANCE(pThis), pThis->cMsLinkUpDelay / 1000)); 1214 Log(("%s Link up delay is set to %u seconds\n", INSTANCE(pThis), pThis->cMsLinkUpDelay / 1000)); 1215 1216 uint32_t uStatNo = iInstance; 1217 rc = pHlp->pfnCFGMQueryU32Def(pCfg, "StatNo", &uStatNo, iInstance); 1218 if (RT_FAILURE(rc)) 1219 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to get the \"StatNo\" value")); 1220 1221 1222 /* Initialize PCI config space */ 1223 // memcpy(pThis->config.mac.au8, pThis->macConfigured.au8, sizeof(pThis->config.mac.au8)); 1224 // pThis->config.uStatus = 0; 1891 LogRel(("%s WARNING! Link up delay is set to %u seconds!\n", 1892 pThis->szInstanceName, pThis->cMsLinkUpDelay / 1000)); 1893 1894 Log(("%s Link up delay is set to %u seconds\n", pThis->szInstanceName, pThis->cMsLinkUpDelay / 1000)); 1895 1896 /* Copy the MAC address configured for the VM to the MMIO accessible Virtio dev-specific config area */ 1897 memcpy(pThis->virtioNetConfig.uMacAddress, pThis->macConfigured.au, sizeof(pThis->virtioNetConfig.uMacAddress)); /* TBD */ 1225 1898 1226 1899 /* … … 1228 1901 */ 1229 1902 1230 /* Configure virtio_scsi_config that transacts via VirtIO implementation's Dev. Specific Cap callbacks */1231 memset(pThis->virtioNetConfig.uMacAddress, 0, sizeof(pThis->virtioNetConfig.uMacAddress)); /* TBD */1232 1903 #if VIRTIONET_HOST_FEATURES_OFFERED & VIRTIONET_F_STATUS 1233 pThis->virtioNetConfig.uStatus 1904 pThis->virtioNetConfig.uStatus = 0; 1234 1905 #endif 1906 1235 1907 #if VIRTIONET_HOST_FEATURES_OFFERED & VIRTIONET_F_MQ 1236 pThis->virtioNetConfig.uMaxVirtqPairs 1908 pThis->virtioNetConfig.uMaxVirtqPairs = VIRTIONET_MAX_QPAIRS; 1237 1909 #endif 1238 1910 … … 1260 1932 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-net: Required features not successfully negotiated.")); 1261 1933 1262 pThis->cVirtqPairs = pThis->fNegotiatedFeatures & VIRTIONET_F_MQ ? pThis->virtioNetConfig.uMaxVirtqPairs : 1; 1934 pThis->cVirtqPairs = pThis->fNegotiatedFeatures & VIRTIONET_F_MQ 1935 ? pThis->virtioNetConfig.uMaxVirtqPairs : 1; 1263 1936 pThis->cVirtQueues = pThis->cVirtqPairs + 1; 1937 1264 1938 /* 1265 1939 * Initialize queues. … … 1298 1972 pThisCC->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pUpBase, PDMILEDCONNECTORS); 1299 1973 1300 1301 1974 /* 1302 1975 * Register saved state. … … 1312 1985 RTStrPrintf(szTmp, sizeof(szTmp), "%s%u", pDevIns->pReg->szName, pDevIns->iInstance); 1313 1986 PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-net info", virtioNetR3Info); 1314 1315 1987 return rc; 1316 1988 } … … 1338 2010 const PDMDEVREG g_DeviceVirtioNet_1_0 = 1339 2011 { 1340 /* .u 32Version = */ PDM_DEVREG_VERSION,2012 /* .uVersion = */ PDM_DEVREG_VERSION, 1341 2013 /* .uReserved0 = */ 0, 1342 2014 /* .szName = */ "virtio-net-1-dot-0", 1343 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_ RZ | PDM_DEVREG_FLAGS_NEW_STYLE2015 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_NEW_STYLE //| PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE 1344 2016 | PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION 1345 2017 | PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION, … … 1405 2077 # error "Not in IN_RING3, IN_RING0 or IN_RC!" 1406 2078 #endif 1407 /* .u 32VersionEnd = */ PDM_DEVREG_VERSION2079 /* .uVersionEnd = */ PDM_DEVREG_VERSION 1408 2080 }; 1409 2081
Note:
See TracChangeset
for help on using the changeset viewer.