Hey Ankur,

> +    if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
> +        destKey->tunKey.tunnelId = NlAttrGetU64
> +                                   (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
> +        destKey->tunKey.dst = NlAttrGetU32
> +                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
> +        destKey->tunKey.src = NlAttrGetU32
> +                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
> +
> +        /* XXX: There are no attributes to specify tunnel flags.
> +         * Also, i do not see these flags being used anywhere in
> +         * flowPut code. */
> +        destKey->tunKey.flags = 0;
> +        destKey->tunKey.tos = NlAttrGetU8

Those flags are actually necessary.
The flag attributes are (OvsDpInterface.h):
[CODE]
        OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT,      /* No argument, set DF. */
        OVS_TUNNEL_KEY_ATTR_CSUM,               /* No argument. CSUM packet. */
        OVS_TUNNEL_KEY_ATTR_OAM,                /* No argument, OAM frame. */
[/CODE]
The tunnelKey must OR together the flags, based on the attributes.
Each attribute that is a flag does not have a length, nor payload, as I 
remember. If the attribute flag appears, it means you must take it as set. If 
the flag attribute does not appear, you must take it as not set.

The corresponding flags are:
[CODE]
/* Flags for tunneling */
#define OVS_TNL_F_DONT_FRAGMENT         (1 << 0)
#define OVS_TNL_F_CSUM                  (1 << 1)
#define OVS_TNL_F_KEY                   (1 << 2)
[/CODE]

Also,
_OvsFlowMapTunAttrToFlowPut:
> +        destKey->tunKey.tunnelId = NlAttrGetU64
> +                                   (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
This will crash if the userspace did not give you a tunnel attribute "tunnel 
id". And you also have it specified as "optional" in the policy.

OvsFlowMapKeyAttrToFlowPut:
> destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
The same here.
> eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
and here. It is possible that the eth key is required. Or that it is optional 
(I think in ovs 1.11 was required, but in 2.3, when masks were allowed, was 
optional - experience with our implementation of the driver)

>     case ETH_TYPE_ARP:
>     case ETH_TYPE_RARP: {
I really believe RARP is no longer used, since some long time ago.

>     case ETH_TYPE_IPV4: {
>         const struct ovs_key_ipv4 *ipv4Key;
>         const struct ovs_key_tcp *tcpKey;
> 
>         ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
It is possible that the eth type attribute was given "ipv4" but the ipv4 key 
was not given. When key masks are allowed, this can happen if the ipv4 key is 
considered to be "wildcard" so it is not given as a key, nor mask, at all.

>         if (keyAttrs[OVS_KEY_ATTR_TCP]) {
>            tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
>            ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
>            ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
>        }
Where is tcp flags set?

>         arpFlowPutKey->pad[0] = 0;
>        arpFlowPutKey->pad[1] = 0;
>        arpFlowPutKey->pad[2] = 0;
>        destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
What I particularly don't like about the old approach with flows is this 
somewhat crypted text.
I wished there was at least some documentation on structs like this:
[CODE]
typedef struct L2Key {
    uint32_t inPort;             /* Port number of input port. */
    union {
        struct {
            uint16_t offset;
            uint16_t keyLen;
        };
        uint32_t val;
    };
[/CODE]
on what the fields are and how they are used.

Also,
_OvsFlowMapKeyAttrToFlowPut,
_OvsFlowMapTunAttrToFlowPut,
_OvsFlowMapNlToFlowPutFlags,
_OvsFlowMapNlToFlowPut
The names are very long and very similar to one another. It is very easy to 
confuse one with the other, when reading.
Perhaps something like _KeyMapToFlowPut, _FlowMapToFlowPut, _FlowMapToFlags.
Or perhaps use a "FP" for FlowPut, and document this shorthand.

>     eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
>     memcpy(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
>    memcpy(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
For those who prefer the Rtl* style, there is RtlCopyMemory :)

Regards,
Sam
________________________________________
Date: Wed, 24 Sep 2014 00:15:41 -0700
From: Ankur Sharma <ankursha...@vmware.com>
To: dev@openvswitch.org
Subject: [ovs-dev] [PATCH v1 07/10] datapath-windows/Flow.c: FLOW_NEW
        command handler.
Message-ID: <1411542944-19374-7-git-send-email-ankursha...@vmware.com>

This patch covers the changes needed to support FLOW_NEW command.
API _OvsFlowMapNlToFlowPutFlags has a bug, which will be fixed
with the patches for FLOW_DEL.
---
 datapath-windows/include/OvsPub.h |   2 +-
 datapath-windows/ovsext/Flow.c    | 384 +++++++++++++++++++++++++++++++++++---
 datapath-windows/ovsext/Flow.h    |   6 +-
 3 files changed, 366 insertions(+), 26 deletions(-)

diff --git a/datapath-windows/include/OvsPub.h 
b/datapath-windows/include/OvsPub.h
index 36814c4..fa1d6d4 100644
--- a/datapath-windows/include/OvsPub.h
+++ b/datapath-windows/include/OvsPub.h
@@ -420,7 +420,7 @@ typedef struct OvsFlowPut {
     uint32_t actionsLen;
     OvsFlowKey key;
     uint32_t flags;
-    NL_ATTR  actions[0];  /* Variable length indicated by actionsLen. */
+    PNL_ATTR  actions;
 } OvsFlowPut;

 #define OVS_MIN_PACKET_SIZE 60
diff --git a/datapath-windows/ovsext/Flow.c b/datapath-windows/ovsext/Flow.c
index 25b39c1..e170de6 100644
--- a/datapath-windows/ovsext/Flow.c
+++ b/datapath-windows/ovsext/Flow.c
@@ -46,6 +46,20 @@ static VOID DeleteAllFlows(OVS_DATAPATH *datapath);
 static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow);
 static VOID FreeFlow(OvsFlow *flow);
 static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB);
+static NTSTATUS _OvsFlowMapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
+                                       PNL_ATTR actionAttr,
+                                       PNL_ATTR flowAttrClear,
+                                       OvsFlowPut *mappedFlow);
+static VOID _OvsFlowMapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
+                                        PNL_ATTR *tunnelAttrs,
+                                        OvsFlowPut *mappedFlow);
+
+static VOID _OvsFlowMapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
+                                        PNL_ATTR *tunnelAttrs,
+                                        OvsFlowKey *destKey);
+static VOID _OvsFlowMapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr,
+                                        PNL_ATTR flowAttrClear,
+                                        OvsFlowPut *mappedFlow);

 #define OVS_FLOW_TABLE_SIZE 2048
 #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1)
