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

-----Original Message-----
From: dev <dev-boun...@openvswitch.org> on behalf of Sorin Vinturis
<svintu...@cloudbasesolutions.com>
Date: Wednesday, June 1, 2016 at 8:50 AM
To: "dev@openvswitch.org" <dev@openvswitch.org>
Subject: [ovs-dev] [PATCH v2] datapath-windows: Sample action support.

>This patch adds support for sampling to the OVS extension.
>
>The following flow was used for generating sample actions:
>  ovs-ofctl add-flow tcp:127.0.0.1:9999 "actions=sample(
>    probability=12345,collector_set_id=23456,obs_domain_id=34567,
>    obs_point_id=45678)"
>
>Signed-off-by: Sorin Vinturis <svintu...@cloudbasesolutions.com>
>---
>v2: Moved random functions to Util.h and removed Random.h.
>---
> datapath-windows/ovsext/Actions.c | 181
>+++++++++++++++++++++++++++++++-------
> datapath-windows/ovsext/Util.h    |  27 ++++++
> 2 files changed, 175 insertions(+), 33 deletions(-)
>
>diff --git a/datapath-windows/ovsext/Actions.c
>b/datapath-windows/ovsext/Actions.c
>index 4edf7d0..1e894eb 100644
>--- a/datapath-windows/ovsext/Actions.c
>+++ b/datapath-windows/ovsext/Actions.c
>@@ -1596,6 +1596,131 @@ OvsExecuteHash(OvsFlowKey *key,
>         hash = 1;
> 
>     key->dpHash = hash;
>+}
>+
>+/*
>+ * 
>--------------------------------------------------------------------------
>+ * OvsOutputUserspaceAction --
>+ *      This function sends the packet to userspace according to nested
>+ *      %OVS_USERSPACE_ATTR_* attributes.
>+ * 
>--------------------------------------------------------------------------
>+ */
>+static __inline NDIS_STATUS
>+OvsOutputUserspaceAction(OvsForwardingContext *ovsFwdCtx,
>+                         OvsFlowKey *key,
>+                         const PNL_ATTR attr)
>+{
>+    NTSTATUS status = NDIS_STATUS_SUCCESS;
>+    PNL_ATTR userdataAttr;
>+    PNL_ATTR queueAttr;
>+    POVS_PACKET_QUEUE_ELEM elem;
>+    POVS_PACKET_HDR_INFO layers = &ovsFwdCtx->layers;
>+    BOOLEAN isRecv = FALSE;
>+
>+    POVS_VPORT_ENTRY vport =
>OvsFindVportByPortNo(ovsFwdCtx->switchContext,
>+                                                  ovsFwdCtx->srcVportNo);
>+
>+    if (vport) {
>+        if (vport->isExternal ||
>+            OvsIsTunnelVportType(vport->ovsType)) {
>+            isRecv = TRUE;
>+        }
>+    }
>+
>+    queueAttr = NlAttrFindNested(attr, OVS_USERSPACE_ATTR_PID);
>+    userdataAttr = NlAttrFindNested(attr, OVS_USERSPACE_ATTR_USERDATA);
>+
>+    elem = OvsCreateQueueNlPacket(NlAttrData(userdataAttr),
>+                                  NlAttrGetSize(userdataAttr),
>+                                  OVS_PACKET_CMD_ACTION,
>+                                  vport, key, ovsFwdCtx->curNbl,
>+                 
>NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl),
>+                                  isRecv,
>+                                  layers);
>+    if (elem) {
>+        LIST_ENTRY missedPackets;
>+        InitializeListHead(&missedPackets);
>+        InsertTailList(&missedPackets, &elem->link);
>+        OvsQueuePackets(&missedPackets, 1);
>+    } else {
>+        status = NDIS_STATUS_FAILURE;
>+    }
>+
>+    return status;
>+}
>+
>+/*
>+ * 
>--------------------------------------------------------------------------
>+ * OvsExecuteSampleAction --
>+ *      Executes actions based on probability, as specified in the nested
>+ *      %OVS_SAMPLE_ATTR_* attributes.
>+ * 
>--------------------------------------------------------------------------
>+ */
>+static __inline NDIS_STATUS
>+OvsExecuteSampleAction(OvsForwardingContext *ovsFwdCtx,
>+                       OvsFlowKey *key,
>+                       const PNL_ATTR attr)
>+{
>+    PNET_BUFFER_LIST newNbl = NULL;
>+    PNL_ATTR actionsList = NULL;
>+    PNL_ATTR a = NULL;
>+    INT rem = 0;
>+
>+    SRand();
>+    NL_ATTR_FOR_EACH_UNSAFE(a, rem, NlAttrData(attr),
>NlAttrGetSize(attr)) {
>+        switch (NlAttrType(a)) {
>+        case OVS_SAMPLE_ATTR_PROBABILITY:
>+        {
>+            UINT32 probability = NlAttrGetU32(a);
>+
>+            if (!probability || Rand() > probability) {
>+                return 0;
>+            }
>+            break;
>+        }
>+        case OVS_SAMPLE_ATTR_ACTIONS:
>+            actionsList = a;
>+            break;
>+        }
>+    }
>+
>+    if (actionsList) {
>+        rem = NlAttrGetSize(actionsList);
>+        a = (PNL_ATTR)NlAttrData(actionsList);
>+    }
>+
>+    if (!rem) {
>+        /* Actions list is empty, do nothing */
>+        return STATUS_SUCCESS;
>+    }
>+
>+    /*
>+     * The only known usage of sample action is having a single
>user-space
>+     * action. Treat this usage as a special case.
>+     */
>+    if (NlAttrType(a) == OVS_ACTION_ATTR_USERSPACE &&
>+        NlAttrIsLast(a, rem)) {
>+        return OvsOutputUserspaceAction(ovsFwdCtx, key, a);
>+    }
>+
>+    newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext,
>ovsFwdCtx->curNbl,
>+                               0, 0, TRUE /*copy NBL info*/);
>+    if (newNbl == NULL) {
>+        /*
>+         * Skip the sample action when out of memory, but continue on
>with the
>+         * rest of the action list.
>+         */
>+        ovsActionStats.noCopiedNbl++;
>+        return STATUS_SUCCESS;
>+    }
>+
>+    if (!OvsAddDeferredActions(newNbl, key, a)) {
>+        OVS_LOG_INFO(
>+            "Deferred actions limit reached, dropping sample action.");
>+        OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE);
>+    }
>+
>+    return STATUS_SUCCESS;
> }
> 
> /*
>@@ -1838,43 +1963,15 @@ OvsDoExecuteActions(POVS_SWITCH_CONTEXT
>switchContext,
> 
>         case OVS_ACTION_ATTR_USERSPACE:
>         {
>-            PNL_ATTR userdataAttr;
>-            PNL_ATTR queueAttr;
>-            POVS_PACKET_QUEUE_ELEM elem;
>-            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);
>-
>-            elem = OvsCreateQueueNlPacket((PVOID)userdataAttr,
>-                                    userdataAttr->nlaLen,
>-                                    OVS_PACKET_CMD_ACTION,
>-                                    vport, key, ovsFwdCtx.curNbl,
>-                 
>NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx.curNbl),
>-                                    isRecv,
>-                                    layers);
>-            if (elem) {
>-                LIST_ENTRY missedPackets;
>-                InitializeListHead(&missedPackets);
>-                InsertTailList(&missedPackets, &elem->link);
>-                OvsQueuePackets(&missedPackets, 1);
>-                dropReason = L"OVS-Completed since packet was copied to "
>-                             L"userspace";
>-            } else {
>+            status = OvsOutputUserspaceAction(&ovsFwdCtx, key,
>+                                              (const PNL_ATTR)a);
>+            if (status != NDIS_STATUS_SUCCESS) {
>                 dropReason = L"OVS-Dropped due to failure to queue to "
>                              L"userspace";
>                 goto dropit;
>             }
>+            dropReason = L"OVS-Completed since packet was copied to "
>+                         L"userspace";
>             break;
>         }
>         case OVS_ACTION_ATTR_SET:
>@@ -1898,6 +1995,24 @@ OvsDoExecuteActions(POVS_SWITCH_CONTEXT
>switchContext,
>             break;
>         }
>         case OVS_ACTION_ATTR_SAMPLE:
>+        {
>+            if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic
>!= NULL
>+                || ovsFwdCtx.tunnelRxNic != NULL) {
>+                status = OvsOutputBeforeSetAction(&ovsFwdCtx);
>+                if (status != NDIS_STATUS_SUCCESS) {
>+                    dropReason = L"OVS-adding destination failed";
>+                    goto dropit;
>+                }
>+            }
>+
>+            status = OvsExecuteSampleAction(&ovsFwdCtx, key,
>+                                            (const PNL_ATTR)a);
>+            if (status != NDIS_STATUS_SUCCESS) {
>+                dropReason = L"OVS-sample action failed";
>+                goto dropit;
>+            }
>+            break;
>+        }
>         default:
>             status = NDIS_STATUS_NOT_SUPPORTED;
>             break;
>diff --git a/datapath-windows/ovsext/Util.h
>b/datapath-windows/ovsext/Util.h
>index 4bcde3b..bcd38dd 100644
>--- a/datapath-windows/ovsext/Util.h
>+++ b/datapath-windows/ovsext/Util.h
>@@ -113,4 +113,31 @@ OvsPerCpuDataInit();
> VOID
> OvsPerCpuDataCleanup();
> 
>+static LARGE_INTEGER seed;
>+
>+/*
>+ 
>*-------------------------------------------------------------------------
>---
>+ *  SRand --
>+ *    This function sets the starting seed value for the pseudorandom
>number
>+ *    generator.
>+ 
>*-------------------------------------------------------------------------
>---
>+ */
>+static __inline
>+VOID SRand()
>+{
>+    KeQuerySystemTime(&seed);
>+}
>+
>+/*
>+ 
>*-------------------------------------------------------------------------
>---
>+ *  Rand --
>+ *    This function generates a pseudorandom number between 0 to
>UINT_MAX.
>+ 
>*-------------------------------------------------------------------------
>---
>+ */
>+static __inline
>+UINT32 Rand()
>+{
>+    return seed.LowPart *= 0x8088405 + 1;
>+}
>+
> #endif /* __UTIL_H_ */
>-- 
>1.9.0.msysgit.0
>_______________________________________________
>dev mailing list
>dev@openvswitch.org
>https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailma
>n_listinfo_dev&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=pN
>HQcdr7B40b4h6Yb7FIedI1dnBsxdDuTLBYD3JqV80&m=p0xyPE9NNSVKxNSdJT_xtx2SsWQyL7
>t17RcyK2oAL4U&s=q_Hy9n6rNMc-cu5YjuUzuks_f79tZEPg_w5WsvSQY4s&e= 

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

Reply via email to