datapath-windows: Rename local variable in Vport.c
[cascardo/ovs.git] / datapath-windows / ovsext / Vport.c
index 69e9513..b69360e 100644 (file)
  */
 
 #include "precomp.h"
+
+#include "Datapath.h"
+#include "Event.h"
+#include "Gre.h"
+#include "IpHelper.h"
 #include "Jhash.h"
+#include "Oid.h"
+#include "Stt.h"
 #include "Switch.h"
-#include "Vport.h"
-#include "Event.h"
 #include "User.h"
+#include "Vport.h"
 #include "Vxlan.h"
-#include "Stt.h"
-#include "IpHelper.h"
-#include "Oid.h"
-#include "Datapath.h"
 
 #ifdef OVS_DBG_MOD
 #undef OVS_DBG_MOD
@@ -94,7 +96,8 @@ static VOID OvsTunnelVportPendingInit(PVOID context,
 static VOID OvsTunnelVportPendingRemove(PVOID context,
                                         NTSTATUS status,
                                         UINT32 *replyLen);
-static VOID AssignNicNameSpecial(POVS_VPORT_ENTRY vport);
+static NTSTATUS GetNICAlias(GUID *netCfgInstanceId,
+                            IF_COUNTED_STRING *portFriendlyName);
 
 /*
  * --------------------------------------------------------------------------
@@ -288,7 +291,15 @@ HvDeletePort(POVS_SWITCH_CONTEXT switchContext,
      * delete will delete the vport.
     */
     if (vport) {
+        OVS_EVENT_ENTRY event;
+
+        event.portNo = vport->portNo;
+        event.ovsType = vport->ovsType;
+        event.upcallPid = vport->upcallPid;
+        RtlCopyMemory(&event.ovsName, &vport->ovsName, sizeof event.ovsName);
+        event.type = OVS_EVENT_LINK_DOWN;
         OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, FALSE);
+        OvsPostEvent(&event);
     } else {
         OVS_LOG_WARN("Vport not present.");
     }