@@ -191,20 +205,365 @@ static const NL_POLICY nlFlowActionPolicy[] = {
  * Netlink interface for flow commands.
  *----------------------------------------------------------------------------
  */
+
+/*
+ *----------------------------------------------------------------------------
+ *  OvsFlowNlNewCmdHandler --
+ *    Handler for OVS_FLOW_CMD_NEW command.
+ *----------------------------------------------------------------------------
+ */
 NTSTATUS
 OvsFlowNlNewCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
                        UINT32 *replyLen)
 {
     NTSTATUS rc = STATUS_SUCCESS;
+    POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
+    POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
+    PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
+    PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
+    POVS_HDR ovsHdr = &(msgIn->ovsHdr);
+    PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX];
+    UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN;
+    POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
+                                   usrParamsCtx->ovsInstance;
+    OvsFlowPut mappedFlow;
+    OvsFlowStats stats;
+    struct ovs_flow_stats replyStats;
+
+    NL_BUFFER nlBuf;
+
+    UNREFERENCED_PARAMETER(genlMsgHdr);
+    UNREFERENCED_PARAMETER(ovsHdr);
+    UNREFERENCED_PARAMETER(instance);
+
+    RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
+    RtlZeroMemory(&stats, sizeof(stats));
+    RtlZeroMemory(&replyStats, sizeof(replyStats));
+
+    *replyLen = 0;
+
+    /* Get all the top level Flow attributes */
+    if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrLen(nlMsgHdr),
+                     nlFlowPolicy, nlAttrs, ARRAY_SIZE(nlAttrs)))
+                     != TRUE) {
+        OVS_LOG_ERROR("Attr Parsing failed for msg: %p",
+                       nlMsgHdr);
+        rc = NDIS_STATUS_FAILURE;
+        goto done;
+    }
+
+    if ((_OvsFlowMapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
+         nlAttrs[OVS_FLOW_ATTR_ACTIONS], nlAttrs[OVS_FLOW_ATTR_CLEAR],
+         &mappedFlow))
+        != NDIS_STATUS_SUCCESS) {
+        OVS_LOG_ERROR("Conversion to OvsFlowPut failed");
+        goto done;
+    }
+
+    rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
+                         &stats);
+    if (rc != STATUS_SUCCESS) {
+        OVS_LOG_ERROR("OvsFlowPut failed.");
+        goto done;
+    }
+
+    if (!(usrParamsCtx->outputBuffer)) {
+        /* No output buffer */
+        OVS_LOG_ERROR("outputBuffer NULL.");
+        goto done;
+    }
+
+    replyStats.n_packets = stats.packetCount;
+    replyStats.n_bytes = stats.byteCount;
+
+    /* So far so good. Prepare the reply for userspace */
+    NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
+              usrParamsCtx->outputLength);
+
+    /* Prepare nl Msg headers */
+    rc = NlFillOvsMsg(msgOut, &nlBuf, nlMsgHdr->nlmsgType, 0,
+                      nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
+                      genlMsgHdr->cmd, OVS_FLOW_VERSION,
+                      ovsHdr->dp_ifindex);
+    ASSERT(rc);
+
+    /* Append OVS_FLOW_ATTR_STATS attribute */
+    if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
+        (PCHAR)(&replyStats), sizeof(replyStats))) {
+        OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed.");
+        rc = NDIS_STATUS_FAILURE;
+    }
+
+    *replyLen = msgOut->nlMsg.nlmsgLen;
+
+done:
+    return rc;
+}
+
+/*
+ *----------------------------------------------------------------------------
+ *  _OvsFlowMapNlToFlowPut --
+ *    Maps input netlink message to OvsFlowPut.
+ *----------------------------------------------------------------------------
+ */
+static NTSTATUS
+_OvsFlowMapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
+                       PNL_ATTR actionAttr, PNL_ATTR flowAttrClear,
+                       OvsFlowPut *mappedFlow)
+{
+    NTSTATUS rc = NDIS_STATUS_SUCCESS;
+    PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
+    PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
+    POVS_HDR ovsHdr = &(msgIn->ovsHdr);
+
+    UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
+    UINT32 tunnelKeyAttrOffset;
+
+    PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
+    PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
+
+    UNREFERENCED_PARAMETER(ovsHdr);
+    UNREFERENCED_PARAMETER(tunnelKeyAttrOffset);
+
+    /* Get flow keys attributes */
+    if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
+                           nlFlowKeyPolicy, keyAttrs, ARRAY_SIZE(keyAttrs)))
+                           != TRUE) {
+        OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p",
+                       nlMsgHdr);
+        rc = NDIS_STATUS_FAILURE;
+        goto done;
+    }
+
+    if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
+        tunnelKeyAttrOffset = (UINT32)((PCHAR)
+                              (keyAttrs[OVS_KEY_ATTR_TUNNEL])
+                              - (PCHAR)nlMsgHdr);
+
+        OVS_LOG_ERROR("Parse Flow Tunnel Key Policy");
+
+        /* Get tunnel keys attributes */
+        if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
+                               NlAttrLen(keyAttr), nlFlowTunnelKeyPolicy,
+                               tunnelAttrs, ARRAY_SIZE(tunnelAttrs)))
+                               != TRUE) {
+            OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p",
+                           nlMsgHdr);
+            rc = NDIS_STATUS_FAILURE;
+            goto done;
+        }
+    }
+
+    _OvsFlowMapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
+                                mappedFlow);
+
+    /* Map the action */
+    mappedFlow->actionsLen = NlAttrGetSize(actionAttr);
+    mappedFlow->actions = NlAttrGet(actionAttr);
+    mappedFlow->dpNo = ovsHdr->dp_ifindex;

