VOID DbgPrintArg(ULONG logLevel, _In_ OVS_ARGUMENT* pArg, int depth, int index) { char* padding = NULL; OVS_CHECK(pArg); OVS_CHECK(depth >= 0); padding = KAlloc(depth + 1); if (!padding) { return; } memset(padding, '\t', depth); padding[depth] = 0; DbgPrintArgType(logLevel, pArg->type, padding, index); DEBUGP_ARG(logLevel, "%ssize: 0x%x\n", padding, pArg->length); if (IsArgTypeGroup(pArg->type)) { ++depth; DbgPrintArgGroup(logLevel, pArg->data, depth); } KFree(padding); }
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; }
VOID DestroyArgumentData(_In_ OVS_ARGUMENT* pArg) { OVS_CHECK(pArg); if (IsArgTypeGroup(pArg->type)) { OVS_ARGUMENT_GROUP* pGroup = pArg->data; DestroyArgumentGroup(pGroup); } else { //free arg data if (pArg->freeData) { KFree(pArg->data); } } }
OVS_ARGUMENT* FindArgumentGroupAsArg(_In_ OVS_ARGUMENT_GROUP* pArgGroup, OVS_ARGTYPE groupType) { OVS_CHECK(pArgGroup); for (UINT32 i = 0; i < pArgGroup->count; ++i) { OVS_ARGUMENT* pArg = pArgGroup->args + i; if (!pArg->isDisabled && IsArgTypeGroup(pArg->type)) { if (pArg->type == (UINT32)groupType) { return pArg; } } } return NULL; }
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; } }
BOOLEAN GetPacketContextFromPIArgs(_In_ const OVS_ARGUMENT_GROUP* pArgGroup, _Inout_ OVS_OFPACKET_INFO* pPacketInfo) { OF_PI_IPV4_TUNNEL* pTunnelInfo = &pPacketInfo->tunnelInfo; OVS_PI_RANGE* pPiRange = NULL; OVS_ARGUMENT* pDatapathInPortArg = NULL; OVS_FLOW_MATCH flowMatch = { 0 }; pPacketInfo->physical.ovsInPort = OVS_INVALID_PORT_NUMBER; pPacketInfo->physical.packetPriority = 0; pPacketInfo->physical.packetMark = 0; RtlZeroMemory(pTunnelInfo, sizeof(OF_PI_IPV4_TUNNEL)); RtlZeroMemory(&flowMatch, sizeof(flowMatch)); flowMatch.pPacketInfo = pPacketInfo; OVS_CHECK(pArgGroup); pPiRange = &flowMatch.piRange; pPacketInfo = flowMatch.pPacketInfo; for (UINT i = 0; i < pArgGroup->count; ++i) { OVS_ARGUMENT* pArg = pArgGroup->args + i; OVS_ARGTYPE argType = pArg->type; switch (argType) { case OVS_ARGTYPE_PI_DATAPATH_HASH: PIFromArg_DatapathHash(pPacketInfo, pPiRange, pArg); break; case OVS_ARGTYPE_PI_DATAPATH_RECIRCULATION_ID: PIFromArg_DatapathRecirculationId(pPacketInfo, pPiRange, pArg); break; case OVS_ARGTYPE_PI_PACKET_PRIORITY: PIFromArg_PacketPriority(pPacketInfo, pPiRange, pArg); break; case OVS_ARGTYPE_PI_PACKET_MARK: PIFromArg_PacketMark(pPacketInfo, pPiRange, pArg); break; case OVS_ARGTYPE_PI_DP_INPUT_PORT: pDatapathInPortArg = pArg; if (!PIFromArg_DatapathInPort(pPacketInfo, pPiRange, pArg, /*is mask*/FALSE)) { return FALSE; } break; case OVS_ARGTYPE_PI_TUNNEL_GROUP: OVS_CHECK(IsArgTypeGroup(pArg->type)); if (!PIFromArg_Tunnel(pArg->data, pPacketInfo, pPiRange, /*is mask*/ FALSE)) { return FALSE; } break; default: //nothing to do here: the rest are non-context / non-metadata keys break; } } if (!pDatapathInPortArg) { PIFromArg_SetDefaultDatapathInPort(pPacketInfo, pPiRange, FALSE); } return TRUE; }
BOOLEAN GetArgumentExpectedSize(OVS_ARGTYPE argumentType, _Inout_ UINT* pSize) { if (IsArgTypeGroup(argumentType)) { *pSize = MAXUINT; return TRUE; } switch (argumentType) { __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_FLOW_STATS, OVS_WINL_FLOW_STATS); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_FLOW_TCP_FLAGS, UINT8); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_FLOW_TIME_USED, UINT64); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_FLOW_CLEAR, 0); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_PACKET_PRIORITY, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_DP_INPUT_PORT, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_ETH_ADDRESS, OVS_PI_ETH_ADDRESS); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_ETH_TYPE, UINT16); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_VLAN_TCI, BE16); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_IPV4, OVS_PI_IPV4); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_IPV6, OVS_PI_IPV6); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_TCP, OVS_PI_TCP); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_TCP_FLAGS, BE16); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_UDP, OVS_PI_UDP); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_SCTP, OVS_PI_SCTP); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_ICMP, OVS_PI_ICMP); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_ICMP6, OVS_PI_ICMP6); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_ARP, OVS_PI_ARP); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_NEIGHBOR_DISCOVERY, OVS_PI_NEIGHBOR_DISCOVERY); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_PACKET_MARK, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_IPV4_TUNNEL, OF_PI_IPV4_TUNNEL); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_MPLS, OVS_PI_MPLS); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_DATAPATH_HASH, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_DATAPATH_RECIRCULATION_ID, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_TUNNEL_ID, BE64); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_TUNNEL_IPV4_SRC, BE32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_TUNNEL_IPV4_DST, BE32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_TUNNEL_TOS, UINT8); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_PI_TUNNEL_TTL, UINT8); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_PI_TUNNEL_DONT_FRAGMENT, 0); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_PI_TUNNEL_CHECKSUM, 0); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_PI_TUNNEL_OAM, 0); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_PI_TUNNEL_GENEVE_OPTIONS, MAXUINT); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_PACKET_BUFFER, MAXUINT); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_PACKET_USERDATA, MAXUINT); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_ACTION_OUTPUT_TO_PORT, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_ACTION_PUSH_VLAN, OVS_ACTION_PUSH_VLAN); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_ACTION_POP_VLAN, 0); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_ACTION_PUSH_MPLS, OVS_ACTION_PUSH_MPLS); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_ACTION_POP_MPLS, BE16); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_ACTION_RECIRCULATION, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_ACTION_HASH, OVS_ACTION_FLOW_HASH); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_ACTION_UPCALL_PORT_ID, UINT32); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_ACTION_UPCALL_DATA, MAXUINT); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_ACTION_SAMPLE_PROBABILITY, UINT32); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_DATAPATH_NAME, MAXUINT); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_DATAPATH_UPCALL_PORT_ID, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_DATAPATH_STATS, OVS_DATAPATH_STATS); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_DATAPATH_MEGAFLOW_STATS, OVS_DATAPATH_MEGAFLOW_STATS); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_DATAPATH_USER_FEATURES, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_OFPORT_NUMBER, UINT32); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_OFPORT_TYPE, UINT32); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_OFPORT_NAME, MAXUINT); __SIZE_CASE_ARGTYPE(OVS_ARGTYPE_OFPORT_UPCALL_PORT_ID, MAXUINT); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_OFPORT_STATS, OVS_OFPORT_STATS); __SIZE_CASE_ARGTYPE_TYPE(OVS_ARGTYPE_OFPORT_OPTION_DESTINATION_PORT, UINT16); default: OVS_CHECK(__UNEXPECTED__); return FALSE; } }
BOOLEAN GetPacketInfoFromArguments(_Inout_ OVS_OFPACKET_INFO* pPacketInfo, _Inout_ OVS_PI_RANGE* pPiRange, _In_ const OVS_ARGUMENT_GROUP* pPIGroup, _In_ BOOLEAN isMask) { BOOLEAN haveIpv4 = FALSE; OVS_ARGUMENT* pVlanTciArg = NULL, *pEthTypeArg = NULL, *pDatapathInPortArg = NULL; OVS_CHECK(pPacketInfo); OVS_CHECK(pPiRange); for (UINT i = 0; i < pPIGroup->count; ++i) { OVS_ARGUMENT* pArg = pPIGroup->args + i; OVS_ARGTYPE argType = pArg->type; switch (argType) { case OVS_ARGTYPE_PI_DATAPATH_HASH: OVS_PI_UPDATE_MAIN_FIELD(pPacketInfo, pPiRange, pArg, UINT32, flowHash); break; case OVS_ARGTYPE_PI_DATAPATH_RECIRCULATION_ID: OVS_PI_UPDATE_MAIN_FIELD(pPacketInfo, pPiRange, pArg, UINT32, recirculationId); break; case OVS_ARGTYPE_PI_PACKET_PRIORITY: OVS_PI_UPDATE_PHYSICAL_FIELD(pPacketInfo, pPiRange, pArg, UINT32, packetPriority); break; case OVS_ARGTYPE_PI_DP_INPUT_PORT: pDatapathInPortArg = pArg; EXPECT(_PIFromArg_DatapathInPort(pPacketInfo, pPiRange, pArg, isMask)); break; case OVS_ARGTYPE_PI_PACKET_MARK: OVS_PI_UPDATE_PHYSICAL_FIELD(pPacketInfo, pPiRange, pArg, UINT32, packetMark); break; case OVS_ARGTYPE_PI_TUNNEL_GROUP: OVS_CHECK(IsArgTypeGroup(pArg->type)); EXPECT(_PIFromArg_Tunnel(pArg->data, pPacketInfo, pPiRange, isMask)); break; case OVS_ARGTYPE_PI_ETH_ADDRESS: { const OVS_PI_ETH_ADDRESS* pEthAddressPI = pArg->data; OVS_PI_UPDATE_ETHINFO_ADDRESS(pPacketInfo, pPiRange, source, pEthAddressPI->source); OVS_PI_UPDATE_ETHINFO_ADDRESS(pPacketInfo, pPiRange, destination, pEthAddressPI->destination); } break; case OVS_ARGTYPE_PI_VLAN_TCI: pVlanTciArg = pArg; { BE16 tci = GET_ARG_DATA(pVlanTciArg, BE16); EXPECT(tci & RtlUshortByteSwap(OVS_VLAN_TAG_PRESENT)); OVS_PI_UPDATE_ETHINFO_FIELD(pPacketInfo, pPiRange, pVlanTciArg, BE16, tci); } break; case OVS_ARGTYPE_PI_ETH_TYPE: pEthTypeArg = pArg; EXPECT(_GetPIFromArg_EthType(pPacketInfo, pPiRange, pArg, isMask)); break; case OVS_ARGTYPE_PI_IPV4: haveIpv4 = TRUE; EXPECT(_GetPIFromArg_Ipv4(pPacketInfo, pPiRange, pArg, isMask)); break; case OVS_ARGTYPE_PI_IPV6: EXPECT(_GetPIFromArg_Ipv6(pPacketInfo, pPiRange, pArg, isMask)); break; case OVS_ARGTYPE_PI_ARP: EXPECT(_GetPIFromArg_Arp(pPacketInfo, pPiRange, pArg, isMask)); break; case OVS_ARGTYPE_PI_MPLS: { const OVS_PI_MPLS* pMplsPI = pArg->data; OVS_PI_UPDATE_NETINFO_FIELD_VALUE(pPacketInfo, pPiRange, mplsTopLabelStackEntry, pMplsPI->mplsLse); } break; case OVS_ARGTYPE_PI_TCP: { const OVS_PI_TCP* pTcpPI = pArg->data; OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, sourcePort, pTcpPI->source); OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, destinationPort, pTcpPI->destination); } break; case OVS_ARGTYPE_PI_TCP_FLAGS: OVS_PI_UPDATE_TPINFO_FIELD(pPacketInfo, pPiRange, pArg, BE16, tcpFlags); break; case OVS_ARGTYPE_PI_UDP: { const OVS_PI_UDP* pUdpPI = pArg->data; OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, sourcePort, pUdpPI->source); OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, destinationPort, pUdpPI->destination); } break; case OVS_ARGTYPE_PI_SCTP: { const OVS_PI_SCTP* pSctpPI = pArg->data; OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, sourcePort, pSctpPI->source); OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, destinationPort, pSctpPI->destination); } break; case OVS_ARGTYPE_PI_ICMP: { const OVS_PI_ICMP* pIcmpPI = pArg->data; OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, sourcePort, RtlUshortByteSwap(pIcmpPI->type)); OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, destinationPort, RtlUshortByteSwap(pIcmpPI->code)); } break; case OVS_ARGTYPE_PI_ICMP6: { const OVS_PI_ICMP6* pIcmpv6PI = pArg->data; OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, sourcePort, RtlUshortByteSwap(pIcmpv6PI->type)); OVS_PI_UPDATE_TPINFO_FIELD_VALUE(pPacketInfo, pPiRange, destinationPort, RtlUshortByteSwap(pIcmpv6PI->code)); } break; case OVS_ARGTYPE_PI_NEIGHBOR_DISCOVERY: _GetPIFromArg_NeighborDiscovery(pPacketInfo, pPiRange, pArg); break; default: DEBUGP(LOG_ERROR, __FUNCTION__ " unexpected key / mask arg type: %u\n", pArg->type); return FALSE; } } if (!pDatapathInPortArg && !isMask) { OVS_PI_UPDATE_PHYSICAL_FIELD_VALUE(pPacketInfo, pPiRange, packetMark, OVS_INVALID_PORT_NUMBER); } if (!pVlanTciArg) { if (!isMask) { //TODO: we should normally set vlan tci to 0xFFFF in this case. //but it used to work with 0 only OVS_PI_UPDATE_ETHINFO_FIELD_VALUE(pPacketInfo, pPiRange, tci, 0); } } if (!pEthTypeArg) { if (isMask) { OVS_PI_UPDATE_ETHINFO_FIELD_VALUE(pPacketInfo, pPiRange, type, OVS_PI_MASK_MATCH_EXACT(UINT16)); } else { OVS_PI_UPDATE_ETHINFO_FIELD_VALUE(pPacketInfo, pPiRange, type, RtlUshortByteSwap(OVS_ETHERTYPE_802_2)); } } return TRUE; }