- Timestamp:
- Nov 18, 2009 12:55:18 PM (15 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
r24712 r24757 219 219 STAMPROFILEADV StatIOWriteHC; 220 220 STAMCOUNTER StatIntsRaised; 221 STAMCOUNTER StatIntsSkipped; 221 222 #endif /* VBOX_WITH_STATISTICS */ 222 223 }; … … 496 497 Log(("%s vqueueNotify: Failed to raise an interrupt (%Vrc).\n", INSTANCE(pState), rc)); 497 498 } 499 else 500 { 501 STAM_COUNTER_INC(&pState->StatIntsSkipped); 502 } 503 498 504 } 499 505 … … 1118 1124 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIOWriteHC, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in HC", "/Devices/VNet%d/IO/WriteHC", iInstance); 1119 1125 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIntsRaised, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of raised interrupts", "/Devices/VNet%d/Interrupts/Raised", iInstance); 1126 PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatIntsSkipped, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of skipped interrupts", "/Devices/VNet%d/Interrupts/Skipped", iInstance); 1120 1127 #endif /* VBOX_WITH_STATISTICS */ 1121 1128 … … 1206 1213 #define VNET_TX_DELAY 150 /* 150 microseconds */ 1207 1214 #define VNET_MAX_FRAME_SIZE 65536 // TODO: Is it the right limit? 1215 #define VNET_MAC_FILTER_LEN 32 1216 #define VNET_MAX_VID (1 << 12) 1208 1217 1209 1218 /* Virtio net features */ … … 1289 1298 uint32_t u32PktNo; 1290 1299 1291 /** Locked state -- no state alteration possible. */1292 bool fLocked;1293 1294 1300 /** N/A: */ 1295 1301 bool volatile fMaybeOutOfSpace; 1302 1303 /** Promiscuous mode -- RX filter accepts all packets. */ 1304 bool fPromiscuous; 1305 /** AllMulti mode -- RX filter accepts all multicast packets. */ 1306 bool fAllMulti; 1307 /** The number of actually used slots in aMacTable. */ 1308 uint32_t nMacFilterEntries; 1309 /** Array of MAC addresses accepted by RX filter. */ 1310 RTMAC aMacFilter[VNET_MAC_FILTER_LEN]; 1311 /** Bit array of VLAN filter, one bit per VLAN ID. */ 1312 uint8_t aVlanFilter[VNET_MAX_VID / sizeof(uint8_t)]; 1313 1314 #if HC_ARCH_BITS == 64 1315 uint32_t padding3; 1316 #endif 1296 1317 1297 1318 R3PTRTYPE(PVQUEUE) pRxQueue; … … 1338 1359 AssertCompileMemberOffset(VNETSTATE, VPCI, 0); 1339 1360 1361 #define VNET_OK 0 1362 #define VNET_ERROR 1 1363 typedef uint8_t VNETCTLACK; 1364 1365 #define VNET_CTRL_CLS_RX_MODE 0 1366 #define VNET_CTRL_CMD_RX_MODE_PROMISC 0 1367 #define VNET_CTRL_CMD_RX_MODE_ALLMULTI 1 1368 1369 #define VNET_CTRL_CLS_MAC 1 1370 #define VNET_CTRL_CMD_MAC_TABLE_SET 0 1371 1372 #define VNET_CTRL_CLS_VLAN 2 1373 #define VNET_CTRL_CMD_VLAN_ADD 0 1374 #define VNET_CTRL_CMD_VLAN_DEL 1 1375 1376 1377 struct VNetCtlHdr 1378 { 1379 uint8_t u8Class; 1380 uint8_t u8Command; 1381 }; 1382 typedef struct VNetCtlHdr VNETCTLHDR; 1383 typedef VNETCTLHDR *PVNETCTLHDR; 1384 AssertCompileSize(VNETCTLHDR, 2); 1385 1340 1386 //- TODO: Leave here ---------------------------------------------------------- 1341 1387 … … 1359 1405 PDMBOTHCBDECL(uint32_t) vnetGetHostFeatures(void *pvState) 1360 1406 { 1361 // TODO: implement 1362 return VNET_F_MAC | VNET_F_STATUS; 1407 /* We support: 1408 * - Host-provided MAC address 1409 * - Link status reporting in config space 1410 * - Control queue 1411 * - RX mode setting 1412 * - MAC filter table 1413 * - VLAN filter 1414 */ 1415 return VNET_F_MAC 1416 | VNET_F_STATUS 1417 | VNET_F_CTRL_VQ 1418 | VNET_F_CTRL_RX 1419 | VNET_F_CTRL_VLAN; 1363 1420 } 1364 1421 … … 1414 1471 else 1415 1472 STATUS = 0; 1473 /* 1474 * By default we pass all packets up since the older guests cannot control 1475 * virtio mode. 1476 */ 1477 pState->fPromiscuous = true; 1478 pState->fAllMulti = false; 1479 pState->nMacFilterEntries = 0; 1480 memset(pState->aMacFilter, 0, VNET_MAC_FILTER_LEN * sizeof(RTMAC)); 1481 memset(pState->aVlanFilter, 0, sizeof(pState->aVlanFilter)); 1416 1482 } 1417 1483 … … 1581 1647 1582 1648 /** 1583 * Determines if the packet is to be delivered to upper layer. The following 1584 * filters supported: 1585 * - Exact Unicast/Multicast 1586 * - Promiscuous Unicast/Multicast 1587 * - Multicast 1588 * - VLAN 1649 * Returns true if it is a broadcast packet. 1650 * 1651 * @returns true if destination address indicates broadcast. 1652 * @param pvBuf The ethernet packet. 1653 */ 1654 DECLINLINE(bool) vnetIsBroadcast(const void *pvBuf) 1655 { 1656 static const uint8_t s_abBcastAddr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 1657 return memcmp(pvBuf, s_abBcastAddr, sizeof(s_abBcastAddr)) == 0; 1658 } 1659 1660 /** 1661 * Returns true if it is a multicast packet. 1662 * 1663 * @remarks returns true for broadcast packets as well. 1664 * @returns true if destination address indicates multicast. 1665 * @param pvBuf The ethernet packet. 1666 */ 1667 DECLINLINE(bool) vnetIsMulticast(const void *pvBuf) 1668 { 1669 return (*(char*)pvBuf) & 1; 1670 } 1671 1672 /** 1673 * Determines if the packet is to be delivered to upper layer. 1589 1674 * 1590 1675 * @returns true if packet is intended for this node. … … 1595 1680 static bool vnetAddressFilter(PVNETSTATE pState, const void *pvBuf, size_t cb) 1596 1681 { 1597 return true; // TODO: Implement! 1682 if (pState->fPromiscuous) 1683 return true; 1684 1685 /* Ignore everything outside of our VLANs */ 1686 uint16_t *u16Ptr = (uint16_t*)pvBuf; 1687 /* Compare TPID with VLAN Ether Type */ 1688 if ( u16Ptr[6] == RT_H2BE_U16(0x8100) 1689 && !ASMBitTest(pState->aVlanFilter, RT_BE2H_U16(u16Ptr[7]) & 0xFFF)) 1690 return false; 1691 1692 if (vnetIsBroadcast(pvBuf)) 1693 return true; 1694 1695 if (pState->fAllMulti && vnetIsMulticast(pvBuf)) 1696 return true; 1697 1698 if (!memcmp(pState->config.mac.au8, pvBuf, sizeof(RTMAC))) 1699 return true; 1700 1701 for (unsigned i = 0; i < pState->nMacFilterEntries; i++) 1702 if (!memcmp(&pState->aMacFilter[i], pvBuf, sizeof(RTMAC))) 1703 return true; 1704 1705 return false; 1598 1706 } 1599 1707 … … 1871 1979 #endif /* !VNET_TX_DELAY */ 1872 1980 1981 static uint8_t vnetControlRx(PVNETSTATE pState, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem) 1982 { 1983 uint8_t u8Ack = VNET_OK; 1984 uint8_t fOn; 1985 PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), 1986 pElem->aSegsOut[1].addr, 1987 &fOn, sizeof(fOn)); 1988 Log(("%s vnetControlRx: uCommand=%u fOn=%u\n", INSTANCE(pState), pCtlHdr->u8Command, fOn)); 1989 switch (pCtlHdr->u8Command) 1990 { 1991 case VNET_CTRL_CMD_RX_MODE_PROMISC: 1992 pState->fPromiscuous = !!fOn; 1993 break; 1994 case VNET_CTRL_CMD_RX_MODE_ALLMULTI: 1995 pState->fAllMulti = !!fOn; 1996 break; 1997 default: 1998 u8Ack = VNET_ERROR; 1999 } 2000 2001 return u8Ack; 2002 } 2003 2004 static uint8_t vnetControlMac(PVNETSTATE pState, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem) 2005 { 2006 uint32_t nMacs = 0; 2007 2008 if (pCtlHdr->u8Command != VNET_CTRL_CMD_MAC_TABLE_SET 2009 || pElem->nOut != 3 2010 || pElem->aSegsOut[1].cb < sizeof(nMacs) 2011 || pElem->aSegsOut[2].cb < sizeof(nMacs)) 2012 { 2013 Log(("%s vnetControlMac: Segment layout is wrong " 2014 "(u8Command=%u nOut=%u cb1=%u cb2=%u)\n", INSTANCE(pState), 2015 pCtlHdr->u8Command, pElem->nOut, 2016 pElem->aSegsOut[1].cb, pElem->aSegsOut[2].cb)); 2017 return VNET_ERROR; 2018 } 2019 2020 /* Load unicast addresses */ 2021 PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), 2022 pElem->aSegsOut[1].addr, 2023 &nMacs, sizeof(nMacs)); 2024 2025 if (pElem->aSegsOut[1].cb < nMacs * sizeof(RTMAC) + sizeof(nMacs)) 2026 { 2027 Log(("%s vnetControlMac: The unicast mac segment is too small " 2028 "(nMacs=%u cb=%u)\n", INSTANCE(pState), pElem->aSegsOut[1].cb)); 2029 return VNET_ERROR; 2030 } 2031 2032 if (nMacs > VNET_MAC_FILTER_LEN) 2033 { 2034 Log(("%s vnetControlMac: MAC table is too big, have to use promiscuous" 2035 " mode (nMacs=%u)\n", INSTANCE(pState), nMacs)); 2036 pState->fPromiscuous = true; 2037 } 2038 else 2039 { 2040 if (nMacs) 2041 PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), 2042 pElem->aSegsOut[1].addr + sizeof(nMacs), 2043 pState->aMacFilter, nMacs * sizeof(RTMAC)); 2044 pState->nMacFilterEntries = nMacs; 2045 #ifdef DEBUG 2046 Log(("%s vnetControlMac: unicast macs:\n", INSTANCE(pState))); 2047 for(unsigned i = 0; i < nMacs; i++) 2048 Log((" %RTmac\n", &pState->aMacFilter[i])); 2049 #endif /* DEBUG */ 2050 } 2051 2052 /* Load multicast addresses */ 2053 PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), 2054 pElem->aSegsOut[2].addr, 2055 &nMacs, sizeof(nMacs)); 2056 2057 if (pElem->aSegsOut[2].cb < nMacs * sizeof(RTMAC) + sizeof(nMacs)) 2058 { 2059 Log(("%s vnetControlMac: The multicast mac segment is too small " 2060 "(nMacs=%u cb=%u)\n", INSTANCE(pState), pElem->aSegsOut[2].cb)); 2061 return VNET_ERROR; 2062 } 2063 2064 if (nMacs > VNET_MAC_FILTER_LEN - pState->nMacFilterEntries) 2065 { 2066 Log(("%s vnetControlMac: MAC table is too big, have to use allmulti" 2067 " mode (nMacs=%u)\n", INSTANCE(pState), nMacs)); 2068 pState->fAllMulti = true; 2069 } 2070 else 2071 { 2072 if (nMacs) 2073 PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), 2074 pElem->aSegsOut[2].addr + sizeof(nMacs), 2075 &pState->aMacFilter[pState->nMacFilterEntries], 2076 nMacs * sizeof(RTMAC)); 2077 #ifdef DEBUG 2078 Log(("%s vnetControlMac: multicast macs:\n", INSTANCE(pState))); 2079 for(unsigned i = 0; i < nMacs; i++) 2080 Log((" %RTmac\n", 2081 &pState->aMacFilter[i+pState->nMacFilterEntries])); 2082 #endif /* DEBUG */ 2083 pState->nMacFilterEntries += nMacs; 2084 } 2085 2086 return VNET_OK; 2087 } 2088 2089 static uint8_t vnetControlVlan(PVNETSTATE pState, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem) 2090 { 2091 uint8_t u8Ack = VNET_OK; 2092 uint16_t u16Vid; 2093 2094 if (pElem->nOut != 2 || pElem->aSegsOut[1].cb != sizeof(u16Vid)) 2095 { 2096 Log(("%s vnetControlVlan: Segment layout is wrong " 2097 "(u8Command=%u nOut=%u cb=%u)\n", INSTANCE(pState), 2098 pCtlHdr->u8Command, pElem->nOut, pElem->aSegsOut[1].cb)); 2099 return VNET_ERROR; 2100 } 2101 2102 PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), 2103 pElem->aSegsOut[1].addr, 2104 &u16Vid, sizeof(u16Vid)); 2105 2106 if (u16Vid >= VNET_MAX_VID) 2107 { 2108 Log(("%s vnetControlVlan: VLAN ID is out of range " 2109 "(VID=%u)\n", INSTANCE(pState), u16Vid)); 2110 return VNET_ERROR; 2111 } 2112 2113 Log(("%s vnetControlVlan: uCommand=%u VID=%u\n", INSTANCE(pState), 2114 pCtlHdr->u8Command, u16Vid)); 2115 2116 switch (pCtlHdr->u8Command) 2117 { 2118 case VNET_CTRL_CMD_VLAN_ADD: 2119 ASMBitSet(pState->aVlanFilter, u16Vid); 2120 break; 2121 case VNET_CTRL_CMD_VLAN_DEL: 2122 ASMBitClear(pState->aVlanFilter, u16Vid); 2123 break; 2124 default: 2125 u8Ack = VNET_ERROR; 2126 } 2127 2128 return u8Ack; 2129 } 2130 2131 1873 2132 static DECLCALLBACK(void) vnetQueueControl(void *pvState, PVQUEUE pQueue) 1874 2133 { 1875 2134 VNETSTATE *pState = (VNETSTATE*)pvState; 1876 Log(("%s Pending control message\n", INSTANCE(pState))); 2135 uint8_t u8Ack; 2136 VQUEUEELEM elem; 2137 while (vqueueGet(&pState->VPCI, pQueue, &elem)) 2138 { 2139 unsigned int uOffset = 0; 2140 if (elem.nOut < 1 || elem.aSegsOut[0].cb < sizeof(VNETCTLHDR)) 2141 { 2142 Log(("%s vnetQueueControl: The first 'out' segment is not the " 2143 "header! (%u < 1 || %u < %u).\n", INSTANCE(pState), elem.nOut, 2144 elem.aSegsOut[0].cb,sizeof(VNETCTLHDR))); 2145 vqueueElemFree(&elem); 2146 break; /* Skip the element and hope the next one is good. */ 2147 } 2148 else if ( elem.nIn < 1 2149 || elem.aSegsIn[elem.nIn - 1].cb < sizeof(VNETCTLACK)) 2150 { 2151 Log(("%s vnetQueueControl: The last 'in' segment is too small " 2152 "to hold the acknowledge! (%u < 1 || %u < %u).\n", 2153 INSTANCE(pState), elem.nIn, elem.aSegsIn[elem.nIn - 1].cb, 2154 sizeof(VNETCTLACK))); 2155 vqueueElemFree(&elem); 2156 break; /* Skip the element and hope the next one is good. */ 2157 } 2158 else 2159 { 2160 VNETCTLHDR CtlHdr; 2161 PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), 2162 elem.aSegsOut[0].addr, 2163 &CtlHdr, sizeof(CtlHdr)); 2164 switch (CtlHdr.u8Class) 2165 { 2166 case VNET_CTRL_CLS_RX_MODE: 2167 u8Ack = vnetControlRx(pState, &CtlHdr, &elem); 2168 break; 2169 case VNET_CTRL_CLS_MAC: 2170 u8Ack = vnetControlMac(pState, &CtlHdr, &elem); 2171 break; 2172 case VNET_CTRL_CLS_VLAN: 2173 u8Ack = vnetControlVlan(pState, &CtlHdr, &elem); 2174 break; 2175 default: 2176 u8Ack = VNET_ERROR; 2177 } 2178 Log(("%s Processed control message %u, ack=%u.\n", INSTANCE(pState), 2179 CtlHdr.u8Class, u8Ack)); 2180 PDMDevHlpPhysWrite(pState->VPCI.CTX_SUFF(pDevIns), 2181 elem.aSegsIn[elem.nIn - 1].addr, 2182 &u8Ack, sizeof(u8Ack)); 2183 } 2184 vqueuePut(&pState->VPCI, pQueue, &elem, sizeof(u8Ack)); 2185 vqueueSync(&pState->VPCI, pQueue); 2186 } 1877 2187 } 1878 2188 … … 1940 2250 /* Save device-specific part */ 1941 2251 rc = SSMR3PutMem( pSSM, pState->config.mac.au8, sizeof(pState->config.mac)); 2252 AssertRCReturn(rc, rc); 2253 rc = SSMR3PutBool(pSSM, pState->fPromiscuous); 2254 AssertRCReturn(rc, rc); 2255 rc = SSMR3PutBool(pSSM, pState->fAllMulti); 2256 AssertRCReturn(rc, rc); 2257 rc = SSMR3PutU32( pSSM, pState->nMacFilterEntries); 2258 AssertRCReturn(rc, rc); 2259 rc = SSMR3PutMem( pSSM, pState->aMacFilter, 2260 pState->nMacFilterEntries * sizeof(RTMAC)); 2261 AssertRCReturn(rc, rc); 2262 rc = SSMR3PutMem( pSSM, pState->aVlanFilter, sizeof(pState->aVlanFilter)); 1942 2263 AssertRCReturn(rc, rc); 1943 2264 Log(("%s State has been saved\n", INSTANCE(pState))); … … 2014 2335 if (uPass == SSM_PASS_FINAL) 2015 2336 { 2016 rc = SSMR3GetMem( pSSM, pState->config.mac.au8, sizeof(pState->config.mac)); 2337 rc = SSMR3GetMem( pSSM, pState->config.mac.au8, 2338 sizeof(pState->config.mac)); 2017 2339 AssertRCReturn(rc, rc); 2340 if (uVersion > VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1) 2341 { 2342 rc = SSMR3GetBool(pSSM, &pState->fPromiscuous); 2343 AssertRCReturn(rc, rc); 2344 rc = SSMR3GetBool(pSSM, &pState->fAllMulti); 2345 AssertRCReturn(rc, rc); 2346 rc = SSMR3GetU32(pSSM, &pState->nMacFilterEntries); 2347 AssertRCReturn(rc, rc); 2348 rc = SSMR3GetMem(pSSM, pState->aMacFilter, 2349 pState->nMacFilterEntries * sizeof(RTMAC)); 2350 AssertRCReturn(rc, rc); 2351 /* Clear the rest. */ 2352 if (pState->nMacFilterEntries < VNET_MAC_FILTER_LEN) 2353 memset(&pState->aMacFilter[pState->nMacFilterEntries], 2354 0, 2355 (VNET_MAC_FILTER_LEN - pState->nMacFilterEntries) 2356 * sizeof(RTMAC)); 2357 rc = SSMR3GetMem(pSSM, pState->aVlanFilter, 2358 sizeof(pState->aVlanFilter)); 2359 AssertRCReturn(rc, rc); 2360 } 2361 else 2362 { 2363 pState->fPromiscuous = true; 2364 pState->fAllMulti = false; 2365 pState->nMacFilterEntries = 0; 2366 memset(pState->aMacFilter, 0, VNET_MAC_FILTER_LEN * sizeof(RTMAC)); 2367 memset(pState->aVlanFilter, 0, sizeof(pState->aVlanFilter)); 2368 } 2018 2369 } 2019 2370 … … 2095 2446 2096 2447 /* Initialize state structure */ 2097 pState->fLocked = false;2098 2448 pState->u32PktNo = 1; 2099 2449 -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp
r24749 r24757 1362 1362 GEN_CHECK_OFF(VNETSTATE, pTxBuf); 1363 1363 GEN_CHECK_OFF(VNETSTATE, pLinkUpTimer); 1364 #ifdef VNET_TX_DELAY 1365 GEN_CHECK_OFF(VNETSTATE, pTxTimerR3); 1366 GEN_CHECK_OFF(VNETSTATE, pTxTimerR0); 1367 GEN_CHECK_OFF(VNETSTATE, pTxTimerRC); 1368 #endif /* VNET_TX_DELAY */ 1364 1369 GEN_CHECK_OFF(VNETSTATE, config); 1365 1370 GEN_CHECK_OFF(VNETSTATE, macConfigured); 1366 1371 GEN_CHECK_OFF(VNETSTATE, fCableConnected); 1367 1372 GEN_CHECK_OFF(VNETSTATE, u32PktNo); 1368 GEN_CHECK_OFF(VNETSTATE, fLocked); 1373 GEN_CHECK_OFF(VNETSTATE, fPromiscuous); 1374 GEN_CHECK_OFF(VNETSTATE, fAllMulti); 1369 1375 GEN_CHECK_OFF(VNETSTATE, pRxQueue); 1370 1376 GEN_CHECK_OFF(VNETSTATE, pTxQueue);
Note:
See TracChangeset
for help on using the changeset viewer.