-    UNREFERENCED_PARAMETER(usrParamsCtx);
-    UNREFERENCED_PARAMETER(replyLen);
+    _OvsFlowMapNlToFlowPutFlags(genlMsgHdr, flowAttrClear,
+                                mappedFlow);

+done:
     return rc;
 }

 /*
  *----------------------------------------------------------------------------
+ *  _OvsFlowMapNlToFlowPutFlags --
+ *    Maps netlink message to OvsFlowPut->flags.
+ *----------------------------------------------------------------------------
+ */
+static VOID
+_OvsFlowMapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr, PNL_ATTR flowAttrClear,
+                            OvsFlowPut *mappedFlow)
+{
+    uint32_t flags = 0;
+
+    switch (genlMsgHdr->cmd) {
+    case OVS_FLOW_CMD_NEW:
+         flags |= OVSWIN_FLOW_PUT_CREATE;
+         break;
+    case OVS_FLOW_CMD_DEL:
+         flags |= OVSWIN_FLOW_PUT_DELETE;
+         break;
+    case OVS_FLOW_CMD_SET:
+         flags |= OVSWIN_FLOW_PUT_MODIFY;
+         break;
+    default:
+         ASSERT(0);
+    }
+
+    if (flowAttrClear) {
+        flags |= OVSWIN_FLOW_PUT_CLEAR;
+    }
+
+    mappedFlow->flags = flags;
+}
+
+/*
+ *----------------------------------------------------------------------------
+ *  _OvsFlowMapKeyAttrToFlowPut --
+ *    Converts FLOW_KEY attribute to OvsFlowPut->key.
+ *----------------------------------------------------------------------------
+ */
+static VOID
+_OvsFlowMapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
+                            PNL_ATTR *tunnelAttrs,
+                            OvsFlowPut *mappedFlow)
+{
+    const struct ovs_key_ethernet *eth_key;
+    OvsFlowKey *destKey = &(mappedFlow->key);
+
+    _OvsFlowMapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
+
+    /* ===== L2 headers ===== */
+    destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
+    eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
+    memcpy(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
+    memcpy(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
+
+    destKey->l2.dlType = ntohs((NlAttrGetU16(keyAttrs
+                          [OVS_KEY_ATTR_ETHERTYPE])));
+
+    if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
+        destKey->l2.vlanTci = NlAttrGetU16(keyAttrs
+                              [OVS_KEY_ATTR_VLAN]);
+    }
+
+    /* ==== L3 + L4. ==== */
+    destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
+                         - destKey->l2.offset;
+
+    switch (destKey->l2.dlType) {
+    case ETH_TYPE_IPV4: {
+        const struct ovs_key_ipv4 *ipv4Key;
+        const struct ovs_key_tcp *tcpKey;
+
+        ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]);
+
+        IpKey *ipv4FlowPutKey = &(destKey->ipKey);
+
+        ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src;
+        ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst;
+        ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto;
+        ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos;
+        ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl;
+        ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag;
+
+        if (keyAttrs[OVS_KEY_ATTR_TCP]) {
+            tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
+            ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
+            ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
+        }
+
+        destKey->l2.keyLen += OVS_IP_KEY_SIZE;
+        break;
+    }
+    case ETH_TYPE_IPV6: {
+        const struct ovs_key_ipv6 *ipv6Key;
+        const struct ovs_key_tcp *tcpKey;
+
+        ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]);
+
+        Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key);
+
+        memcpy(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src, sizeof 
ipv6Key->ipv6_src);
+        memcpy(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst, sizeof 
ipv6Key->ipv6_dst);
+        ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label;
+        ipv6FlowPutKey->nwProto  = ipv6Key->ipv6_proto;
+        ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass;
+        ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit;
+
+        ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag;
+
+        if (keyAttrs[OVS_KEY_ATTR_TCP]) {
+            tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]);
+            ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src;
+            ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst;
+        }
+
+        ipv6FlowPutKey->pad = 0;
+
+        if (ipv6Key->ipv6_proto == IPPROTO_ICMPV6) {
+            const struct ovs_key_nd *ndKey;
+            Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key);
+
+            ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]);
+
+            memcpy(&icmp6FlowPutKey->ndTarget, ndKey->nd_target,
+                   sizeof (icmp6FlowPutKey->ndTarget));
+            memcpy(icmp6FlowPutKey->arpSha, ndKey->nd_sll, ETH_ADDR_LEN);
+            memcpy(icmp6FlowPutKey->arpTha, ndKey->nd_tll, ETH_ADDR_LEN);
+
+            destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE;
+        } else {
+            destKey->l2.keyLen += OVS_IPV6_KEY_SIZE;
+        }
+        break;
+    }
+    case ETH_TYPE_ARP:
+    case ETH_TYPE_RARP: {
+        ArpKey *arpFlowPutKey = &destKey->arpKey;
+        const struct ovs_key_arp *arpKey;
+
+        arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
+
+        arpFlowPutKey->nwSrc = arpKey->arp_sip;
+        arpFlowPutKey->nwDst = arpKey->arp_tip;
+
+        memcpy(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
+        memcpy(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
+        arpFlowPutKey->nwProto = (UINT8)(arpKey->arp_op);
+        arpFlowPutKey->pad[0] = 0;
+        arpFlowPutKey->pad[1] = 0;
+        arpFlowPutKey->pad[2] = 0;
+        destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
+        break;
+    }
+    }
+}
+
+/*
+ *----------------------------------------------------------------------------
+ *  _OvsFlowMapTunAttrToFlowPut --
+ *    Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey.
+ *----------------------------------------------------------------------------
+ */
+static VOID
+_OvsFlowMapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
+                            PNL_ATTR *tunAttrs,
+                            OvsFlowKey *destKey)
+{
+    if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
+        destKey->tunKey.tunnelId = NlAttrGetU64
+                                   (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]);
+        destKey->tunKey.dst = NlAttrGetU32
+                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
+        destKey->tunKey.src = NlAttrGetU32
+                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
+
+        /* XXX: There are no attributes to specify tunnel flags.
+         * Also, i do not see these flags being used anywhere in
+         * flowPut code. */
+        destKey->tunKey.flags = 0;
+        destKey->tunKey.tos = NlAttrGetU8
+                                 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]);
+        destKey->tunKey.ttl = NlAttrGetU8
+                                 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]);
+        destKey->tunKey.pad = 0;
+        destKey->l2.offset = 0;
+    } else {
+        destKey->tunKey.attr[0] = 0;
+        destKey->tunKey.attr[1] = 0;
+        destKey->tunKey.attr[2] = 0;
+        destKey->l2.offset = sizeof destKey->tunKey;
+    }
+}
+
+/*
+ *----------------------------------------------------------------------------
  * OvsDeleteFlowTable --
  * Results:
  *    NDIS_STATUS_SUCCESS always.
@@ -837,13 +1196,10 @@ ReportFlowInfo(OvsFlow *flow,
 NTSTATUS
 OvsPutFlowIoctl(PVOID inputBuffer,
                 UINT32 inputLength,
-                PVOID outputBuffer,
-                UINT32 outputLength,
-                UINT32 *replyLen)
+                struct OvsFlowStats *stats)
 {
     NTSTATUS status = STATUS_SUCCESS;
     OVS_DATAPATH *datapath = NULL;
-    struct OvsFlowStats stats;
     ULONG actionsLen;
     OvsFlowPut *put;
     UINT32 dpNo;
@@ -853,19 +1209,12 @@ OvsPutFlowIoctl(PVOID inputBuffer,
         return STATUS_INFO_LENGTH_MISMATCH;
     }

-    if ((outputLength != sizeof(stats)) || (outputBuffer == NULL)) {
-        return STATUS_INFO_LENGTH_MISMATCH;
-    }
-
     put = (OvsFlowPut *)inputBuffer;
     if (put->actionsLen > 0) {
         actionsLen = put->actionsLen;
     } else {
         actionsLen = 0;
     }
-    if (inputLength != actionsLen + sizeof(*put)) {
-        return STATUS_INFO_LENGTH_MISMATCH;
-    }

     dpNo = put->dpNo;
     NdisAcquireSpinLock(gOvsCtrlLock);
@@ -877,17 +1226,10 @@ OvsPutFlowIoctl(PVOID inputBuffer,

     datapath = &gOvsSwitchContext->datapath;
     ASSERT(datapath);
-    RtlZeroMemory(&stats, sizeof(stats));
     OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
-    status = HandleFlowPut(put, datapath, &stats);
+    status = HandleFlowPut(put, datapath, stats);
     OvsReleaseDatapath(datapath, &dpLockState);

-    if (status == STATUS_SUCCESS) {
-        // Copy stats to User mode app
-        NdisMoveMemory(outputBuffer, (PVOID)&stats, sizeof(stats));
-        *replyLen = sizeof stats;
-    }
-
 unlock:
     NdisReleaseSpinLock(gOvsCtrlLock);
     return status;
diff --git a/datapath-windows/ovsext/Flow.h b/datapath-windows/ovsext/Flow.h
index 602e567..e62ba40 100644
--- a/datapath-windows/ovsext/Flow.h
+++ b/datapath-windows/ovsext/Flow.h
@@ -64,16 +64,14 @@ NTSTATUS OvsDumpFlowIoctl(PVOID inputBuffer, UINT32 
inputLength,
                           PVOID outputBuffer, UINT32 outputLength,
                           UINT32 *replyLen);
 NTSTATUS OvsPutFlowIoctl(PVOID inputBuffer, UINT32 inputLength,
-                         PVOID outputBuffer, UINT32 outputLength,
-                         UINT32 *replyLen);
+                         struct OvsFlowStats *stats);
 NTSTATUS OvsGetFlowIoctl(PVOID inputBuffer, UINT32 inputLength,
                          PVOID outputBuffer, UINT32 outputLength,
                          UINT32 *replyLen);
 NTSTATUS OvsFlushFlowIoctl(PVOID inputBuffer, UINT32 inputLength);

 NTSTATUS OvsFlowNlNewCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
-                                 UINT32 *replyLen);
-
+                                UINT32 *replyLen);

 /* Flags for tunneling */
 #define OVS_TNL_F_DONT_FRAGMENT         (1 << 0)
--
1.9.1


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

Reply via email to