BOOLEAN CopyArgumentGroup(_Out_ OVS_ARGUMENT_GROUP* pDest, _In_ const OVS_ARGUMENT_GROUP* pSource, UINT16 argsMore) { OVS_CHECK(pDest); OVS_CHECK(pSource); AllocateArgumentsToGroup(pSource->count + argsMore, pDest); pDest->count = pSource->count + argsMore; pDest->groupSize = pSource->groupSize; for (UINT i = 0; i < pSource->count; ++i) { if (!CopyArgument(pDest->args + i, pSource->args + i)) { return FALSE; } } return TRUE; }
//TODO: should we put OVS_MESSAGE_FLAG_MULTIPART for Flow_Dump? BOOLEAN CreateMsgFromFlow(_In_ const OVS_FLOW* pFlow, UINT8 command, _Inout_ OVS_MESSAGE* pMsg, UINT32 sequence, UINT32 dpIfIndex, UINT32 portId) { OVS_ARGUMENT_GROUP* pFlowGroup = NULL; OVS_ARGUMENT* pPIArg, *pMasksArg, *pTimeUsedArg, *pFlowStats, *pTcpFlags, *pActionsArg; BOOLEAN ok = TRUE; UINT16 flowArgCount = 0; UINT16 curArg = 0; OVS_WINL_FLOW_STATS winlStats = { 0 }; OVS_FLOW_STATS stats = { 0 }; UINT64 tickCount = 0; UINT8 tcpFlags = 0; UINT16 argsDataSize = 0; LOCK_STATE_EX lockState = { 0 }; OVS_OFPACKET_INFO unmaskedPacketInfo = { 0 }; OVS_OFPACKET_INFO maskedPacketInfo = { 0 }; OVS_OFPACKET_INFO packetInfoMask = { 0 }; OVS_CHECK(pMsg); pPIArg = pMasksArg = pTimeUsedArg = pFlowStats = pTcpFlags = pActionsArg = NULL; FLOW_LOCK_READ(pFlow, &lockState); unmaskedPacketInfo = pFlow->unmaskedPacketInfo; maskedPacketInfo = pFlow->maskedPacketInfo; packetInfoMask = pFlow->pMask->packetInfo; #if OVS_VERSION == OVS_VERSION_1_11 tickCount = pFlow->stats.lastUsedTime; stats.noOfMatchedPackets = pFlow->stats.packetsMached; stats.noOfMatchedBytes = pFlow->stats.bytesMatched; tcpFlags = pFlow->stats.tcpFlags; #elif OVS_VERSION == OVS_VERSION_2_3 //TODO: Flow_GetStats() Flow_GetStats_Unsafe(pFlow, &stats); winlStats.noOfMatchedBytes = stats.bytesMatched; winlStats.noOfMatchedPackets = stats.packetsMached; #endif FLOW_UNLOCK(pFlow, &lockState); //2. INIT OVS_MESSAGE pMsg->length = sizeof(OVS_MESSAGE); pMsg->type = OVS_MESSAGE_TARGET_FLOW; pMsg->flags = 0; pMsg->sequence = sequence; pMsg->pid = portId; pMsg->command = command; pMsg->version = 1; pMsg->reserved = 0; pMsg->dpIfIndex = dpIfIndex; //3. OVS_ARGUMENT_GROUP pFlowGroup = KZAlloc(sizeof(OVS_ARGUMENT_GROUP)); if (!pFlowGroup) { return FALSE; } //3.1. Packet Info pPIArg = CreateArgFromPacketInfo(&unmaskedPacketInfo, NULL, OVS_ARGTYPE_FLOW_PI_GROUP); if (!pPIArg) { ok = FALSE; goto Cleanup; } argsDataSize += pPIArg->length; ++curArg; //3.2. Packet Info Mask pMasksArg = CreateArgFromPacketInfo(&maskedPacketInfo, &packetInfoMask, OVS_ARGTYPE_FLOW_MASK_GROUP); if (!pMasksArg) { ok = FALSE; goto Cleanup; } argsDataSize += pMasksArg->length; ++curArg; //3.3. Flow Time Used if (tickCount > 0) { UINT64 usedTimeInMs = 0, curTimeInMs = 0; usedTimeInMs = _TicksToMiliseconds(tickCount); curTimeInMs = _TicksToMiliseconds(KeQueryPerformanceCounter(NULL).QuadPart); pTimeUsedArg = CreateArgument_Alloc(OVS_ARGTYPE_FLOW_TIME_USED, &usedTimeInMs); if (!pTimeUsedArg) { ok = FALSE; goto Cleanup; } argsDataSize += pTimeUsedArg->length; ++curArg; } //3.4. Flow Stats if (winlStats.noOfMatchedPackets > 0) { pFlowStats = CreateArgument_Alloc(OVS_ARGTYPE_FLOW_STATS, &stats); if (!pFlowStats) { ok = FALSE; goto Cleanup; } argsDataSize += pFlowStats->length; ++curArg; } //3.5. Flow Tcp Flags if (tcpFlags) { pTcpFlags = CreateArgument_Alloc(OVS_ARGTYPE_FLOW_TCP_FLAGS, &tcpFlags); if (!pTcpFlags) { ok = FALSE; goto Cleanup; } argsDataSize += pTcpFlags->length; ++curArg; } FLOW_LOCK_READ(pFlow, &lockState); //NOTE: we don't need to use OVS_REFERENCE for pFlow->pActions here //because the actions cannot be deleted while under the lock of pFlow //pFlow is here referenced, so it and its Actions cannot be deleted pActionsArg = _CreateFlowActionsGroup(pFlow->pActions->pActionGroup); FLOW_UNLOCK(pFlow, &lockState); if (!pActionsArg) { return FALSE; } DBGPRINT_ARG(LOG_INFO, pActionsArg, 0, 0); argsDataSize += pActionsArg->length; ++curArg; flowArgCount = curArg; if (!AllocateArgumentsToGroup(flowArgCount, pFlowGroup)) { ok = FALSE; goto Cleanup; } pFlowGroup->args[0] = *pPIArg; pFlowGroup->args[1] = *pMasksArg; curArg = 2; if (pTimeUsedArg) { pFlowGroup->args[curArg] = *pTimeUsedArg; curArg++; } if (pFlowStats) { pFlowGroup->args[curArg] = *pFlowStats; curArg++; } if (pTcpFlags) { pFlowGroup->args[curArg] = *pTcpFlags; curArg++; } pFlowGroup->args[curArg] = *pActionsArg; ++curArg; pFlowGroup->groupSize += argsDataSize; pMsg->pArgGroup = pFlowGroup; Cleanup: VerifyGroup_Size_Recursive(pMsg->pArgGroup); if (ok) { KFree(pPIArg); KFree(pMasksArg); KFree(pTimeUsedArg); KFree(pFlowStats); KFree(pTcpFlags); KFree(pActionsArg); } else { FreeGroupWithArgs(pFlowGroup); DestroyArgument(pPIArg); DestroyArgument(pMasksArg); DestroyArgument(pTimeUsedArg); DestroyArgument(pFlowStats); DestroyArgument(pTcpFlags); DestroyArgument(pActionsArg); } return ok; }