@@ -301,6 +312,8 @@ HvDeletePort(POVS_SWITCH_CONTEXT switchContext,
 /*
  * --------------------------------------------------------------------------
  * Function to process addition of a NIC connection on the Hyper-V switch.
+ * XXX: Posting an event to DPIF is incorrect here. However, it might be useful
+ * to post an event to netdev-windows.c.
  * --------------------------------------------------------------------------
  */
 NDIS_STATUS
@@ -308,10 +321,8 @@ HvCreateNic(POVS_SWITCH_CONTEXT switchContext,
             PNDIS_SWITCH_NIC_PARAMETERS nicParam)
 {
     POVS_VPORT_ENTRY vport;
-    UINT32 portNo = 0;
-    UINT32 event = 0;
     NDIS_STATUS status = NDIS_STATUS_SUCCESS;
-
+    IF_COUNTED_STRING portFriendlyName = {0};
     LOCK_STATE_EX lockState;
 
     VPORT_NIC_ENTER(nicParam);
@@ -326,50 +337,33 @@ HvCreateNic(POVS_SWITCH_CONTEXT switchContext,
         goto done;
     }
 
+    if (OvsIsInternalNIC(nicParam->NicType) ||
+        OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
+        GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName);
+    }
+
     NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
     /*
      * There can be one or more NICs for the external port. We create a vport
      * structure for each such NIC, and each NIC inherits a lot of properties
      * from the parent external port.
      */
-    if (nicParam->NicType == NdisSwitchNicTypeExternal &&
-        nicParam->NicIndex != 0) {
+    if (OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
+        NDIS_SWITCH_PORT_PARAMETERS portParam;
         POVS_VPORT_ENTRY virtExtVport =
             (POVS_VPORT_ENTRY)switchContext->virtualExternalVport;
 
-        vport = OvsFindVportByPortIdAndNicIndex(switchContext,
-                                                nicParam->PortId,
-                                                nicParam->NicIndex);
-        if (vport == NULL) {
-            NDIS_SWITCH_PORT_PARAMETERS portParam;
-            /* Find by interface name */
-            WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 };
-            NET_LUID interfaceLuid = { 0 };
-            size_t len = 0;
-            status = ConvertInterfaceGuidToLuid(&nicParam->NetCfgInstanceId,
-                                                &interfaceLuid);
-            if (status == STATUS_SUCCESS) {
-                status = ConvertInterfaceLuidToAlias(&interfaceLuid,
-                                                     interfaceName,
-                                                     IF_MAX_STRING_SIZE + 1);
-                if (status == STATUS_SUCCESS) {
-                    RtlStringCbLengthW(interfaceName,
-                                       IF_MAX_STRING_SIZE,
-                                       &len);
-                    vport = OvsFindVportByHvNameW(switchContext,
-                                                  interfaceName,
-                                                  len);
-                }
-            }
-
-            OvsCopyPortParamsFromVport(virtExtVport, &portParam);
-            NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
-            status = HvCreatePort(switchContext, &portParam,
-                                  nicParam->NicIndex);
-            NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
-            if (status != NDIS_STATUS_SUCCESS) {
-                goto add_nic_done;
-            }
+        ASSERT(virtExtVport);
+        ASSERT(OvsFindVportByPortIdAndNicIndex(switchContext,
+                                               nicParam->PortId,
+                                               nicParam->NicIndex) == NULL);
+        OvsCopyPortParamsFromVport(virtExtVport, &portParam);
+        NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
+        status = HvCreatePort(switchContext, &portParam,
+                              nicParam->NicIndex);
+        NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
+        if (status != NDIS_STATUS_SUCCESS) {
+            goto add_nic_done;
         }
     }
 
@@ -383,30 +377,14 @@ HvCreateNic(POVS_SWITCH_CONTEXT switchContext,
         goto add_nic_done;
     }
     OvsInitVportWithNicParam(switchContext, vport, nicParam);
-    if (nicParam->NicType == NdisSwitchNicTypeInternal ||
-        (nicParam->NicType == NdisSwitchNicTypeExternal &&
-         nicParam->NicIndex != 0)) {
-        AssignNicNameSpecial(vport);
-    }
-
-    portNo = vport->portNo;
-    if (vport->ovsState == OVS_STATE_CONNECTED) {
-        event = OVS_EVENT_CONNECT | OVS_EVENT_LINK_UP;
-    } else if (vport->ovsState == OVS_STATE_NIC_CREATED) {
-        event = OVS_EVENT_CONNECT;
+    if (OvsIsInternalNIC(nicParam->NicType) ||
+        OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
+        RtlCopyMemory(&vport->portFriendlyName, &portFriendlyName,
+                      sizeof portFriendlyName);
     }
 
 add_nic_done:
     NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
-    if (status == STATUS_SUCCESS &&
-        (vport->portType == NdisSwitchPortTypeInternal ||
-         (vport->portType == NdisSwitchPortTypeExternal &&
-          nicParam->NicIndex != 0))) {
-        AssignNicNameSpecial(vport);
-    }
-    if (portNo != OVS_DPPORT_NUMBER_INVALID && event) {
-        OvsPostEvent(portNo, event);
-    }
 
 done:
     VPORT_NIC_EXIT(nicParam);
@@ -426,7 +404,6 @@ HvConnectNic(POVS_SWITCH_CONTEXT switchContext,
 {
     LOCK_STATE_EX lockState;
     POVS_VPORT_ENTRY vport;
-    UINT32 portNo = 0;
 
     VPORT_NIC_ENTER(nicParam);
 
@@ -452,15 +429,11 @@ HvConnectNic(POVS_SWITCH_CONTEXT switchContext,
 
     vport->ovsState = OVS_STATE_CONNECTED;
     vport->nicState = NdisSwitchNicStateConnected;
-    portNo = vport->portNo;
 
     NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
 
-    /* XXX only if portNo != INVALID or always? */
-    OvsPostEvent(portNo, OVS_EVENT_LINK_UP);
-
     if (nicParam->NicType == NdisSwitchNicTypeInternal) {
-        OvsInternalAdapterUp(portNo, &nicParam->NetCfgInstanceId);
+        OvsInternalAdapterUp(&nicParam->NetCfgInstanceId);
     }
 
 done:
@@ -479,8 +452,10 @@ HvUpdateNic(POVS_SWITCH_CONTEXT switchContext,
 {
     POVS_VPORT_ENTRY vport;
     LOCK_STATE_EX lockState;
-
-    UINT32 status = 0, portNo = 0;
+    UINT32 event = 0;
+    IF_COUNTED_STRING portFriendlyName = {0};
+    BOOLEAN nameChanged = FALSE;
+    BOOLEAN aliasLookup = FALSE;
 
     VPORT_NIC_ENTER(nicParam);
 
@@ -492,6 +467,13 @@ HvUpdateNic(POVS_SWITCH_CONTEXT switchContext,
         goto update_nic_done;
     }
 
+    /* GetNICAlias() must be called outside of a lock. */
+    if (nicParam->NicType == NdisSwitchNicTypeInternal ||
+        OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) {
+        GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName);
+        aliasLookup = TRUE;
+    }
+
     NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
     vport = OvsFindVportByPortIdAndNicIndex(switchContext,
                                             nicParam->PortId,
@@ -506,13 +488,21 @@ HvUpdateNic(POVS_SWITCH_CONTEXT switchContext,
     case NdisSwitchNicTypeInternal:
         RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId,
                       sizeof (GUID));
-        AssignNicNameSpecial(vport);
+        if (aliasLookup) {
+            if (RtlCompareMemory(&vport->portFriendlyName,
+                    &portFriendlyName, vport->portFriendlyName.Length) !=
+                    vport->portFriendlyName.Length) {
+                RtlCopyMemory(&vport->portFriendlyName, &portFriendlyName,
+                    sizeof portFriendlyName);
+                nameChanged = TRUE;
+            }
+        }
         break;
     case NdisSwitchNicTypeSynthetic:
     case NdisSwitchNicTypeEmulated:
         if (!RtlEqualMemory(vport->vmMacAddress, nicParam->VMMacAddress,
                            sizeof (vport->vmMacAddress))) {
-            status |= OVS_EVENT_MAC_CHANGE;
+            event |= OVS_EVENT_MAC_CHANGE;
             RtlCopyMemory(vport->vmMacAddress, nicParam->VMMacAddress,
                           sizeof (vport->vmMacAddress));
         }
@@ -524,26 +514,42 @@ HvUpdateNic(POVS_SWITCH_CONTEXT switchContext,
                         sizeof (vport->permMacAddress))) {
         RtlCopyMemory(vport->permMacAddress, nicParam->PermanentMacAddress,
                       sizeof (vport->permMacAddress));
-        status |= OVS_EVENT_MAC_CHANGE;
+        event |= OVS_EVENT_MAC_CHANGE;
     }
     if (!RtlEqualMemory(vport->currMacAddress, nicParam->CurrentMacAddress,
                         sizeof (vport->currMacAddress))) {
         RtlCopyMemory(vport->currMacAddress, nicParam->CurrentMacAddress,
                       sizeof (vport->currMacAddress));
-        status |= OVS_EVENT_MAC_CHANGE;
+        event |= OVS_EVENT_MAC_CHANGE;
     }
 
     if (vport->mtu != nicParam->MTU) {
         vport->mtu = nicParam->MTU;
-        status |= OVS_EVENT_MTU_CHANGE;
+        event |= OVS_EVENT_MTU_CHANGE;
     }
     vport->numaNodeId = nicParam->NumaNodeId;
-    portNo = vport->portNo;
 
-    NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
-    if (status && portNo) {
-        OvsPostEvent(portNo, status);
+    if (nameChanged) {
+        OVS_EVENT_ENTRY evt;
+        evt.portNo = vport->portNo;
+        evt.ovsType = vport->ovsType;
+        evt.upcallPid = vport->upcallPid;
+        RtlCopyMemory(&evt.ovsName, &vport->ovsName, sizeof evt.ovsName);
+        evt.type = OVS_EVENT_LINK_DOWN;
+        OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE);
+        OvsPostEvent(&evt);
     }
+
+    NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
+
+    /*
+     * XXX: Not sure what kind of event to post here. DPIF is not interested in
+     * changes to MAC address. Netdev-windows might be intrested, though.
+     * That said, if the name chagnes, not clear what kind of event to be
+     * posted. We might have to delete the vport, and have userspace recreate
+     * it.
+     */
+
 update_nic_done:
     VPORT_NIC_EXIT(nicParam);
 }
@@ -558,9 +564,9 @@ HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext,
                 PNDIS_SWITCH_NIC_PARAMETERS nicParam)
 {
     POVS_VPORT_ENTRY vport;
-    UINT32 portNo = 0;
     LOCK_STATE_EX lockState;
     BOOLEAN isInternalPort = FALSE;
+    OVS_EVENT_ENTRY event;
 
     VPORT_NIC_ENTER(nicParam);
 
@@ -585,16 +591,26 @@ HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext,
 
     vport->nicState = NdisSwitchNicStateDisconnected;
     vport->ovsState = OVS_STATE_NIC_CREATED;
-    portNo = vport->portNo;
 
     if (vport->ovsType == OVS_VPORT_TYPE_INTERNAL) {
         isInternalPort = TRUE;
     }
 
-    NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
+    event.portNo = vport->portNo;
+    event.ovsType = vport->ovsType;
+    event.upcallPid = vport->upcallPid;
+    RtlCopyMemory(&event.ovsName, &vport->ovsName, sizeof event.ovsName);
+    event.type = OVS_EVENT_LINK_DOWN;
 
-    /* XXX if portNo != INVALID or always? */
-    OvsPostEvent(portNo, OVS_EVENT_LINK_DOWN);
+    /*
+     * Delete the port from the hash tables accessible to userspace. After this
+     * point, userspace should not be able to access this port.
+     */
+    if (OvsIsRealExternalVport(vport)) {
+        OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE);
+        OvsPostEvent(&event);
+    }
+    NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
 
     if (isInternalPort) {
         OvsInternalAdapterDown();
@@ -615,7 +631,6 @@ HvDeleteNic(POVS_SWITCH_CONTEXT switchContext,
 {
     LOCK_STATE_EX lockState;
     POVS_VPORT_ENTRY vport;
-    UINT32 portNo = 0;
 
     VPORT_NIC_ENTER(nicParam);
     /* Wait for lists to be initialized. */
@@ -640,21 +655,17 @@ HvDeleteNic(POVS_SWITCH_CONTEXT switchContext,
     vport->nicState = NdisSwitchNicStateUnknown;
     vport->ovsState = OVS_STATE_PORT_CREATED;
 
-    portNo = vport->portNo;
-    if (vport->portType == NdisSwitchPortTypeExternal &&
-        vport->nicIndex != 0) {
+    if (OvsIsRealExternalVport(vport)) {
+        /* This vport was created in HvCreateNic(). */
         OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, FALSE);
     }
 
     NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
-    /* XXX if portNo != INVALID or always? */
-    OvsPostEvent(portNo, OVS_EVENT_DISCONNECT);
 
 done:
     VPORT_NIC_EXIT(nicParam);
 }
 
-
 /*
  * OVS Vport related functionality.
  */
@@ -678,9 +689,9 @@ OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,
 
 
 POVS_VPORT_ENTRY
-OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext,
-                            UINT16 dstPort,
-                            OVS_VPORT_TYPE ovsPortType)
+OvsFindTunnelVportByDstPortAndType(POVS_SWITCH_CONTEXT switchContext,
+                                   UINT16 dstPort,
+                                   OVS_VPORT_TYPE ovsPortType)
 {
     POVS_VPORT_ENTRY vport;
     PLIST_ENTRY head, link;
@@ -697,6 +708,59 @@ OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext,
     return NULL;
 }
 
+POVS_VPORT_ENTRY
+OvsFindTunnelVportByDstPortAndNWProto(POVS_SWITCH_CONTEXT switchContext,
+                                      UINT16 dstPort,
+                                      UINT8 nwProto)
+{
+    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 (GetPortFromPriv(vport) == dstPort) {
+            switch (nwProto) {
+            case IPPROTO_UDP:
+                if (vport->ovsType != OVS_VPORT_TYPE_VXLAN) {
+                    continue;
+                }
+                break;
+            case IPPROTO_TCP:
+                if (vport->ovsType != OVS_VPORT_TYPE_STT) {
+                    continue;
+                }
+                break;
+            case IPPROTO_GRE:
+                break;
+            default:
+                continue;
+            }
+            return vport;
+        }
+    }
+    return NULL;
+}
+
+POVS_VPORT_ENTRY
+OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT switchContext,
+                             OVS_VPORT_TYPE ovsPortType)
+{
+    POVS_VPORT_ENTRY vport;
+    PLIST_ENTRY head, link;
+    UINT16 dstPort = 0;
+    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 (vport->ovsType == ovsPortType) {
+            return vport;
+        }
+    }
+    return NULL;
+}
 
 POVS_VPORT_ENTRY
 OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
@@ -901,14 +965,14 @@ OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext,
     UNREFERENCED_PARAMETER(switchContext);
 
     RtlCopyMemory(vport->permMacAddress, nicParam->PermanentMacAddress,
-                  sizeof (nicParam->PermanentMacAddress));
+                  sizeof (vport->permMacAddress));
     RtlCopyMemory(vport->currMacAddress, nicParam->CurrentMacAddress,
-                  sizeof (nicParam->CurrentMacAddress));
+                  sizeof (vport->currMacAddress));
 
     if (nicParam->NicType == NdisSwitchNicTypeSynthetic ||
         nicParam->NicType == NdisSwitchNicTypeEmulated) {
         RtlCopyMemory(vport->vmMacAddress, nicParam->VMMacAddress,
-                      sizeof (nicParam->VMMacAddress));
+                      sizeof (vport->vmMacAddress));
         RtlCopyMemory(&vport->vmName, &nicParam->VmName,
                       sizeof (nicParam->VmName));
     } else {
@@ -920,6 +984,7 @@ OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext,
     vport->mtu = nicParam->MTU;
     vport->nicState = nicParam->NicState;
     vport->nicIndex = nicParam->NicIndex;
+    vport->nicType = nicParam->NicType;
     vport->numaNodeId = nicParam->NumaNodeId;
 
     switch (vport->nicState) {
@@ -979,6 +1044,7 @@ OvsInitTunnelVport(PVOID userContext,
     vport->ovsState = OVS_STATE_PORT_CREATED;
     switch (ovsType) {
     case OVS_VPORT_TYPE_GRE:
+        status = OvsInitGreTunnel(vport);
         break;
     case OVS_VPORT_TYPE_VXLAN:
     {
@@ -1038,18 +1104,16 @@ OvsInitBridgeInternalVport(POVS_VPORT_ENTRY vport)
  * Hyper-V, is overwritten with the interface alias name.
  * --------------------------------------------------------------------------
  */
-static VOID
-AssignNicNameSpecial(POVS_VPORT_ENTRY vport)
+static NTSTATUS
+GetNICAlias(GUID *netCfgInstanceId,
+            IF_COUNTED_STRING *portFriendlyName)
 {
-    NTSTATUS status = STATUS_SUCCESS;
-    WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 };
-    NET_LUID interfaceLuid = { 0 };
-    size_t len = 0;
-
-    ASSERT(vport->portType == NdisSwitchPortTypeExternal ||
-           vport->portType == NdisSwitchPortTypeInternal);
+    NTSTATUS status;
+    WCHAR interfaceName[IF_MAX_STRING_SIZE + 1];
+    NET_LUID interfaceLuid;
+    size_t len;
 
-    status = ConvertInterfaceGuidToLuid(&vport->netCfgInstanceId,
+    status = ConvertInterfaceGuidToLuid(netCfgInstanceId,
                                         &interfaceLuid);
     if (status == STATUS_SUCCESS) {
         /*
@@ -1059,26 +1123,21 @@ AssignNicNameSpecial(POVS_VPORT_ENTRY vport)
         status = ConvertInterfaceLuidToAlias(&interfaceLuid, interfaceName,
                                              IF_MAX_STRING_SIZE + 1);
         if (status == STATUS_SUCCESS) {
-            if (vport->portType == NdisSwitchPortTypeExternal &&
-                vport->nicIndex == 0) {
-                RtlStringCbPrintfW(vport->portFriendlyName.String, IF_MAX_STRING_SIZE,
-                                   L"%s.virtualAdapter", interfaceName);
-            } else {
-                RtlStringCbPrintfW(vport->portFriendlyName.String,
-                                   IF_MAX_STRING_SIZE, L"%s", interfaceName);
-            }
-
-            RtlStringCbLengthW(vport->portFriendlyName.String, IF_MAX_STRING_SIZE,
+            RtlStringCbPrintfW(portFriendlyName->String,
+                               IF_MAX_STRING_SIZE, L"%s", interfaceName);
+            RtlStringCbLengthW(portFriendlyName->String, IF_MAX_STRING_SIZE,
                                &len);
-            vport->portFriendlyName.Length = (USHORT)len;
+            portFriendlyName->Length = (USHORT)len;
         } else {
-            OVS_LOG_INFO("Fail to convert interface LUID to alias, status: %x",
+            OVS_LOG_ERROR("Fail to convert interface LUID to alias, status: %x",
                 status);
         }
     } else {
-        OVS_LOG_INFO("Fail to convert interface GUID to LUID, status: %x",
+        OVS_LOG_ERROR("Fail to convert interface GUID to LUID, status: %x",
                       status);
     }
+
+    return status;
 }
 
 
@@ -1156,6 +1215,7 @@ InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext,
     UINT32 hash;
 
     switch(vport->ovsType) {
+    case OVS_VPORT_TYPE_GRE:
     case OVS_VPORT_TYPE_VXLAN:
     case OVS_VPORT_TYPE_STT:
     {
@@ -1245,6 +1305,7 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext,
         OvsCleanupSttTunnel(vport);
         break;
     case OVS_VPORT_TYPE_GRE:
+        OvsCleanupGreTunnel(vport);
         break;
     case OVS_VPORT_TYPE_NETDEV:
         if (vport->isExternal) {
@@ -1302,7 +1363,8 @@ OvsRemoveAndDeleteVport(PVOID usrParamsContext,
         RemoveEntryList(&vport->portNoLink);
         InitializeListHead(&vport->portNoLink);
         if (OVS_VPORT_TYPE_VXLAN == vport->ovsType ||
-            OVS_VPORT_TYPE_STT == vport->ovsType) {
+            OVS_VPORT_TYPE_STT == vport->ovsType   ||
+            OVS_VPORT_TYPE_GRE == vport->ovsType) {
             RemoveEntryList(&vport->tunnelVportLink);
             InitializeListHead(&vport->tunnelVportLink);
         }
@@ -1612,7 +1674,7 @@ OvsGetExtInfoIoctl(POVS_VPORT_GET vportGet,
                                                  OVS_MAX_PORT_NAME_LENGTH);
         if (status != STATUS_SUCCESS) {
             OVS_LOG_INFO("Fail to convert NIC name.");
-            extInfo->vmUUID[0] = 0;
+            extInfo->name[0] = 0;
         }
 
         status = OvsConvertIfCountedStrToAnsiStr(&vport->vmName,
@@ -1701,8 +1763,9 @@ cleanup:
         POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
             usrParamsCtx->outputBuffer;
 
-        NlBuildErrorMsg(msgIn, msgError, nlError);
-        *replyLen = msgError->nlMsg.nlmsgLen;
+        ASSERT(msgError);
+        NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+        ASSERT(*replyLen != 0);
     }
 
     return STATUS_SUCCESS;
@@ -2060,8 +2123,9 @@ Cleanup:
         POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
             usrParamsCtx->outputBuffer;
 
-        NlBuildErrorMsg(msgIn, msgError, nlError);
-        *replyLen = msgError->nlMsg.nlmsgLen;
+        ASSERT(msgError);
+        NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+        ASSERT(*replyLen != 0);
     }
 
     return STATUS_SUCCESS;
@@ -2191,13 +2255,20 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
 
         if (OvsIsTunnelVportType(portType)) {
             UINT16 transportPortDest = 0;
+            UINT8 nwProto;
+            POVS_VPORT_ENTRY dupVport;
 
             switch (portType) {
+            case OVS_VPORT_TYPE_GRE:
+                nwProto = IPPROTO_GRE;
+                break;
             case OVS_VPORT_TYPE_VXLAN:
                 transportPortDest = VXLAN_UDP_PORT;
+                nwProto = IPPROTO_UDP;
                 break;
             case OVS_VPORT_TYPE_STT:
                 transportPortDest = STT_TCP_PORT;
+                nwProto = IPPROTO_TCP;
                 break;
             default:
                 nlError = NL_ERROR_INVAL;
@@ -2212,6 +2283,22 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
                 }
             }
 
+            /*
+             * We don't allow two tunnel ports on identical N/W protocol and
+             * L4 port number. This is applicable even if the two ports are of
+             * different tunneling types.
+             */
+            dupVport =
+                OvsFindTunnelVportByDstPortAndNWProto(gOvsSwitchContext,
+                                                      transportPortDest,
+                                                      nwProto);
+            if (dupVport) {
+                OVS_LOG_ERROR("Vport for N/W proto and port already exists,"
+                    " type: %u, dst port: %u, name: %s", dupVport->ovsType,
+                    transportPortDest, dupVport->ovsName);
+                goto Cleanup;
+            }
+
             status = OvsInitTunnelVport(usrParamsCtx,
                                         vport,
                                         portType,
@@ -2286,6 +2373,8 @@ OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
                                    gOvsSwitchContext->dpNo);
 
     *replyLen = msgOut->nlMsg.nlmsgLen;
+    OVS_LOG_INFO("Created new vport, name: %s, type: %u", vport->ovsName,
+                 vport->ovsType);
 
 Cleanup:
     NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
@@ -2312,8 +2401,9 @@ Cleanup:
             OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG);
         }
 
-        NlBuildErrorMsg(msgIn, msgError, nlError);
-        *replyLen = msgError->nlMsg.nlmsgLen;
+        ASSERT(msgError);
+        NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+        ASSERT(*replyLen != 0);
     }
 
     return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS;
@@ -2422,8 +2512,9 @@ Cleanup:
         POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
             usrParamsCtx->outputBuffer;
 
-        NlBuildErrorMsg(msgIn, msgError, nlError);
-        *replyLen = msgError->nlMsg.nlmsgLen;
+        ASSERT(msgError);
+        NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+        ASSERT(*replyLen != 0);
     }
 
     return STATUS_SUCCESS;
@@ -2514,8 +2605,9 @@ Cleanup:
         POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
             usrParamsCtx->outputBuffer;
 
-        NlBuildErrorMsg(msgIn, msgError, nlError);
-        *replyLen = msgError->nlMsg.nlmsgLen;
+        ASSERT(msgError);
+        NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+        ASSERT(*replyLen != 0);
     }
 
     return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS;
@@ -2549,9 +2641,9 @@ OvsTunnelVportPendingRemove(PVOID context,
             *replyLen = msgOut->nlMsg.nlmsgLen;
         } else {
             POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)msgOut;
-
-            NlBuildErrorMsg(msgIn, msgError, nlError);
-            *replyLen = msgError->nlMsg.nlmsgLen;
+            ASSERT(msgError);
+            NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+            ASSERT(*replyLen != 0);
         }
     }
 
@@ -2690,12 +2782,13 @@ OvsTunnelVportPendingInit(PVOID context,
     } while (error);
 
     if (error) {
-        POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) msgOut;
+        POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)msgOut;
 
         OvsCleanupVxlanTunnel(NULL, vport, NULL, NULL);
         OvsFreeMemory(vport);
 
-        NlBuildErrorMsg(msgIn, msgError, nlError);
-        *replyLen = msgError->nlMsg.nlmsgLen;
+        ASSERT(msgError);
+        NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
+        ASSERT(*replyLen != 0);
     }
 }