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