hi Alin,
The change looks good overall, but for the comments I had. I am ok with not 
addressing some of the comments since I have not looked at the future patches 
yet.

There are some  concerns I have about double freeing an external port. When we 
add an external port, the sequence is something like this (as I observed at 
least):
OvsCreatePort(): nicIndex = 0
OvsCreateNic():  nicIndex = 0
OvsCreateNic():  nicIndex = 1
OvsConnectNic(): nicIndex = 1

I don't know if the new code handles this. The previous code handed this in 
kind of a complicated way by checking for nicIndex in OvsInitVportCommon() and 
OvsCreateNic().

This patch as such is fine. If there are bugs, we can address them in future 
patches.

Acked-by: Nithin Raju <nit...@vmware.com>


On Sep 30, 2014, at 7:54 AM, Samuel Ghinet <sghi...@cloudbasesolutions.com> 
wrote:

> For this, the old method of finding vports based on the
> ovs port numbers is removed. Now, the lookup of a vport
> by ovs port number is done the same way as the lookup by
> hyper-v switch port id.

Hmm, the only concern I have is that we call into OvsFindVportByPortNo() many 
times. We should make a good effort that the hash table has as minimum 
collisions as possible. I don't mind using a bigger hash bucker just for 
portNo. Eg. for every packet, we call OvsFindVportByPortNo() at lease 2x of 
number of output ports.


> 
> This is done so that the kernel is able to interact with
> the userspace correctly when using vport channels.
> The problem manifested in lib/dpif-netlink.c, at the function
> vport_add_channels.
> 
> This patch removes the field vportArray from OVS_SWITCH_CONTEXT.
> In its place, portNoHashArray is set. In the OVS_VPORT_ENTRY
> struct, we also add portNoLink. This new method will do lookup
> and insertions of vports by ovs (datapath) port numbers the same
> way it is done for hyper-v switch port ids.
> 
> This patch implicitly removes the indexes, which were previously
> used in insertions and lookups on ovs port numbers. The removal
> of the index also means that the vxlan vport can no longer be
> looked up the same way as it was done before: now we hold a pointer
> to it, vxlanVport in OVS_SWITCH_CONTEXT. For the moment, we can
> have only one vxlan vport. When more will be allowed, this field
> will turn into a list of vxlan ports.
> 
> The invalid port number value (held in OVS_DPPORT_NUMBER_INVALID)
> is now changed from 0 to MAXUINT16, the same as it is on linux.

Ok, we can remove the OVS_DEFAULT_PORT_NO now, and udpate other port number 
fields to be 16-bit too.

