summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/Vxlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'datapath-windows/ovsext/Vxlan.c')
-rw-r--r--datapath-windows/ovsext/Vxlan.c102
1 files changed, 85 insertions, 17 deletions
diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c
index 8c5718506..9d4266544 100644
--- a/datapath-windows/ovsext/Vxlan.c
+++ b/datapath-windows/ovsext/Vxlan.c
@@ -50,14 +50,57 @@
extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
/*
+ *----------------------------------------------------------------------------
+ * This function verifies if the VXLAN tunnel already exists, in order to
+ * avoid sending a duplicate request to the WFP base filtering engine.
+ *----------------------------------------------------------------------------
+ */
+static BOOLEAN
+OvsIsTunnelFilterCreated(POVS_SWITCH_CONTEXT switchContext,
+ UINT16 udpPortDest)
+{
+ 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 = NULL;
+ POVS_VXLAN_VPORT vxlanPort = NULL;
+ vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);
+ vxlanPort = (POVS_VXLAN_VPORT)vport->priv;
+ if (vxlanPort) {
+ if ((udpPortDest == vxlanPort->dstPort)) {
+ /* The VXLAN tunnel was already created. */
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ *----------------------------------------------------------------------------
+ * This function allocates and initializes the OVS_VXLAN_VPORT. The function
+ * also creates a WFP tunnel filter for the necessary destination port. The
+ * tunnel filter create request is passed to the tunnel filter threads that
+ * will complete the request at a later time when IRQL is lowered to
+ * PASSIVE_LEVEL.
+ *
* udpDestPort: the vxlan is set as payload to a udp frame. If the destination
* port of an udp frame is udpDestPort, we understand it to be vxlan.
+ *----------------------------------------------------------------------------
*/
NTSTATUS
-OvsInitVxlanTunnel(POVS_VPORT_ENTRY vport,
- UINT16 udpDestPort)
+OvsInitVxlanTunnel(PIRP irp,
+ POVS_VPORT_ENTRY vport,
+ UINT16 udpDestPort,
+ PFNTunnelVportPendingOp callback,
+ PVOID tunnelContext)
{
- POVS_VXLAN_VPORT vxlanPort;
+ NTSTATUS status = STATUS_SUCCESS;
+ POVS_VXLAN_VPORT vxlanPort = NULL;
vxlanPort = OvsAllocateMemoryWithTag(sizeof (*vxlanPort),
OVS_VXLAN_POOL_TAG);
@@ -67,28 +110,56 @@ OvsInitVxlanTunnel(POVS_VPORT_ENTRY vport,
RtlZeroMemory(vxlanPort, sizeof(*vxlanPort));
vxlanPort->dstPort = udpDestPort;
- /*
- * since we are installing the WFP filter before the port is created
- * We need to check if it is the same number
- * XXX should be removed later
- */
- ASSERT(vxlanPort->dstPort == VXLAN_UDP_PORT);
vport->priv = (PVOID)vxlanPort;
- return STATUS_SUCCESS;
-}
+ if (!OvsIsTunnelFilterCreated(gOvsSwitchContext, udpDestPort)) {
+ status = OvsTunelFilterCreate(irp,
+ udpDestPort,
+ &vxlanPort->filterID,
+ callback,
+ tunnelContext);
+ } else {
+ status = STATUS_OBJECT_NAME_EXISTS;
+ }
+ return status;
+}
-VOID
-OvsCleanupVxlanTunnel(POVS_VPORT_ENTRY vport)
+/*
+ *----------------------------------------------------------------------------
+ * This function releases the OVS_VXLAN_VPORT. The function also deletes the
+ * WFP tunnel filter previously created. The tunnel filter delete request is
+ * passed to the tunnel filter threads that will complete the request at a
+ * later time when IRQL is lowered to PASSIVE_LEVEL.
+ *----------------------------------------------------------------------------
+ */
+NTSTATUS
+OvsCleanupVxlanTunnel(PIRP irp,
+ POVS_VPORT_ENTRY vport,
+ PFNTunnelVportPendingOp callback,
+ PVOID tunnelContext)
{
+ NTSTATUS status = STATUS_SUCCESS;
+ POVS_VXLAN_VPORT vxlanPort = NULL;
+
if (vport->ovsType != OVS_VPORT_TYPE_VXLAN ||
vport->priv == NULL) {
- return;
+ return STATUS_SUCCESS;
+ }
+
+ vxlanPort = (POVS_VXLAN_VPORT)vport->priv;
+
+ if (vxlanPort->filterID != 0) {
+ status = OvsTunelFilterDelete(irp,
+ vxlanPort->filterID,
+ callback,
+ tunnelContext);
}
OvsFreeMemoryWithTag(vport->priv, OVS_VXLAN_POOL_TAG);
vport->priv = NULL;
+
+ return status;
}
@@ -475,9 +546,6 @@ OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet,
break;
}
- /* XXX Should be tested against the dynamic port # in the VXLAN vport */
- ASSERT(udp->dest == RtlUshortByteSwap(VXLAN_UDP_PORT));
-
VxlanHeader = (VXLANHdr *)OvsGetPacketBytes(packet,
sizeof(*VxlanHeader),
layers.l7Offset,