}
/*
+ * XXX: When we search for the tunnelVport we also need to specify the
+ * tunnelling protocol or the L4 protocol as key as well, because there are
+ * different protocols that can use the same destination port.
* --------------------------------------------------------------------------
* OvsDetectTunnelRxPkt --
* Utility function for an RX packet to detect its tunnel type.
* packets only if they are at least VXLAN header size.
*/
if (!flowKey->ipKey.nwFrag &&
- flowKey->ipKey.nwProto == IPPROTO_UDP &&
- flowKey->ipKey.l4.tpDst == VXLAN_UDP_PORT_NBO) {
- tunnelVport = ovsFwdCtx->switchContext->vxlanVport;
- ovsActionStats.rxVxlan++;
+ flowKey->ipKey.nwProto == IPPROTO_UDP) {
+ UINT16 dstPort = htons(flowKey->ipKey.l4.tpDst);
+ tunnelVport = OvsFindTunnelVportByDstPort(ovsFwdCtx->switchContext,
+ dstPort);
}
// We might get tunnel packets even before the tunnel gets initialized.
if (tunnelVport) {
ASSERT(ovsFwdCtx->tunnelRxNic == NULL);
ovsFwdCtx->tunnelRxNic = tunnelVport;
+ ovsActionStats.rxVxlan++;
return TRUE;
}
status = OvsTunnelAttrToIPv4TunnelKey((PNL_ATTR)a, &tunKey);
ASSERT(status == NDIS_STATUS_SUCCESS);
tunKey.flow_hash = (uint16)(hash ? *hash : OvsHashFlow(key));
+ tunKey.dst_port = key->ipKey.l4.tpDst;
RtlCopyMemory(&ovsFwdCtx->tunKey, &tunKey, sizeof ovsFwdCtx->tunKey);
break;
sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
switchContext->pidHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
sizeof(LIST_ENTRY) * OVS_MAX_PID_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
+ switchContext->tunnelVportsArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
+ sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
status = OvsAllocateFlowTable(&switchContext->datapath, switchContext);
if (status == NDIS_STATUS_SUCCESS) {
switchContext->portNoHashArray == NULL ||
switchContext->ovsPortNameHashArray == NULL ||
switchContext->portIdHashArray== NULL ||
- switchContext->pidHashArray == NULL) {
+ switchContext->pidHashArray == NULL ||
+ switchContext->tunnelVportsArray == NULL) {
if (switchContext->dispatchLock) {
NdisFreeRWLock(switchContext->dispatchLock);
}
OVS_SWITCH_POOL_TAG);
}
+ if (switchContext->tunnelVportsArray) {
+ OvsFreeMemory(switchContext->tunnelVportsArray);
+ }
+
OvsDeleteFlowTable(&switchContext->datapath);
OvsCleanupBufferPool(switchContext);
for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
InitializeListHead(&switchContext->ovsPortNameHashArray[i]);
- }
- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
InitializeListHead(&switchContext->portIdHashArray[i]);
- }
- for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
InitializeListHead(&switchContext->portNoHashArray[i]);
+ InitializeListHead(&switchContext->tunnelVportsArray[i]);
}
for (i = 0; i < OVS_MAX_PID_ARRAY_SIZE; i++) {
OvsFreeMemoryWithTag(switchContext->pidHashArray,
OVS_SWITCH_POOL_TAG);
switchContext->pidHashArray = NULL;
+ OvsFreeMemory(switchContext->tunnelVportsArray);
+ switchContext->tunnelVportsArray = NULL;
OvsDeleteFlowTable(&switchContext->datapath);
OvsCleanupBufferPool(switchContext);
POVS_VPORT_ENTRY virtualExternalVport; // the virtual adapter vport
POVS_VPORT_ENTRY internalVport;
- POVS_VPORT_ENTRY vxlanVport;
-
/*
* 'portIdHashArray' ONLY contains ports that exist on the Hyper-V switch,
* namely: VIF (vNIC) ports, external port and Hyper-V internal port.
* exist on the Hyper-V switch, and 'numNonHvVports' counts such ports in
* 'portNoHashArray'.
*
+ * 'tunnelVportsArray' contains tunnel ports that are added from OVS
+ * userspace. Currently only VXLAN tunnels are added in this list.
+ *
* 'ovsPortNameHashArray' contains the same entries as 'portNoHashArray' but
* hashed on a different key.
*/
PLIST_ENTRY portIdHashArray; // based on Hyper-V portId
PLIST_ENTRY portNoHashArray; // based on ovs port number
+ PLIST_ENTRY tunnelVportsArray; // based on ovs dst port number
PLIST_ENTRY ovsPortNameHashArray; // based on ovsName
PLIST_ENTRY pidHashArray; // based on packet pids
NDIS_SPIN_LOCK pidHashLock; // Lock for pidHash table
SendFlags |= NDIS_SEND_FLAGS_DISPATCH_LEVEL;
- vport = gOvsSwitchContext->vxlanVport;
+ vport = OvsFindTunnelVportByDstPort(gOvsSwitchContext,
+ htons(tunnelKey.dst_port));
if (vport == NULL){
status = STATUS_UNSUCCESSFUL;
}
+POVS_VPORT_ENTRY
+OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext,
+ UINT16 dstPort)
+{
+ POVS_VPORT_ENTRY vport;
+ PLIST_ENTRY head, link;
+ UINT32 hash = OvsJhashBytes((const VOID *)&dstPort, sizeof(dstPort),
+ OVS_HASH_BASIS);
+ head = &(switchContext->tunnelVportsArray[hash & OVS_VPORT_MASK]);
+ LIST_FORALL(head, link) {
+ vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, tunnelVportLink);
+ if (((POVS_VXLAN_VPORT)vport->priv)->dstPort == dstPort) {
+ return vport;
+ }
+ }
+ return NULL;
+}
+
+
POVS_VPORT_ENTRY
OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
PSTR name)
* --------------------------------------------------------------------------
* Functionality common to any port added from OVS userspace.
*
- * Inserts the port into 'portIdHashArray', 'ovsPortNameHashArray' and caches
- * the pointer in the 'switchContext' if needed.
+ * Inserts the port into 'portNoHashArray', 'ovsPortNameHashArray' and in
+ * 'tunnelVportsArray' if appropriate.
* --------------------------------------------------------------------------
*/
NDIS_STATUS
switch(vport->ovsType) {
case OVS_VPORT_TYPE_VXLAN:
- switchContext->vxlanVport = vport;
+ {
+ POVS_VXLAN_VPORT vxlanVport = (POVS_VXLAN_VPORT)vport->priv;
+ hash = OvsJhashBytes(&vxlanVport->dstPort,
+ sizeof(vxlanVport->dstPort),
+ OVS_HASH_BASIS);
+ InsertHeadList(
+ &gOvsSwitchContext->tunnelVportsArray[hash & OVS_VPORT_MASK],
+ &vport->tunnelVportLink);
switchContext->numNonHvVports++;
break;
+ }
case OVS_VPORT_TYPE_INTERNAL:
if (vport->isBridgeInternal) {
switchContext->numNonHvVports++;
InitializeListHead(&vport->ovsNameLink);
RemoveEntryList(&vport->portNoLink);
InitializeListHead(&vport->portNoLink);
+ if (OVS_VPORT_TYPE_VXLAN == vport->ovsType) {
+ RemoveEntryList(&vport->tunnelVportLink);
+ InitializeListHead(&vport->tunnelVportLink);
+ }
+
deletedOnOvs = TRUE;
}
vport,
OvsTunnelVportPendingUninit,
tunnelContext);
-
- switchContext->vxlanVport = NULL;
break;
}
case OVS_VPORT_TYPE_GRE:
OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE);
}
}
+
/*
* Remove 'virtualExternalVport' as well. This port is not part of the
* 'portIdHashArray'.
(POVS_VPORT_ENTRY)switchContext->virtualExternalVport, TRUE, TRUE);
}
+
for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) {
PLIST_ENTRY head, link, next;
-
head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);
LIST_FORALL_SAFE(head, link, next) {
POVS_VPORT_ENTRY vport;
ASSERT(switchContext->virtualExternalVport == NULL);
ASSERT(switchContext->internalVport == NULL);
- ASSERT(switchContext->vxlanVport == NULL);
}
LIST_ENTRY ovsNameLink;
LIST_ENTRY portIdLink;
LIST_ENTRY portNoLink;
+ LIST_ENTRY tunnelVportLink;
OVS_VPORT_STATE ovsState;
OVS_VPORT_TYPE ovsType;
struct _OVS_SWITCH_CONTEXT;
-POVS_VPORT_ENTRY
-OvsFindVportByPortNo(struct _OVS_SWITCH_CONTEXT *switchContext,
- UINT32 portNo);
-
+POVS_VPORT_ENTRY OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,
+ UINT32 portNo);
/* "name" is null-terminated */
POVS_VPORT_ENTRY OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
PSTR name);
POVS_VPORT_ENTRY OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,
NDIS_SWITCH_PORT_ID portId,
NDIS_SWITCH_NIC_INDEX index);
+POVS_VPORT_ENTRY OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext,
+ UINT16 dstPort);
NDIS_STATUS OvsAddConfiguredSwitchPorts(struct _OVS_SWITCH_CONTEXT *switchContext);
NDIS_STATUS OvsInitConfiguredSwitchNics(struct _OVS_SWITCH_CONTEXT *switchContext);
ovsType == OVS_VPORT_TYPE_GRE64;
}
-static __inline POVS_VPORT_ENTRY
-OvsGetTunnelVport(POVS_SWITCH_CONTEXT switchContext,
- OVS_VPORT_TYPE ovsType)
-{
- switch(ovsType) {
- case OVS_VPORT_TYPE_VXLAN:
- return switchContext->vxlanVport;
- default:
- return NULL;
- }
-}
-
static __inline BOOLEAN
OvsIsInternalVportType(OVS_VPORT_TYPE ovsType)
{
/* UDP header */
udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr);
udpHdr->source = htons(tunKey->flow_hash | 32768);
- udpHdr->dest = VXLAN_UDP_PORT_NBO;
+ udpHdr->dest = htons(tunKey->dst_port);
udpHdr->len = htons(NET_BUFFER_DATA_LENGTH(curNb) - headRoom +
sizeof *udpHdr + sizeof *vxlanHdr);
udpHdr->check = 0;
#include "NetProto.h"
typedef struct _OVS_VXLAN_VPORT {
- UINT32 dstPort;
+ UINT16 dstPort;
UINT64 inPkts;
UINT64 outPkts;
UINT64 slowInPkts;