> 
> The function OvsComputeVportNo has also been removed, since the
> computation of a vport port number can no longer be done like this.
> When vport add will be added, a new, updated OvsComputeVportNo
> function will be added.
> 
> Also, in OvsInitVportCommon, we no longer need to (and no longer can)
> initialize vport->ovsName, nor vport->ovsNameLen, because they will
> be initialized by the netlink command vport add. Since the netlink
> command vport add will generate numbers for the datapath (ovs) port
> numbers and set the port names, we cannot insert the vport into the
> hash array of port numbers here, nor into the hash array of port names.
> 
> Signed-off-by: Samuel Ghinet <sghi...@cloudbasesolutions.com>
> ---
> datapath-windows/ovsext/Actions.c |  27 ++++--
> datapath-windows/ovsext/Switch.c  |  28 ++-----
> datapath-windows/ovsext/Switch.h  |  18 ++--
> datapath-windows/ovsext/Tunnel.c  |   2 +-
> datapath-windows/ovsext/Vport.c   | 169 ++++++++++----------------------------
> datapath-windows/ovsext/Vport.h   |  56 +++----------
> 6 files changed, 94 insertions(+), 206 deletions(-)
> 
> diff --git a/datapath-windows/ovsext/Actions.c 
> b/datapath-windows/ovsext/Actions.c
> index 180b6b8..cf44140 100644
> --- a/datapath-windows/ovsext/Actions.c
> +++ b/datapath-windows/ovsext/Actions.c
> @@ -205,7 +205,7 @@ OvsDetectTunnelRxPkt(OvsForwardingContext *ovsFwdCtx,
>     if (!flowKey->ipKey.nwFrag &&
>         flowKey->ipKey.nwProto == IPPROTO_UDP &&
>         flowKey->ipKey.l4.tpDst == VXLAN_UDP_PORT_NBO) {
> -        tunnelVport = OvsGetTunnelVport(OVS_VPORT_TYPE_VXLAN);
> +        tunnelVport = ovsFwdCtx->switchContext->vxlanVport;
>         ovsActionStats.rxVxlan++;
>     }
> 
> @@ -271,9 +271,14 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx,
>          * If the packet will not be encapsulated, consume the tunnel context
>          * by clearing it.
>          */
> -        if (ovsFwdCtx->srcVportNo != OVS_DEFAULT_PORT_NO &&
> -            !OvsIsVifVportNo(ovsFwdCtx->srcVportNo)) {
> -            ovsFwdCtx->tunKey.dst = 0;
> +        if (ovsFwdCtx->srcVportNo != OVS_DEFAULT_PORT_NO) {
> +
> +            POVS_VPORT_ENTRY vport = OvsFindVportByPortNo(
> +                ovsFwdCtx->switchContext, ovsFwdCtx->srcVportNo);
> +
> +            if (!vport || vport->ovsType != OVS_VPORT_TYPE_NETDEV) {
> +                ovsFwdCtx->tunKey.dst = 0;
> +            }

There's intermixing of OVS_DEFAULT_PORT_NO and OVS_DPPORT_NUMBER_INVALID.


>         }
> 
>         /* Tunnel the packet only if tunnel context is set. */
> @@ -1468,9 +1473,17 @@ OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext,
>             PNL_ATTR queueAttr;
>             POVS_PACKET_QUEUE_ELEM elem;
>             UINT32 queueId = OVS_DEFAULT_PACKET_QUEUE;
> -            //XXX confusing that portNo is actually portId for external port.
> -            BOOLEAN isRecv = (portNo == switchContext->externalPortId)
> -                            || OvsIsTunnelVportNo(portNo);
> +            BOOLEAN isRecv = FALSE;
> +
> +            POVS_VPORT_ENTRY vport = OvsFindVportByPortNo(switchContext,
> +                                                          portNo);
> +
> +            if (vport) {
> +                if (vport->isExternal ||
> +                    OvsIsTunnelVportType(vport->ovsType)) {
> +                    isRecv = TRUE;
> +                }
> +            }
> 
>             queueAttr = NlAttrFindNested(a, OVS_USERSPACE_ATTR_PID);
>             userdataAttr = NlAttrFindNested(a, OVS_USERSPACE_ATTR_USERDATA);
> diff --git a/datapath-windows/ovsext/Switch.c 
> b/datapath-windows/ovsext/Switch.c
> index ca95bdd..fbf5e80 100644
> --- a/datapath-windows/ovsext/Switch.c
> +++ b/datapath-windows/ovsext/Switch.c
> @@ -354,8 +354,8 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
>     switchContext->dispatchLock =
>         NdisAllocateRWLock(switchContext->NdisFilterHandle);
> 
> -    switchContext->vportArray =
> -        (PVOID *)OvsAllocateMemory(sizeof (PVOID) * 
> OVS_MAX_VPORT_ARRAY_SIZE);
> +    switchContext->portNoHashArray = (PLIST_ENTRY)
> +        OvsAllocateMemory(sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE);
>     switchContext->ovsPortNameHashArray = (PLIST_ENTRY)
>          OvsAllocateMemory(sizeof (LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE);
>     switchContext->portIdHashArray = (PLIST_ENTRY)
> @@ -367,14 +367,14 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
>     }
>     if (status != NDIS_STATUS_SUCCESS ||
>         switchContext->dispatchLock == NULL ||
> -        switchContext->vportArray == NULL ||
> +        switchContext->portNoHashArray == NULL ||
>         switchContext->ovsPortNameHashArray == NULL ||
>         switchContext->portIdHashArray == NULL) {
>         if (switchContext->dispatchLock) {
>             NdisFreeRWLock(switchContext->dispatchLock);
>         }
> -        if (switchContext->vportArray) {
> -            OvsFreeMemory(switchContext->vportArray);
> +        if (switchContext->portNoHashArray) {
> +            OvsFreeMemory(switchContext->portNoHashArray);
>         }
>         if (switchContext->ovsPortNameHashArray) {
>             OvsFreeMemory(switchContext->ovsPortNameHashArray);
> @@ -395,13 +395,13 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
>     for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
>         InitializeListHead(&switchContext->portIdHashArray[i]);
>     }
> -    RtlZeroMemory(switchContext->vportArray,
> -                  sizeof (PVOID) * OVS_MAX_VPORT_ARRAY_SIZE);
> +    for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
> +        InitializeListHead(&switchContext->portNoHashArray[i]);
> +    }
> 
>     switchContext->isActivated = FALSE;
>     switchContext->isActivateFailed = FALSE;
>     switchContext->dpNo = OVS_DP_NUMBER;
> -    switchContext->lastPortIndex = OVS_MAX_VPORT_ARRAY_SIZE -1;
>     ovsTimeIncrementPerTick = KeQueryTimeIncrement() / 10000;
>     OVS_LOG_TRACE("Exit: Succesfully initialized switchContext: %p",
>                   switchContext);
> @@ -419,7 +419,7 @@ OvsCleanupSwitchContext(POVS_SWITCH_CONTEXT switchContext)
>     NdisFreeRWLock(switchContext->dispatchLock);
>     OvsFreeMemory(switchContext->ovsPortNameHashArray);
>     OvsFreeMemory(switchContext->portIdHashArray);
> -    OvsFreeMemory(switchContext->vportArray);
> +    OvsFreeMemory(switchContext->portNoHashArray);
>     OvsDeleteFlowTable(&switchContext->datapath);
>     OvsCleanupBufferPool(switchContext);
>     OVS_LOG_TRACE("Exit: Delete switchContext: %p", switchContext);
> @@ -469,16 +469,6 @@ cleanup:
> }
> 
> PVOID
> -OvsGetVportFromIndex(UINT16 index)
> -{
> -    if (index < OVS_MAX_VPORT_ARRAY_SIZE &&
> -            !OVS_IS_VPORT_ENTRY_NULL(gOvsSwitchContext, index)) {
> -        return gOvsSwitchContext->vportArray[index];
> -    }
> -    return NULL;
> -}
> -
> -PVOID
> OvsGetExternalVport()
> {
>     return gOvsSwitchContext->externalVport;
> diff --git a/datapath-windows/ovsext/Switch.h 
> b/datapath-windows/ovsext/Switch.h
> index 5cf65b9..83a725c 100644
> --- a/datapath-windows/ovsext/Switch.h
> +++ b/datapath-windows/ovsext/Switch.h
> @@ -43,10 +43,6 @@
> #define OVS_INTERNAL_VPOR_END    72
> #define OVS_VM_VPORT_START       72
> #define OVS_VM_VPORT_MAX         0xffff

We don't need these constants either.

> -#define OVS_VPORT_INDEX(_portNo)    ((_portNo) & 0xffffff)
> -#define OVS_VPORT_PORT_NO(_index, _gen) \
> -          (((_index) & 0xffffff) | ((UINT32)(_gen) << 24))
> -#define OVS_VPORT_GEN(portNo) (portNo >> 24)
> 
> #define OVS_MAX_PHYS_ADAPTERS    32
> #define OVS_MAX_IP_VPOR          32
> @@ -109,13 +105,18 @@ typedef struct _OVS_SWITCH_CONTEXT
>     POVS_VPORT_ENTRY        externalVport;  // the virtual adapter vport
>     POVS_VPORT_ENTRY        internalVport;
> 
> -    PVOID                  *vportArray;
> -    PLIST_ENTRY             ovsPortNameHashArray;  // based on ovsName
> -    PLIST_ENTRY             portIdHashArray;       // based on portId
> +    /*
> +     * XXX when we support multiple VXLAN ports, we will need a list entry
> +     * instead
> +    */
> +    POVS_VPORT_ENTRY        vxlanVport;
> +
> +    PLIST_ENTRY             ovsPortNameHashArray;    // based on ovsName
> +    PLIST_ENTRY             portIdHashArray;                  // based on 
> portId
> +    PLIST_ENTRY             portNoHashArray;                  // based on 
> ovs port number
> 
>     UINT32                  numPhysicalNics;
>     UINT32                  numVports;     // include validation port
> -    UINT32                  lastPortIndex;
> 
>     /* Lock taken over the switch. This protects the ports on the switch. */
>     PNDIS_RW_LOCK_EX        dispatchLock;
> @@ -165,7 +166,6 @@ OvsReleaseDatapath(OVS_DATAPATH *datapath,
> }
> 
> 
> -PVOID OvsGetVportFromIndex(UINT16 index);
> PVOID OvsGetExternalVport();
> 
> #endif /* __SWITCH_H_ */
> diff --git a/datapath-windows/ovsext/Tunnel.c 
> b/datapath-windows/ovsext/Tunnel.c
> index 304ab59..64e279c 100644
> --- a/datapath-windows/ovsext/Tunnel.c
> +++ b/datapath-windows/ovsext/Tunnel.c
> @@ -284,7 +284,7 @@ OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl,
> 
>         SendFlags |= NDIS_SEND_FLAGS_DISPATCH_LEVEL;
> 
> -        vport = OvsGetTunnelVport(OVS_VPORT_TYPE_VXLAN);
> +        vport = gOvsSwitchContext->vxlanVport;
> 
>         if (vport == NULL){
>             status = STATUS_UNSUCCESSFUL;
> diff --git a/datapath-windows/ovsext/Vport.c b/datapath-windows/ovsext/Vport.c
> index 28319a4..443e71e 100644
> --- a/datapath-windows/ovsext/Vport.c
> +++ b/datapath-windows/ovsext/Vport.c
> @@ -211,7 +211,7 @@ HvOnCreateNic(POVS_SWITCH_CONTEXT switchContext,
> 
> add_nic_done:
>     NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
> -    if (portNo && event) {
> +    if (portNo != OVS_DPPORT_NUMBER_INVALID && event) {
>         OvsPostEvent(portNo, event);
>     }
> 
> @@ -260,6 +260,7 @@ HvOnConnectNic(POVS_SWITCH_CONTEXT switchContext,
> 
>     NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
> 
> +    /* XXX only if portNo != INVALID or always? */
>     OvsPostEvent(portNo, OVS_EVENT_LINK_UP);
> 
>     if (nicParam->NicType == NdisSwitchNicTypeInternal) {
> @@ -384,6 +385,7 @@ HvOnDisconnectNic(POVS_SWITCH_CONTEXT switchContext,
> 
>     NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
> 
> +    /* XXX if portNo != INVALID or always? */
>     OvsPostEvent(portNo, OVS_EVENT_LINK_DOWN);
> 
>     if (isInternalPort) {
> @@ -432,6 +434,7 @@ HvOnDeleteNic(POVS_SWITCH_CONTEXT switchContext,
>     vport->ovsState = OVS_STATE_PORT_CREATED;
> 
>     NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
> +    /* XXX if portNo != INVALID or always? */
>     OvsPostEvent(portNo, OVS_EVENT_DISCONNECT);
> 
> done:
> @@ -446,14 +449,15 @@ POVS_VPORT_ENTRY
> OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,
>                      UINT32 portNo)
> {
> -    if (OVS_VPORT_INDEX(portNo) < OVS_MAX_VPORT_ARRAY_SIZE) {
> -        if (OVS_IS_VPORT_ENTRY_NULL(switchContext, OVS_VPORT_INDEX(portNo))) 
> {
> -            return NULL;
> -        } else {
> -            POVS_VPORT_ENTRY vport;
> -            vport = (POVS_VPORT_ENTRY)
> -                     switchContext->vportArray[OVS_VPORT_INDEX(portNo)];
> -            return vport->portNo == portNo ? vport : NULL;
> +    POVS_VPORT_ENTRY vport;
> +    PLIST_ENTRY head, link;
> +    UINT32 hash = OvsJhashBytes((const VOID *)&portNo, sizeof(portNo),
> +                                OVS_HASH_BASIS);
> +    head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);
> +    LIST_FORALL(head, link) {
> +        vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);
> +        if (vport->portNo == portNo) {
> +            return vport;
>         }
>     }
>     return NULL;
> @@ -485,18 +489,7 @@ OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT 
> switchContext,
>                                 NDIS_SWITCH_NIC_INDEX index)
> {
>     if (portId == switchContext->externalPortId) {
> -        if (index == 0) {
> -            return (POVS_VPORT_ENTRY)switchContext->externalVport;
> -        } else if (index > OVS_MAX_PHYS_ADAPTERS) {
> -            return NULL;
> -        }
> -        if (OVS_IS_VPORT_ENTRY_NULL(switchContext,
> -                                    index + OVS_EXTERNAL_VPORT_START)) {
> -           return NULL;
> -        } else {
> -           return (POVS_VPORT_ENTRY)switchContext->vportArray[
> -                            index + OVS_EXTERNAL_VPORT_START];
> -        }
> +        return (POVS_VPORT_ENTRY)switchContext->externalVport;
>     } else if (switchContext->internalPortId == portId) {
>         return (POVS_VPORT_ENTRY)switchContext->internalVport;
>     } else {
> @@ -515,72 +508,6 @@ OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT 
> switchContext,
>     }
> }
> 
> -UINT32
> -OvsComputeVportNo(POVS_SWITCH_CONTEXT switchContext,
> -                  UINT32 nicIndex,
> -                  OVS_VPORT_TYPE ovsType,
> -                  BOOLEAN isExternal)
> -{
> -    UINT32 index = 0xffffff, i = 0;
> -    UINT64 gen;
> -
> -    if (isExternal) {
> -        if (nicIndex == 0) {
> -            return 0;  // not a valid portNo
> -        } else if (nicIndex > OVS_MAX_PHYS_ADAPTERS) {
> -            return 0;
> -        } else {
> -            index = nicIndex + OVS_EXTERNAL_VPORT_START;
> -        }
> -    }
> -
> -    switch (ovsType) {
> -    case OVS_VPORT_TYPE_INTERNAL:
> -        index = OVS_INTERNAL_VPORT_DEFAULT_INDEX;
> -        break;
> -    case OVS_VPORT_TYPE_NETDEV:
> -        index = switchContext->lastPortIndex + 1;
> -        if (index == OVS_MAX_VPORT_ARRAY_SIZE) {
> -            index = OVS_VM_VPORT_START;
> -        }
> -        while (!OVS_IS_VPORT_ENTRY_NULL(switchContext, index) &&
> -               i < (OVS_MAX_VPORT_ARRAY_SIZE - OVS_VM_VPORT_START)) {
> -            index++;
> -            i++;
> -            if (index == OVS_MAX_VPORT_ARRAY_SIZE) {
> -                index = OVS_VM_VPORT_START;
> -            }
> -        }
> -        if (i == (OVS_MAX_VPORT_ARRAY_SIZE - OVS_VM_VPORT_START)) {
> -            return 0; // not available
> -        }
> -        switchContext->lastPortIndex = index;
> -        break;
> -    case OVS_VPORT_TYPE_GRE:
> -        index = OVS_GRE_VPORT_INDEX;
> -        break;
> -    case OVS_VPORT_TYPE_GRE64:
> -        index = OVS_GRE64_VPORT_INDEX;
> -        break;
> -    case OVS_VPORT_TYPE_VXLAN:
> -        index = OVS_VXLAN_VPORT_INDEX;
> -        break;
> -    default:
> -        ASSERT(isExternal);
> -    }
> -    if (index > OVS_MAX_VPORT_ARRAY_SIZE) {
> -        return 0;
> -    }
> -    gen = (UINT64)switchContext->vportArray[index];
> -    if (gen > 0xff) {
> -        return 0;
> -    } else if (gen == 0) {
> -        gen++;
> -    }
> -    return OVS_VPORT_PORT_NO(index, (UINT32)gen);
> -}
> -
> -
> static POVS_VPORT_ENTRY
> OvsAllocateVport(VOID)
> {
> @@ -591,6 +518,12 @@ OvsAllocateVport(VOID)
>     }
>     RtlZeroMemory(vport, sizeof (OVS_VPORT_ENTRY));
>     vport->ovsState = OVS_STATE_UNKNOWN;
> +    vport->portNo = OVS_DPPORT_NUMBER_INVALID;
> +
> +    InitializeListHead(&vport->ovsNameLink);
> +    InitializeListHead(&vport->portIdLink);
> +    InitializeListHead(&vport->portNoLink);
> +
>     return vport;
> }
> 
> @@ -699,63 +632,45 @@ OvsInitPhysNicVport(POVS_VPORT_ENTRY vport,
> }
> static NDIS_STATUS
> OvsInitVportCommon(POVS_SWITCH_CONTEXT switchContext,
> -POVS_VPORT_ENTRY vport)
> +                   POVS_VPORT_ENTRY vport)
> {
>     UINT32 hash;
> -    size_t len;
> -    if (vport->portType != NdisSwitchPortTypeExternal ||
> -        vport->nicIndex != 0) {
> -        vport->portNo = OvsComputeVportNo(switchContext, vport->nicIndex,
> -            vport->ovsType, vport->portType == NdisSwitchPortTypeExternal);
> -        if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) {
> -            return NDIS_STATUS_RESOURCES;
> -        }
> -        ASSERT(OVS_IS_VPORT_ENTRY_NULL(switchContext,
> -            OVS_VPORT_INDEX(vport->portNo)));
> 
> -        switchContext->vportArray[OVS_VPORT_INDEX(vport->portNo)] = vport;
> -    }

Adding an external port is a little complicated. We get two calls to 
OvsCreateNic(). The code above kind of handled this case. Anyway, we need to 
simplify this code. So, I am OK with getting rid of it.

> +    ASSERT(vport->portNo == OVS_DPPORT_NUMBER_INVALID);
> +
>     switch (vport->portType) {
>     case NdisSwitchPortTypeExternal:
>         if (vport->nicIndex == 0) {
>             switchContext->externalPortId = vport->portId;
>             switchContext->externalVport = vport;
> -            RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
> -                "external.virtualAdapter");
> -        }
> -        else {
> +        } else {
>             switchContext->numPhysicalNics++;

The else code is not really serving the purpose it is supposed to. But, I am ok 
with it. Pls. add a XXX: comment saying we need to handle this in the future.

> -            RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
> -                "external.%lu", (UINT32)vport->nicIndex);
>         }
>         break;
>     case NdisSwitchPortTypeInternal:
>         switchContext->internalPortId = vport->portId;
>         switchContext->internalVport = vport;
> -        RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
> -            "internal");
>         break;
>     case NdisSwitchPortTypeSynthetic:
> -        RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
> -            "vmNICSyn.%lx", vport->portNo);
>         break;
>     case NdisSwitchPortTypeEmulated:
> -        RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
> -            "vmNICEmu.%lx", vport->portNo);
>         break;
>     }
> -    StringCbLengthA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1, &len);
> -    vport->ovsNameLen = (UINT32)len;
> +
>     if (vport->portType == NdisSwitchPortTypeExternal &&
>         vport->nicIndex == 0) {
>         return NDIS_STATUS_SUCCESS;
>     }
> -    hash = OvsJhashBytes(vport->ovsName, vport->ovsNameLen, OVS_HASH_BASIS);
> -    InsertHeadList(&switchContext->ovsPortNameHashArray[hash & 
> OVS_VPORT_MASK],
> -        &vport->ovsNameLink);
> +
> +    /*
> +     * NOTE: OvsJhashWords has portId as "1" word. This should be ok, even
> +     * though sizeof(NDIS_SWITCH_PORT_ID) = 4, not 2, because the
> +     * hyper-v switch seems to use only 2 bytes out of 4.
> +    */

Pls. add a XXX comment, we'll revisit this in the future.

>     hash = OvsJhashWords(&vport->portId, 1, OVS_HASH_BASIS);
>     InsertHeadList(&switchContext->portIdHashArray[hash & OVS_VPORT_MASK],
>         &vport->portIdLink);
> +
>     switchContext->numVports++;
>     return NDIS_STATUS_SUCCESS;
> }
> @@ -765,8 +680,6 @@ static VOID
> OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
>                         POVS_VPORT_ENTRY vport)
> {
> -    UINT64 gen = vport->portNo >> 24;
> -
>     if (vport->isExternal) {
>         if (vport->nicIndex == 0) {
>             ASSERT(switchContext->numPhysicalNics == 0);
> @@ -799,9 +712,7 @@ OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
> 
>     RemoveEntryList(&vport->ovsNameLink);
>     RemoveEntryList(&vport->portIdLink);
> -    gen = (gen + 1) & 0xff;
> -    switchContext->vportArray[OVS_VPORT_INDEX(vport->portNo)] =
> -                     (PVOID)(UINT64)gen;
> +    RemoveEntryList(&vport->portNoLink);
>     switchContext->numVports--;
>     OvsFreeMemory(vport);
> }
> @@ -925,14 +836,18 @@ cleanup:
> VOID
> OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
> {
> -    UINT32 i;
> +    for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; ++hash) {
> +        PLIST_ENTRY head, link;
> +
> +        head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]);
> +        LIST_FORALL(head, link) {
> +            POVS_VPORT_ENTRY vport;
> 
> -    for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
> -        if (!OVS_IS_VPORT_ENTRY_NULL(switchContext, i)) {
> -            OvsRemoveAndDeleteVport(switchContext,
> -                       (POVS_VPORT_ENTRY)switchContext->vportArray[i]);
> +            vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink);
> +            OvsRemoveAndDeleteVport(switchContext, vport);
>         }
>     }
> +
>     if (switchContext->externalVport) {
>         OvsRemoveAndDeleteVport(switchContext,
>                         (POVS_VPORT_ENTRY)switchContext->externalVport);

I don't know if we need the special code to remove a vport based on 
'switchContext->externalVport'. All the Vports should be part of 
portNoHashArray. So, if you flush that list, it should be sufficient. Did you 
encounter any double frees in your testing?


> diff --git a/datapath-windows/ovsext/Vport.h b/datapath-windows/ovsext/Vport.h
> index fce16e2..678c7c5 100644
> --- a/datapath-windows/ovsext/Vport.h
> +++ b/datapath-windows/ovsext/Vport.h
> @@ -17,7 +17,18 @@
> #ifndef __VPORT_H_
> #define __VPORT_H_ 1
> 
> -#define OVS_DPPORT_NUMBER_INVALID 0
> +#define OVS_MAX_DPPORTS             MAXUINT16
> +#define OVS_DPPORT_NUMBER_INVALID   OVS_MAX_DPPORTS
> +/*
> + * The local port (0) is a reserved port, that is not allowed to be be
> + * created by the netlink command vport add. On linux, this port is created
> + * at netlink command datapath new. However, on windows, we do not need to
> + * create it, and more, we shouldn't. The userspace attempts to create two
> + * internal vports, the LOCAL port (0) and the internal port (with any other
> + * port number). The non-LOCAL internal port is used in the userspace when it
> + * requests the internal port.
> +*/
> +#define OVS_DPPORT_LOCAL            0

Pls. call this OVS_DPPORT_NUMBER_LOCAL.

> 
> #include "Switch.h"
> 
> @@ -67,6 +78,7 @@ typedef struct _OVS_VPORT_FULL_STATS {
> typedef struct _OVS_VPORT_ENTRY {
>     LIST_ENTRY             ovsNameLink;
>     LIST_ENTRY             portIdLink;
> +    LIST_ENTRY             portNoLink;
> 
>     OVS_VPORT_STATE        ovsState;
>     OVS_VPORT_TYPE         ovsType;
> @@ -99,9 +111,6 @@ typedef struct _OVS_VPORT_ENTRY {
> 
> struct _OVS_SWITCH_CONTEXT;
> 
> -#define OVS_IS_VPORT_ENTRY_NULL(_SwitchContext, _i) \
> -   ((UINT64)(_SwitchContext)->vportArray[_i] <= 0xff)
> -
> POVS_VPORT_ENTRY
> OvsFindVportByPortNo(struct _OVS_SWITCH_CONTEXT *switchContext,
>                      UINT32 portNo);
> @@ -148,49 +157,10 @@ OvsIsInternalVportType(OVS_VPORT_TYPE ovsType)
>     return ovsType == OVS_VPORT_TYPE_INTERNAL;
> }
> 
> -static __inline BOOLEAN
> -OvsIsTunnelVportNo(UINT32 portNo)
> -{
> -    UINT32 idx = OVS_VPORT_INDEX(portNo);
> -    return (idx >= OVS_TUNNEL_INDEX_START && idx <= OVS_TUNNEL_INDEX_END);
> -}

OvsIsTunnelVportNo() can can still be useful, but we can add it back later.

> -
> -static __inline BOOLEAN
> -OvsIsVifVportNo(UINT32 portNo)
> -{
> -    UINT32 idx = OVS_VPORT_INDEX(portNo);
> -    return (idx >= OVS_VM_VPORT_START && idx <= OVS_VM_VPORT_MAX);
> -}
> -
> -static __inline POVS_VPORT_ENTRY
> -OvsGetTunnelVport(OVS_VPORT_TYPE type)
> -{
> -    ASSERT(OvsIsTunnelVportType(type));
> -    switch(type) {
> -    case OVS_VPORT_TYPE_VXLAN:
> -        return (POVS_VPORT_ENTRY) 
> OvsGetVportFromIndex(OVS_VXLAN_VPORT_INDEX);
> -    default:
> -        ASSERT(! "OvsGetTunnelVport not implemented for this tunnel.");
> -    }
> -
> -    return NULL;
> -}
> -
> -static __inline PVOID
> -OvsGetVportPriv(OVS_VPORT_TYPE type)
> -{
> -    return OvsGetTunnelVport(type)->priv;
> -}
> -
> static __inline UINT32
> OvsGetExternalMtu()
> {
>     return ((POVS_VPORT_ENTRY) OvsGetExternalVport())->mtu;
> }
> 
> -UINT32 OvsComputeVportNo(POVS_SWITCH_CONTEXT switchContext,
> -                         UINT32 nicIndex,
> -                         OVS_VPORT_TYPE ovsType,
> -                         BOOLEAN isExternal);
> -
> #endif /* __VPORT_H_ */
> -- 
> 1.8.3.msysgit.0
> 

Thanks,
-- Nithin

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to