OVS_ARGUMENT* CreateArgumentStringA_Alloc(OVS_ARGTYPE argType, const char* buffer) { OVS_ARGUMENT* pArg = NULL; VOID* newBuffer = NULL; UINT16 size = 0; pArg = KZAlloc(sizeof(OVS_ARGUMENT)); if (!pArg) { return NULL; } size = (UINT16)strlen(buffer) + 1; newBuffer = KZAlloc(size); if (!newBuffer) { return NULL; } RtlCopyMemory(newBuffer, buffer, size); pArg->type = argType; pArg->isDisabled = FALSE; pArg->isNested = FALSE; pArg->freeData = TRUE; pArg->length = size; pArg->data = newBuffer; return pArg; }
static BOOLEAN _CreateActionsGroupToList(OVS_ARGTYPE groupType, const OVS_ARGUMENT_GROUP* pArgGroup, OVS_ARGUMENT_SLIST_ENTRY** ppArgList) { OVS_ARGUMENT_SLIST_ENTRY* pCurListArg = NULL, *pHeadArg = NULL; OVS_ARGUMENT* pGroupArg = NULL; BOOLEAN ok = TRUE; pHeadArg = KZAlloc(sizeof(OVS_ARGUMENT_SLIST_ENTRY)); if (!pHeadArg) { return FALSE; } pCurListArg = pHeadArg; ok = _CreateActionsArgsToList(pArgGroup, &pCurListArg); if (!ok) { return FALSE; } pGroupArg = CreateGroupArgFromList(groupType, &pHeadArg); if (!pGroupArg) { KFree(pHeadArg); return FALSE; } ok = AppendArgumentToList(pGroupArg, ppArgList); if (!ok) { return FALSE; } return TRUE; }
BOOLEAN CopyArgument(_Out_ OVS_ARGUMENT* pDest, _In_ const OVS_ARGUMENT* pSource) { OVS_CHECK(pDest); OVS_CHECK(pSource); pDest->type = pSource->type; pDest->length = pSource->length; pDest->isDisabled = pSource->isDisabled; pDest->isNested = pSource->isNested; pDest->freeData = pSource->freeData; if (pDest->length) { pDest->data = KZAlloc(pDest->length); if (!pDest->data) { return FALSE; } } if (IsArgTypeGroup(pDest->type)) { if (!CopyArgumentGroup(pDest->data, pSource->data, /*args more*/0)) { DestroyArgumentGroup(pDest->data); } } else { RtlCopyMemory(pDest->data, pSource->data, pDest->length); } return TRUE; }
OVS_ARGUMENT* CreateArgFromPacketInfo(const OVS_OFPACKET_INFO* pPacketInfo, const OVS_OFPACKET_INFO* pMask, UINT16 groupType) { OVS_ARGUMENT_SLIST_ENTRY* pList = NULL; UINT16 count = 0; UINT size = 0; OVS_ARGUMENT* args = NULL, *pResult = NULL; OVS_ARGUMENT_GROUP* pArgGroup = NULL; pList = _CreateArgListFromPacketInfo(pPacketInfo, pMask); if (!pList) { DEBUGP(LOG_ERROR, __FUNCTION__ " _CreateArgListFromPacketInfo failed\n"); return NULL; } args = ArgumentListToArray(pList, &count, &size); if (!args) { DEBUGP(LOG_ERROR, __FUNCTION__ " could not convert arg list to array\n"); DestroyOrFreeArgList(&pList, /*destroy*/ TRUE); return NULL; } OVS_CHECK(size <= MAXUINT16); pArgGroup = KZAlloc(sizeof(OVS_ARGUMENT_GROUP)); if (!pArgGroup) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed allocating arg group\n"); DestroyOrFreeArgList(&pList, /*destroy*/ TRUE); KFree(args); return NULL; } pArgGroup->args = args; pArgGroup->count = count; pArgGroup->groupSize = (UINT16)size; pResult = CreateArgumentFromGroup(groupType, pArgGroup); if (!pResult) { DEBUGP(LOG_ERROR, "CreateArgumentFromGroup failed\n"); DestroyOrFreeArgList(&pList, /*destroy*/ TRUE); KFree(args); return NULL; } DBGPRINT_ARG(LOG_INFO, pResult, 0, 0); DestroyOrFreeArgList(&pList, /*destroy*/ FALSE); VerifyGroup_Size_Recursive(pArgGroup); return pResult; }
OVS_ARGUMENT_GROUP* CreateGroupFromArgArray(OVS_ARGUMENT* argArray, UINT16 countArgs, UINT16 totalSize) { OVS_ARGUMENT_GROUP* pArgGroup = NULL; pArgGroup = KZAlloc(sizeof(OVS_ARGUMENT_GROUP)); EXPECT(pArgGroup); pArgGroup->args = argArray; pArgGroup->count = countArgs; pArgGroup->groupSize = (UINT16)totalSize; return pArgGroup; }
static BOOLEAN _SampleActionToList(const OVS_ARGUMENT_GROUP* pArgGroup, OVS_ARGUMENT_SLIST_ENTRY** ppArgList) { BOOLEAN ok = TRUE; OVS_ARGUMENT_SLIST_ENTRY* pCurListArg = NULL, *pHeadArg = NULL; pHeadArg = KZAlloc(sizeof(OVS_ARGUMENT_SLIST_ENTRY)); if (!pHeadArg) { return FALSE; } pCurListArg = pHeadArg; OVS_ARGUMENT* pGroupArg = NULL; for (UINT i = 0; i < pArgGroup->count; ++i) { const OVS_ARGUMENT* pArg = pArgGroup->args + i; OVS_ARGTYPE argType = pArg->type; switch (argType) { case OVS_ARGTYPE_ACTION_SAMPLE_PROBABILITY: if (!CreateArgInList_WithSize(OVS_ARGTYPE_ACTION_SAMPLE_PROBABILITY, pArg->data, pArg->length, &pCurListArg)) { return FALSE; } break; case OVS_ARGTYPE_ACTION_SAMPLE_ACTIONS_GROUP: _CreateActionsGroupToList(OVS_ARGTYPE_ACTION_SAMPLE_ACTIONS_GROUP, pArg->data, &pCurListArg); break; } } pGroupArg = CreateGroupArgFromList(OVS_ARGTYPE_ACTION_SAMPLE_GROUP, &pHeadArg); if (!pGroupArg) { KFree(pHeadArg); return FALSE; } ok = AppendArgumentToList(pGroupArg, ppArgList); if (!ok) { DestroyArgument(pGroupArg); } return ok; }
BOOLEAN SetArgument_Alloc(_Inout_ OVS_ARGUMENT* pArg, OVS_ARGTYPE argType, const VOID* buffer) { UINT expectedSize = 0; VOID* newBuffer = NULL; OVS_CHECK(pArg); if (!GetArgumentExpectedSize(argType, &expectedSize)) { return FALSE; } if (expectedSize == MAXUINT) { return FALSE; } OVS_CHECK(expectedSize <= MAXUINT16); if (expectedSize) { newBuffer = KZAlloc(expectedSize); if (!newBuffer) { return FALSE; } RtlCopyMemory(newBuffer, buffer, expectedSize); } DEBUGP_ARG(LOG_INFO, "Set argument: %p; type=%u\n", pArg, argType); DBGPRINT_ARGTYPE(LOG_INFO, argType, "", 0); pArg->type = argType; pArg->isDisabled = FALSE; pArg->isNested = FALSE; pArg->freeData = TRUE; pArg->length = (UINT16)expectedSize; pArg->data = (VOID*)newBuffer; return TRUE; }
OVS_ARGUMENT* CreateArgumentStringA(OVS_ARGTYPE argType, const char* buffer) { OVS_ARGUMENT* pArg; pArg = KZAlloc(sizeof(OVS_ARGUMENT)); if (!pArg) { return NULL; } pArg->type = argType; pArg->isDisabled = FALSE; pArg->isNested = FALSE; pArg->freeData = FALSE; pArg->length = (UINT16)strlen(buffer) + 1; pArg->data = (VOID*)buffer; return pArg; }
OVS_ARGUMENT* CreateArgumentFromGroup(OVS_ARGTYPE argType, const OVS_ARGUMENT_GROUP* pData) { OVS_ARGUMENT* pArg = NULL; pArg = KZAlloc(sizeof(OVS_ARGUMENT)); if (!pArg) { return NULL; } pArg->type = argType; pArg->isDisabled = FALSE; pArg->isNested = FALSE; pArg->freeData = TRUE; pArg->length = pData->groupSize + OVS_ARGUMENT_GROUP_HEADER_SIZE; pArg->data = (VOID*)pData; return pArg; }
OVS_ARGUMENT* CreateArgumentWithSize(OVS_ARGTYPE argType, const VOID* buffer, ULONG size) { OVS_ARGUMENT* pArg = NULL; UINT expectedSize = 0; OVS_CHECK(size > 0); OVS_CHECK(size <= MAXUINT); pArg = KZAlloc(sizeof(OVS_ARGUMENT)); if (!pArg) { return NULL; } DEBUGP_ARG(LOG_INFO, "Created argument: %p; type=%u\n", pArg, argType); DBGPRINT_ARGTYPE(LOG_INFO, argType, "", 0); pArg->type = argType; pArg->isDisabled = FALSE; pArg->isNested = FALSE; pArg->freeData = FALSE; if (!GetArgumentExpectedSize(argType, &expectedSize)) { return NULL; } if (expectedSize != MAXUINT) { DEBUGP_ARG(LOG_ERROR, "Create arg with size should only be used with var-sized args!"); return NULL; } pArg->length = (UINT16)size; pArg->data = (VOID*)buffer; return pArg; }
static OVS_ARGUMENT* _CreateSetActionArg(const OVS_ARGUMENT* pArgument) { const OVS_ARGUMENT_GROUP* pGroupArg = NULL; OVS_ARGTYPE argType = OVS_ARGTYPE_INVALID; OVS_CHECK(IsArgTypeGroup(pArgument->type)); pGroupArg = pArgument->data; OVS_CHECK(pGroupArg->count == 1); pArgument = pGroupArg->args; argType = pArgument->type; switch (argType) { case OVS_ARGTYPE_PI_IPV4_TUNNEL: { OVS_ARGUMENT* pArg = _CreateIpv4TunnelGroup(pArgument->data); return pArg; } break; default: { OVS_ARGUMENT* pPacketInfoArg = KZAlloc(sizeof(OVS_ARGUMENT)); if (!pPacketInfoArg) { DEBUGP(LOG_ERROR, "could not alloc key arg\n"); return NULL; } CopyArgument(pPacketInfoArg, pArgument); return pPacketInfoArg; } break; } }
OVS_ARGUMENT* CreateArgument_Alloc(OVS_ARGTYPE argType, const VOID* buffer) { UINT expectedSize = 0; VOID* newBuffer = NULL; OVS_ARGUMENT* pArg = NULL; if (!GetArgumentExpectedSize(argType, &expectedSize)) { return NULL; } if (expectedSize == MAXUINT) { return NULL; } if (expectedSize) { newBuffer = KZAlloc(expectedSize); if (!newBuffer) { return NULL; } RtlCopyMemory(newBuffer, buffer, expectedSize); } pArg = CreateArgument(argType, newBuffer); if (pArg) { pArg->isNested = FALSE; pArg->freeData = TRUE; } return pArg; }
OVS_ARGUMENT* CreateArgument(OVS_ARGTYPE argType, const VOID* buffer) { OVS_ARGUMENT* pArg = NULL; UINT expectedSize = 0; pArg = KZAlloc(sizeof(OVS_ARGUMENT)); if (!pArg) { return NULL; } DEBUGP_ARG(LOG_INFO, "Created argument: %p; type=%u\n", pArg, argType); DBGPRINT_ARGTYPE(LOG_INFO, argType, "", 0); pArg->type = argType; pArg->isDisabled = FALSE; pArg->isNested = FALSE; pArg->freeData = FALSE; if (!GetArgumentExpectedSize(argType, &expectedSize)) { return NULL; } if (expectedSize == MAXUINT) { return NULL; } OVS_CHECK(expectedSize <= MAXUINT16); pArg->length = (UINT16)expectedSize; pArg->data = (VOID*)buffer; return pArg; }
static BOOLEAN _CreateActionsArgsToList(const OVS_ARGUMENT_GROUP* pArgGroup, OVS_ARGUMENT_SLIST_ENTRY** ppArgList) { BOOLEAN ok = TRUE; for (UINT i = 0; i < pArgGroup->count; ++i) { const OVS_ARGUMENT* pArg = pArgGroup->args + i; OVS_ARGTYPE argType = pArg->type; switch (argType) { case OVS_ARGTYPE_ACTION_SETINFO_GROUP: { OVS_ARGUMENT_GROUP* pSetGroup = NULL; OVS_ARGUMENT* pPacketInfoArg = NULL, *pSetArg = NULL; pPacketInfoArg = _CreateSetActionArg(pArg); if (!pPacketInfoArg) { return FALSE; } pSetGroup = KZAlloc(sizeof(OVS_ARGUMENT_GROUP)); if (!pSetGroup) { return FALSE; } pSetGroup->args = pPacketInfoArg; pSetGroup->count = 1; pSetGroup->groupSize = pPacketInfoArg->length + OVS_ARGUMENT_HEADER_SIZE; pSetArg = KZAlloc(sizeof(OVS_ARGUMENT)); pSetArg->data = pSetGroup; pSetArg->type = OVS_ARGTYPE_ACTION_SETINFO_GROUP; pSetArg->length = pSetGroup->groupSize + OVS_ARGUMENT_GROUP_HEADER_SIZE; if (!AppendArgumentToList(pSetArg, ppArgList)) { return FALSE; } } break; case OVS_ARGTYPE_ACTION_SAMPLE_GROUP: ok = _SampleActionToList(pArg->data, ppArgList); if (!ok) { return FALSE; } break; case OVS_ARGTYPE_ACTION_UPCALL_GROUP: { OVS_ARGUMENT_GROUP* pUpcallGroup = NULL; OVS_ARGUMENT* pUpcallArg = NULL; BOOLEAN ok = TRUE; pUpcallGroup = KZAlloc(sizeof(OVS_ARGUMENT_GROUP)); if (NULL == pUpcallGroup) { return FALSE; } ok = CopyArgumentGroup(pUpcallGroup, pArg->data, /*actionsToAdd*/0); if (!ok) { DestroyArgumentGroup(pUpcallGroup); return FALSE; } pUpcallArg = CreateArgumentFromGroup(argType, pUpcallGroup); if (!AppendArgumentToList(pUpcallArg, ppArgList)) { return FALSE; } } break; default: { OVS_ARGUMENT* pDestArg = KAlloc(sizeof(OVS_ARGUMENT)); if (!pDestArg) { return FALSE; } CopyArgument(pDestArg, pArg); if (!AppendArgumentToList(pDestArg, ppArgList)) { return FALSE; } } break; } } return TRUE; }
static OVS_ARGUMENT* _CreateIpv4TunnelGroup(const OF_PI_IPV4_TUNNEL* pTunnelInfo) { OVS_ARGUMENT_GROUP* pTunnelGroup = NULL; OVS_ARGUMENT_SLIST_ENTRY* pArgListCur = NULL; OVS_ARGUMENT_SLIST_ENTRY* pArgHead = NULL; OVS_ARGUMENT* argArray = NULL, *pTunnelArg = NULL; UINT16 countArgs = 0; UINT totalSize = 0; BOOLEAN ok = TRUE; pArgListCur = KZAlloc(sizeof(OVS_ARGUMENT_SLIST_ENTRY)); if (!pArgListCur) { return FALSE; } pArgHead = pArgListCur; pArgHead->pArg = NULL; if (pTunnelInfo->tunnelFlags & OVS_TUNNEL_FLAG_KEY) { if (!CreateArgInList(OVS_ARGTYPE_PI_TUNNEL_ID, &pTunnelInfo->tunnelId, &pArgListCur)) { ok = FALSE; goto Cleanup; } } if (pTunnelInfo->tunnelFlags & OVS_TUNNEL_FLAG_DONT_FRAGMENT) { if (!CreateArgInList(OVS_ARGTYPE_PI_TUNNEL_DONT_FRAGMENT, NULL, &pArgListCur)) { ok = FALSE; goto Cleanup; } } if (pTunnelInfo->tunnelFlags & OVS_TUNNEL_FLAG_CHECKSUM) { if (!CreateArgInList(OVS_ARGTYPE_PI_TUNNEL_CHECKSUM, NULL, &pArgListCur)) { ok = FALSE; goto Cleanup; } } //ipv4 addr 0.0.0.0 is invalid if (pTunnelInfo->ipv4Source) { if (!CreateArgInList(OVS_ARGTYPE_PI_TUNNEL_IPV4_SRC, &pTunnelInfo->ipv4Source, &pArgListCur)) { ok = FALSE; goto Cleanup; } } //ipv4 addr 0.0.0.0 is invalid if (pTunnelInfo->ipv4Destination) { if (!CreateArgInList(OVS_ARGTYPE_PI_TUNNEL_IPV4_DST, &pTunnelInfo->ipv4Destination, &pArgListCur)) { ok = FALSE; goto Cleanup; } } //ipv4 TOS 0x00 is invalid! if (pTunnelInfo->ipv4TypeOfService) { if (!CreateArgInList(OVS_ARGTYPE_PI_TUNNEL_TOS, &pTunnelInfo->ipv4TypeOfService, &pArgListCur)) { ok = FALSE; goto Cleanup; } } if (!CreateArgInList(OVS_ARGTYPE_PI_TUNNEL_TTL, &pTunnelInfo->ipv4TimeToLive, &pArgListCur)) { ok = FALSE; goto Cleanup; } //OVS_ARGUMENT-s argArray = ArgumentListToArray(pArgHead, &countArgs, &totalSize); //OVS_ARGUMENT_GROUP pTunnelGroup = KZAlloc(sizeof(OVS_ARGUMENT_GROUP)); if (!pTunnelGroup) { return NULL; } pTunnelGroup->args = argArray; pTunnelGroup->count = countArgs; pTunnelGroup->groupSize = (UINT16)totalSize; //parent OVS_ARGUMENT pTunnelArg = KAlloc(sizeof(OVS_ARGUMENT)); if (!pTunnelArg) { ok = FALSE; goto Cleanup; } pTunnelArg->data = pTunnelGroup; pTunnelArg->length = pTunnelGroup->groupSize + OVS_ARGUMENT_GROUP_HEADER_SIZE; pTunnelArg->type = OVS_ARGTYPE_PI_TUNNEL_GROUP; VerifyGroup_Size_Recursive(pTunnelArg->data); Cleanup: if (ok) { DestroyOrFreeArgList(&pArgHead, /*destroy*/ FALSE); } else { DestroyOrFreeArgList(&pArgHead, /*destroy*/ TRUE); KFree(argArray); KFree(pTunnelGroup); KFree(pTunnelArg); return NULL; } return pTunnelArg; }
static OVS_ARGUMENT* _CreateFlowActionsGroup(const OVS_ARGUMENT_GROUP* pActions) { OVS_ARGUMENT_GROUP* pActionsGroup = NULL; OVS_ARGUMENT* argArray = NULL, *pActionsArg = NULL; OVS_ARGUMENT_SLIST_ENTRY* pArgListCur = NULL; OVS_ARGUMENT_SLIST_ENTRY* pArgHead = NULL; BOOLEAN ok = TRUE; UINT16 countArgs = 0; UINT totalSize = 0; pArgListCur = KZAlloc(sizeof(OVS_ARGUMENT_SLIST_ENTRY)); if (!pArgListCur) { return FALSE; } pArgHead = pArgListCur; pArgHead->pArg = NULL; pArgHead->pNext = NULL; if (pActions->count > 0) { ok = _CreateActionsArgsToList(pActions, &pArgListCur); if (!ok) { goto Cleanup; } argArray = ArgumentListToArray(pArgHead, &countArgs, &totalSize); if (!argArray) { ok = FALSE; goto Cleanup; } } pActionsGroup = KZAlloc(sizeof(OVS_ARGUMENT_GROUP)); if (!pActionsGroup) { ok = FALSE; goto Cleanup; } pActionsGroup->args = argArray; pActionsGroup->count = countArgs; pActionsGroup->groupSize = (UINT16)totalSize; pActionsArg = KZAlloc(sizeof(OVS_ARGUMENT)); if (!pActionsArg) { ok = FALSE; goto Cleanup; } pActionsArg->data = pActionsGroup; pActionsArg->length = pActionsGroup->groupSize + OVS_ARGUMENT_GROUP_HEADER_SIZE; pActionsArg->type = OVS_ARGTYPE_FLOW_ACTIONS_GROUP; Cleanup: if (ok) { DestroyOrFreeArgList(&pArgHead, /*destroy*/ FALSE); } else { DestroyOrFreeArgList(&pArgHead, /*destroy*/ TRUE); KFree(argArray); KFree(pActionsGroup); KFree(pActionsArg); return NULL; } return pActionsArg; }
//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; }
static OVS_ARGUMENT* _CreateEncapsulationArg(const OVS_OFPACKET_INFO* pPacketInfo, const OVS_OFPACKET_INFO* pMask) { OVS_ARGUMENT_GROUP* pEncapsGroup = NULL; OVS_ARGUMENT* argArray = NULL, *pEncapsArg = NULL; OVS_ARGUMENT_SLIST_ENTRY* pArgListCur = NULL; OVS_ARGUMENT_SLIST_ENTRY* pArgHead = NULL; BOOLEAN ok = TRUE; UINT16 countArgs = 0; UINT totalSize = 0; BE16 ethType = 0; ethType = (pMask ? pMask->ethInfo.type : pPacketInfo->ethInfo.type); pEncapsGroup = KZAlloc(sizeof(OVS_ARGUMENT_GROUP)); if (!pEncapsGroup) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed allocating group\n"); return FALSE; } pEncapsArg = KZAlloc(sizeof(OVS_ARGUMENT)); if (!pEncapsArg) { ok = FALSE; DEBUGP(LOG_ERROR, __FUNCTION__ " failed allocating encaps arg\n"); goto Cleanup; } pArgListCur = KZAlloc(sizeof(OVS_ARGUMENT_SLIST_ENTRY)); if (!pArgListCur) { ok = FALSE; DEBUGP(LOG_ERROR, __FUNCTION__ " failed allocating arg list item\n"); goto Cleanup; } pArgHead = pArgListCur; pArgHead->pArg = NULL; //NOTE: 802.2 frames are represented in ovs messages as: //packet info eth type = missing (=> filled by us) //mask eth info = exact match if (pPacketInfo->ethInfo.type == RtlUshortByteSwap(OVS_ETHERTYPE_802_2) && pMask && pMask->ethInfo.type) { if (pMask->ethInfo.type != OVS_PI_MASK_MATCH_EXACT(BE16)) { DEBUGP(LOG_ERROR, __FUNCTION__ " expected 802.2 mask to be exact!\n"); ok = FALSE; goto Cleanup; } } if (!CreateArgInList(OVS_ARGTYPE_PI_ETH_TYPE, ðType, &pArgListCur)) //UINT16 { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending enc eth type\n"); ok = FALSE; goto Cleanup; } if (!_CreateArgsFromLayer3And4InList(pPacketInfo, pMask, &pArgListCur)) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending layer 4 / 4 to list\n"); ok = FALSE; goto Cleanup; } argArray = ArgumentListToArray(pArgHead, &countArgs, &totalSize); if (!argArray) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed converting list to array\n"); ok = FALSE; goto Cleanup; } pEncapsGroup->args = argArray; pEncapsGroup->count = countArgs; pEncapsGroup->groupSize = (UINT16)totalSize; pEncapsArg->data = pEncapsGroup; pEncapsArg->length = (UINT16)totalSize + OVS_ARGUMENT_GROUP_HEADER_SIZE; pEncapsArg->type = OVS_ARGTYPE_PI_ENCAP_GROUP; VerifyGroup_Size_Recursive(pEncapsArg->data); Cleanup: if (ok) { DestroyOrFreeArgList(&pArgHead, /*destroy*/ FALSE); return pEncapsArg; } DestroyOrFreeArgList(&pArgHead, /*destroy*/ TRUE); KFree(argArray); KFree(pEncapsGroup); KFree(pEncapsArg); return NULL; }
static OVS_ARGUMENT_SLIST_ENTRY* _CreateArgListFromPacketInfo(const OVS_OFPACKET_INFO* pPacketInfo, const OVS_OFPACKET_INFO* pMask) { OVS_ARGUMENT_SLIST_ENTRY* pArgListCur = NULL; OVS_ARGUMENT_SLIST_ENTRY* pArgHead = NULL; BOOLEAN ok = TRUE; BOOLEAN encapsulated = FALSE; UINT32 packetPriority = 0, packetMark = 0, datapathHash = 0, recircId = 0; pArgListCur = KZAlloc(sizeof(OVS_ARGUMENT_SLIST_ENTRY)); if (!pArgListCur) { return NULL; } pArgHead = pArgListCur; pArgHead->pArg = NULL; packetPriority = (pMask ? pMask->physical.packetPriority : pPacketInfo->physical.packetPriority); packetMark = (pMask ? pMask->physical.packetMark : pPacketInfo->physical.packetMark); datapathHash = (pMask ? pMask->flowHash : pPacketInfo->flowHash); recircId = (pMask ? pMask->recirculationId : pPacketInfo->recirculationId); if (!CreateArgInList(OVS_ARGTYPE_PI_DATAPATH_HASH, &datapathHash, &pArgListCur)) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending datapath hash\n"); return NULL; } if (!CreateArgInList(OVS_ARGTYPE_PI_DATAPATH_RECIRCULATION_ID, &recircId, &pArgListCur)) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending datapath recirculation id\n"); return NULL; } if (!CreateArgInList(OVS_ARGTYPE_PI_PACKET_PRIORITY, &packetPriority, &pArgListCur)) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending packet priority\n"); return NULL; } if (!CreateArgInList(OVS_ARGTYPE_PI_PACKET_MARK, &packetMark, &pArgListCur)) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending packet mark\n"); ok = FALSE; goto Cleanup; } //TUNNEL if (!_CreateTunnelArgInList(pPacketInfo, pMask, &pArgListCur)) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending tunnel key\n"); ok = FALSE; goto Cleanup; } //INPUT OF PORT if (!_CreateInPortArgInList(pPacketInfo, pMask, &pArgListCur)) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending in port\n"); ok = FALSE; goto Cleanup; } if (!_CreateEthernetArgsInList(pPacketInfo, pMask, &pArgListCur, &encapsulated)) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending eth args\n"); ok = FALSE; goto Cleanup; } if (encapsulated) { goto Cleanup; } if (!_CreateArgsFromLayer3And4InList(pPacketInfo, pMask, &pArgListCur)) { DEBUGP(LOG_ERROR, __FUNCTION__ " failed appending layer3 / 4 args\n"); ok = FALSE; goto Cleanup; } Cleanup: if (!ok) { DestroyOrFreeArgList(&pArgHead, /*destroy*/ TRUE); return NULL; } return pArgHead; }