[ovs-dev] [PATCH 1/6] ofp-actions: Add the NXAST_SAMPLE vendor action

Romain Lenglet rlenglet at vmware.com
Tue Mar 26 01:33:02 UTC 2013


Define NXAST_SAMPLE OpenFlow vendor action and the corresponding
OFPACT_SAMPLE OVS action, to do per-flow packet sampling.

Signed-off-by: Romain Lenglet <rlenglet at vmware.com>
---
 FAQ                           |  13 ++--
 NEWS                          |   1 +
 WHY-OVS                       |  17 ++---
 debian/control                | 160 +++++++++++++++++++++---------------------
 include/openflow/nicira-ext.h |  26 +++++++
 lib/ofp-actions.c             |  57 +++++++++++++++
 lib/ofp-actions.h             |  12 ++++
 lib/ofp-parse.c               |  34 +++++++++
 lib/ofp-util.def              |   1 +
 ofproto/ofproto-dpif.c        |   4 ++
 tests/ofp-actions.at          |   6 ++
 tests/ovs-ofctl.at            |  10 +++
 utilities/ovs-ofctl.8.in      |  25 +++++++
 13 files changed, 272 insertions(+), 94 deletions(-)

diff --git a/FAQ b/FAQ
index 6d43e72..24502e7 100644
--- a/FAQ
+++ b/FAQ
@@ -9,12 +9,13 @@ General
 Q: What is Open vSwitch?
 
 A: Open vSwitch is a production quality open source software switch
-   designed to be used as a vswitch in virtualized server environments.  A
-   vswitch forwards traffic between different VMs on the same physical host
-   and also forwards traffic between VMs and the physical network.  Open
-   vSwitch supports standard management interfaces (e.g. sFlow, NetFlow,
-   RSPAN, CLI), and is open to programmatic extension and control using
-   OpenFlow and the OVSDB management protocol.
+   designed to be used as a vswitch in virtualized server
+   environments.  A vswitch forwards traffic between different VMs on
+   the same physical host and also forwards traffic between VMs and
+   the physical network.  Open vSwitch supports standard management
+   interfaces (e.g. sFlow, NetFlow, IPFIX, RSPAN, CLI), and is open to
+   programmatic extension and control using OpenFlow and the OVSDB
+   management protocol.
 
    Open vSwitch as designed to be compatible with modern switching
    chipsets.  This means that it can be ported to existing high-fanout
diff --git a/NEWS b/NEWS
index cbbe06b..b9231f9 100644
--- a/NEWS
+++ b/NEWS
@@ -76,6 +76,7 @@ v1.10.0 - xx xxx xxxx
         retire that meaning of ANY in favor of the OpenFlow 1.1 meaning.
     - Patch ports no longer require kernel support, so they now work
       with FreeBSD and the kernel module built into Linux 3.3 and later.
+    - New "sample" action.
 
 
 v1.9.0 - 26 Feb 2013
diff --git a/WHY-OVS b/WHY-OVS
index e8c6f75..f5f47ff 100644
--- a/WHY-OVS
+++ b/WHY-OVS
@@ -21,7 +21,7 @@ vSwitch cope with the above requirements.
   migratable between different hosts.  This may include traditional
   "soft state" (such as an entry in an L2 learning table), L3 forwarding
   state, policy routing state, ACLs, QoS policy, monitoring
-  configuration (e.g. NetFlow, sFlow), etc.
+  configuration (e.g. NetFlow, IPFIX, sFlow), etc.
 
   Open vSwitch has support for both configuring and migrating both slow
   (configuration) and fast network state between instances.  For
@@ -38,13 +38,14 @@ vSwitch cope with the above requirements.
   environments, and so forth.
 
   Open vSwitch supports a number of features that allow a network
-  control system to respond and adapt as the environment changes.  This
-  includes simple accounting and visibility support such as NetFlow and
-  sFlow.  But perhaps more useful, Open vSwitch supports a network state
-  database (OVSDB) that supports remote triggers.  Therefore, a piece of
-  orchestration software can "watch" various aspects of the network and
-  respond if/when they change.  This is used heavily today, for example,
-  to respond to and track VM migrations.
+  control system to respond and adapt as the environment changes.
+  This includes simple accounting and visibility support such as
+  NetFlow, IPFIX, and sFlow.  But perhaps more useful, Open vSwitch
+  supports a network state database (OVSDB) that supports remote
+  triggers.  Therefore, a piece of orchestration software can "watch"
+  various aspects of the network and respond if/when they change.
+  This is used heavily today, for example, to respond to and track VM
+  migrations.
 
   Open vSwitch also supports OpenFlow as a method of exporting remote
   access to control traffic.  There are a number of uses for this
diff --git a/debian/control b/debian/control
index acf47b9..60396bb 100644
--- a/debian/control
+++ b/debian/control
@@ -4,7 +4,7 @@ Priority: extra
 Maintainer: Open vSwitch developers <dev at openvswitch.org>
 Uploaders: Ben Pfaff <pfaffben at debian.org>, Simon Horman <horms at debian.org>
 Build-Depends:
- debhelper (>= 8), autoconf (>= 2.64), automake (>= 1.10) | automake1.10, 
+ debhelper (>= 8), autoconf (>= 2.64), automake (>= 1.10) | automake1.10,
  libssl-dev, pkg-config (>= 0.21), bzip2, openssl,
  python-all (>= 2.6.6-3~), procps, python-qt4,
  python-zopeinterface, python-twisted-conch
@@ -16,13 +16,13 @@ Architecture: all
 Depends: module-assistant, bzip2, debhelper (>= 5.0.37), ${misc:Depends}
 Suggests: openvswitch-switch
 Description: Open vSwitch datapath module source - module-assistant version
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package provides the Open vSwitch datapath module source code
  that is needed by openvswitch-switch.  The kernel module can be built
@@ -33,13 +33,13 @@ Package: openvswitch-datapath-dkms
 Architecture: all
 Depends: dkms (>= 1.95), make, libc6-dev, ${misc:Depends}, ${python:Depends}
 Description: Open vSwitch datapath module source - DKMS version
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package provides the Open vSwitch datapath module source code
  that is needed by openvswitch-switch.  DKMS can built the kernel
@@ -52,13 +52,13 @@ Depends:
  python (>= 2.7) | python-argparse
 Suggests: ethtool
 Description: Open vSwitch common components
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  openvswitch-common provides components required by both openvswitch-switch
  and openvswitch-controller.
@@ -68,34 +68,34 @@ Architecture: linux-any
 Suggests: openvswitch-datapath-module
 Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, openvswitch-common (= ${binary:Version}), module-init-tools, procps, uuid-runtime, netbase
 Description: Open vSwitch switch implementations
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  openvswitch-switch provides the userspace components and utilities for
- the Open vSwitch kernel-based switch.  
+ the Open vSwitch kernel-based switch.
 
 Package: openvswitch-ipsec
 Architecture: linux-any
 Depends:
  ${shlibs:Depends}, ${misc:Depends}, python,
- ipsec-tools (>=0.8~alpha20101208), 
+ ipsec-tools (>=0.8~alpha20101208),
  racoon (>=0.8~alpha20101208),
  openvswitch-common (= ${binary:Version}),
  openvswitch-switch (= ${binary:Version}),
  python-openvswitch (= ${source:Version})
 Description: Open vSwitch GRE-over-IPsec support
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  The ovs-monitor-ipsec script provides support for encrypting GRE
  tunnels with IPsec.
@@ -106,13 +106,13 @@ Depends:
  ${misc:Depends}, openvswitch-common (>= ${source:Version}),
  openvswitch-common (<< ${source:Version}.1~)
 Description: Open vSwitch public key infrastructure dependency package
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  openvswitch-pki provides PKI (public key infrastructure) support for
  Open vSwitch switches and controllers, reducing the risk of
@@ -124,13 +124,13 @@ Depends:
  ${shlibs:Depends}, openvswitch-common (= ${binary:Version}),
  openvswitch-pki (= ${source:Version}), ${misc:Depends}
 Description: Open vSwitch controller implementation
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  The Open vSwitch controller enables OpenFlow switches that connect to it
  to act as MAC-learning Ethernet switches.
@@ -144,13 +144,13 @@ Depends:
  openvswitch-controller (= ${binary:Version}),
  openvswitch-switch (= ${binary:Version})
 Description: Debug symbols for Open vSwitch packages
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package contains the debug symbols for all the other openvswitch-*
  packages.  Install it to debug one of them or to examine a core dump
@@ -161,13 +161,13 @@ Architecture: all
 Section: python
 Depends: ${misc:Depends}, ${python:Depends}
 Description: Python bindings for Open vSwitch
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package contains the full Python bindings for Open vSwitch database.
 
@@ -176,13 +176,13 @@ Architecture: all
 Section: utils
 Depends: ${python:Depends}, python-openvswitch, ${misc:Depends}
 Description: Open vSwitch graphical monitoring tool
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package is a GUI tool for monitoring and troubleshooting local
  or remote Open vSwitch installations.  It presents GUI tables that
@@ -194,13 +194,13 @@ Package: openvswitch-test
 Architecture: all
 Depends: ${misc:Depends}, ${python:Depends}, python-twisted-web, python (>= 2.7) | python-argparse
 Description: Open vSwitch test package
- Open vSwitch is a production quality, multilayer, software-based, Ethernet
- virtual switch. It is designed to enable massive network automation through
- programmatic extension, while still supporting standard management interfaces
- and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In
- addition, it is designed to support distribution across multiple physical
- servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus
- 1000V.
+ Open vSwitch is a production quality, multilayer, software-based,
+ Ethernet virtual switch. It is designed to enable massive network
+ automation through programmatic extension, while still supporting
+ standard management interfaces and protocols (e.g. NetFlow, IPFIX,
+ sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed
+ to support distribution across multiple physical servers similar to
+ VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V.
  .
  This package contains utilities that are useful to diagnose
  performance and connectivity issues in Open vSwitch setup.
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 54fc4f9..230f870 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -312,6 +312,7 @@ enum nx_action_subtype {
     NXAST_DEC_MPLS_TTL,         /* struct nx_action_header */
     NXAST_STACK_PUSH,           /* struct nx_action_stack */
     NXAST_STACK_POP,            /* struct nx_action_stack */
+    NXAST_SAMPLE,               /* struct nx_action_sample */
 };
 
 /* Header for Nicira-defined actions. */
@@ -2233,4 +2234,29 @@ struct nx_action_mpls_ttl {
 };
 OFP_ASSERT(sizeof(struct nx_action_mpls_ttl) == 16);
 
+/* Action structure for NXAST_SAMPLE.
+ *
+ * Samples matching packets with the given probability and sends them
+ * each to the set of collectors identified with the given ID.  The
+ * probability is expressed as a number of packets to be sampled out
+ * of USHRT_MAX packets, and must be >0.
+ *
+ * When sending packet samples to IPFIX collectors, the IPFIX flow
+ * record sent for each sampled packet is associated with the given
+ * observation domain ID and observation point ID.  Each IPFIX flow
+ * record contain the sampled packet's headers when executing this
+ * rule.  If a sampled packet's headers are modified by previous
+ * actions in the flow, those modified headers are sent. */
+struct nx_action_sample {
+    ovs_be16 type;                  /* OFPAT_VENDOR. */
+    ovs_be16 len;                   /* Length is 16. */
+    ovs_be32 vendor;                /* NX_VENDOR_ID. */
+    ovs_be16 subtype;               /* NXAST_SAMPLE. */
+    ovs_be16 probability;           /* Fraction of packets to sample. */
+    ovs_be32 collector_set_id;      /* ID of collector set in OVSDB. */
+    ovs_be32 obs_domain_id;         /* ID of sampling observation domain. */
+    ovs_be32 obs_point_id;          /* ID of sampling observation point. */
+};
+OFP_ASSERT(sizeof(struct nx_action_sample) == 24);
+
 #endif /* openflow/nicira-ext.h */
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index d405d2d..fc47e26 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -218,6 +218,25 @@ dec_ttl_cnt_ids_from_openflow(const struct nx_action_cnt_ids *nac_ids,
 }
 
 static enum ofperr
+sample_from_openflow(const struct nx_action_sample *nas,
+                     struct ofpbuf *out)
+{
+    struct ofpact_sample *sample;
+
+    sample = ofpact_put_SAMPLE(out);
+    sample->probability = ntohs(nas->probability);
+    sample->collector_set_id = ntohl(nas->collector_set_id);
+    sample->obs_domain_id = ntohl(nas->obs_domain_id);
+    sample->obs_point_id = ntohl(nas->obs_point_id);
+
+    if (sample->probability == 0) {
+        return OFPERR_OFPBAC_BAD_ARGUMENT;
+    }
+
+    return 0;
+}
+
+static enum ofperr
 decode_nxast_action(const union ofp_action *a, enum ofputil_action_code *code)
 {
     const struct nx_action_header *nah = (const struct nx_action_header *) a;
@@ -434,6 +453,11 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
         ofpact_put_POP_MPLS(out)->ethertype = nxapm->ethertype;
         break;
     }
+
+    case OFPUTIL_NXAST_SAMPLE:
+        error = sample_from_openflow(
+            (const struct nx_action_sample *) a, out);
+        break;
     }
 
     return error;
@@ -1199,6 +1223,9 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
         *dl_type = ofpact_get_POP_MPLS(a)->ethertype;
         return 0;
 
+    case OFPACT_SAMPLE:
+        return 0;
+
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_WRITE_METADATA:
     case OFPACT_GOTO_TABLE:
@@ -1394,6 +1421,19 @@ ofpact_fin_timeout_to_nxast(const struct ofpact_fin_timeout *fin_timeout,
 }
 
 static void
+ofpact_sample_to_nxast(const struct ofpact_sample *os,
+                             struct ofpbuf *out)
+{
+    struct nx_action_sample *nas;
+
+    nas = ofputil_put_NXAST_SAMPLE(out);
+    nas->probability = htons(os->probability);
+    nas->collector_set_id = ntohl(os->collector_set_id);
+    nas->obs_domain_id = ntohl(os->obs_domain_id);
+    nas->obs_point_id = htonl(os->obs_point_id);
+}
+
+static void
 ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
 {
     switch (a->type) {
@@ -1489,6 +1529,10 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
             ofpact_get_POP_MPLS(a)->ethertype;
         break;
 
+    case OFPACT_SAMPLE:
+        ofpact_sample_to_nxast(ofpact_get_SAMPLE(a), out);
+        break;
+
     case OFPACT_OUTPUT:
     case OFPACT_ENQUEUE:
     case OFPACT_SET_VLAN_VID:
@@ -1621,6 +1665,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_EXIT:
     case OFPACT_PUSH_MPLS:
     case OFPACT_POP_MPLS:
+    case OFPACT_SAMPLE:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -1784,6 +1829,7 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_MULTIPATH:
     case OFPACT_NOTE:
     case OFPACT_EXIT:
+    case OFPACT_SAMPLE:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -1912,6 +1958,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
     case OFPACT_EXIT:
     case OFPACT_PUSH_MPLS:
     case OFPACT_POP_MPLS:
+    case OFPACT_SAMPLE:
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_GOTO_TABLE:
     default:
@@ -2003,6 +2050,7 @@ ofpact_format(const struct ofpact *a, struct ds *s)
     const struct ofpact_controller *controller;
     const struct ofpact_metadata *metadata;
     const struct ofpact_tunnel *tunnel;
+    const struct ofpact_sample *sample;
     uint16_t port;
 
     switch (a->type) {
@@ -2204,6 +2252,15 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         ds_put_cstr(s, "exit");
         break;
 
+    case OFPACT_SAMPLE:
+        sample = ofpact_get_SAMPLE(a);
+        ds_put_format(
+            s, "sample(probability=%"PRIu16",collector_set_id=%"PRIu32
+            ",obs_domain_id=%"PRIu32",obs_point_id=%"PRIu32")",
+            sample->probability, sample->collector_set_id,
+            sample->obs_domain_id, sample->obs_point_id);
+        break;
+
     case OFPACT_CLEAR_ACTIONS:
         ds_put_format(s, "%s",
                       ofpact_instruction_name_from_type(
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 0189c8a..ffceb05 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -94,6 +94,7 @@
     /* Other. */                                                    \
     DEFINE_OFPACT(NOTE,            ofpact_note,          data)      \
     DEFINE_OFPACT(EXIT,            ofpact_null,          ofpact)    \
+    DEFINE_OFPACT(SAMPLE,          ofpact_sample,        ofpact)    \
                                                                     \
     /* Instructions */                                              \
     /* XXX Write-Actions */                                         \
@@ -441,6 +442,17 @@ struct ofpact_note {
     uint8_t data[];
 };
 
+/* OFPACT_SAMPLE.
+ *
+ * Used for NXAST_SAMPLE. */
+struct ofpact_sample {
+    struct ofpact ofpact;
+    uint16_t probability;  // Always >0.
+    uint32_t collector_set_id;
+    uint32_t obs_domain_id;
+    uint32_t obs_point_id;
+};
+
 /* OFPACT_DEC_TTL.
  *
  * Used for OFPAT11_DEC_NW_TTL, NXAST_DEC_TTL and NXAST_DEC_TTL_CNT_IDS. */
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index e8abc9f..f1b97af 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -390,6 +390,34 @@ parse_metadata(struct ofpbuf *b, char *arg)
 }
 
 static void
+parse_sample(struct ofpbuf *b, char *arg)
+{
+    struct ofpact_sample *os = ofpact_put_SAMPLE(b);
+    char *key, *value;
+
+    while (ofputil_parse_key_value(&arg, &key, &value)) {
+        if (!strcmp(key, "probability")) {
+            os->probability = str_to_u16(value, "probability");
+            if (os->probability == 0) {
+                ovs_fatal(0, "invalid probability value \"%s\"", value);
+            }
+        } else if (!strcmp(key, "collector_set_id")) {
+            os->collector_set_id = str_to_u32(value);
+        } else if (!strcmp(key, "obs_domain_id")) {
+            os->obs_domain_id = str_to_u32(value);
+        } else if (!strcmp(key, "obs_point_id")) {
+            os->obs_point_id = str_to_u32(value);
+        } else {
+            ovs_fatal(0, "invalid key \"%s\" in \"sample\" argument",
+                      key);
+        }
+    }
+    if (os->probability == 0) {
+        ovs_fatal(0, "non-zero \"probability\" must be specified on sample");
+    }
+}
+
+static void
 parse_named_action(enum ofputil_action_code code, const struct flow *flow,
                    char *arg, struct ofpbuf *ofpacts)
 {
@@ -591,12 +619,18 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
         ofpact_put_POP_MPLS(ofpacts)->ethertype =
             htons(str_to_u16(arg, "pop_mpls"));
         break;
+
     case OFPUTIL_NXAST_STACK_PUSH:
         nxm_parse_stack_action(ofpact_put_STACK_PUSH(ofpacts), arg);
         break;
     case OFPUTIL_NXAST_STACK_POP:
         nxm_parse_stack_action(ofpact_put_STACK_POP(ofpacts), arg);
         break;
+
+
+    case OFPUTIL_NXAST_SAMPLE:
+        parse_sample(ofpacts, arg);
+        break;
     }
 }
 
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index b7dde48..d88d420 100644
--- a/lib/ofp-util.def
+++ b/lib/ofp-util.def
@@ -71,6 +71,7 @@ NXAST_ACTION(NXAST_SET_MPLS_TTL,    nx_action_mpls_ttl,     0, "set_mpls_ttl")
 NXAST_ACTION(NXAST_DEC_MPLS_TTL,    nx_action_header,       0, "dec_mpls_ttl")
 NXAST_ACTION(NXAST_PUSH_MPLS,       nx_action_push_mpls,    0, "push_mpls")
 NXAST_ACTION(NXAST_POP_MPLS,        nx_action_pop_mpls,     0, "pop_mpls")
+NXAST_ACTION(NXAST_SAMPLE,          nx_action_sample,       0, "sample")
 
 #undef OFPAT10_ACTION
 #undef OFPAT11_ACTION
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index b8db91d..99161d9 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -6623,6 +6623,10 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             }
             break;
         }
+
+        case OFPACT_SAMPLE:
+            /* TODO: Actually implement the translation here. */
+            break;
         }
     }
 
diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at
index 8a40eb4..2ecbdb5 100644
--- a/tests/ofp-actions.at
+++ b/tests/ofp-actions.at
@@ -114,6 +114,9 @@ ffff 0010 00002320 0014 04d2 162e 02 00
 # actions=dec_ttl(32768,12345,90,765,1024)
 ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000
 
+# actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+ffff 0018 00002320 001d 3039 00005BA0 00008707 0000B26E
+
 ])
 sed '/^[[#&]]/d' < test-data > input.txt
 sed -n 's/^# //p; /^$/p' < test-data > expout
@@ -289,6 +292,9 @@ ffff 0010 00002320 0014 04d2 162e 02 00
 # actions=dec_ttl(32768,12345,90,765,1024)
 ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000
 
+# actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+ffff 0018 00002320 001d 3039 00005BA0 00008707 0000B26E
+
 ])
 sed '/^[[#&]]/d' < test-data > input.txt
 sed -n 's/^# //p; /^$/p' < test-data > expout
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index 075f2e4..9e256a2 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -12,6 +12,7 @@ cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller
 actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note
 actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
 in_port=0 actions=resubmit:0
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 
 AT_CHECK([ovs-ofctl parse-flows flows.txt
@@ -28,6 +29,7 @@ OFPT_FLOW_MOD: ADD priority=60000 cookie:0x123456789abcdef hard:10 actions=CONTR
 OFPT_FLOW_MOD: ADD actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00
 OFPT_FLOW_MOD: ADD actions=load:0xa6badbfffefe59fa->NXM_NX_IPV6_SRC[0..63],load:0xfe8001234567890a->NXM_NX_IPV6_SRC[64..127]
 OFPT_FLOW_MOD: ADD in_port=0 actions=resubmit:0
+OFPT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
@@ -43,6 +45,7 @@ cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller
 actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note
 actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
 in_port=0 actions=resubmit:0
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 
 AT_CHECK([ovs-ofctl --protocols OpenFlow12 parse-flows flows.txt
@@ -59,6 +62,7 @@ OFPT_FLOW_MOD (OF1.2): ADD table:255 priority=60000 cookie:0x123456789abcdef har
 OFPT_FLOW_MOD (OF1.2): ADD table:255 actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00
 OFPT_FLOW_MOD (OF1.2): ADD table:255 actions=set_field:fe80:123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
 OFPT_FLOW_MOD (OF1.2): ADD table:255 in_port=0 actions=resubmit:0
+OFPT_FLOW_MOD (OF1.2): ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
@@ -116,6 +120,7 @@ send_flow_rem,actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[
 check_overlap,actions=output:1,exit,output:2
 actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 actions=controller(max_len=123,reason=invalid_ttl,id=555)
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 
 AT_CHECK([ovs-ofctl parse-flows flows.txt
@@ -150,6 +155,7 @@ NXT_FLOW_MOD: ADD table:255 send_flow_rem actions=output:1,output:NXM_NX_REG0[],
 NXT_FLOW_MOD: ADD table:255 check_overlap actions=output:1,exit,output:2
 NXT_FLOW_MOD: ADD table:255 actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 NXT_FLOW_MOD: ADD table:255 actions=controller(reason=invalid_ttl,max_len=123,id=555)
+NXT_FLOW_MOD: ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
@@ -183,6 +189,7 @@ dl_dst=01:00:00:00:00:00/01:00:00:00:00:00,actions=drop
 dl_dst=00:00:00:00:00:00/01:00:00:00:00:00,actions=drop
 dl_dst=aa:bb:cc:dd:ee:ff/fe:ff:ff:ff:ff:ff,actions=drop
 dl_dst=aa:bb:cc:dd:ee:ff/00:00:00:00:00:00,actions=drop
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ])
 AT_CHECK([ovs-ofctl -F nxm parse-flows flows.txt], [0], [stdout])
 AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0], [dnl
@@ -215,6 +222,7 @@ NXT_FLOW_MOD: ADD dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 actions=drop
 NXT_FLOW_MOD: ADD dl_dst=00:00:00:00:00:00/01:00:00:00:00:00 actions=drop
 NXT_FLOW_MOD: ADD dl_dst=aa:bb:cc:dd:ee:ff/fe:ff:ff:ff:ff:ff actions=drop
 NXT_FLOW_MOD: ADD actions=drop
+NXT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ])
 AT_CLEANUP
 
@@ -245,6 +253,7 @@ reg0=123,actions=move:NXM_NX_REG0[0..5]->NXM_NX_REG1[26..31],load:55->NXM_NX_REG
 actions=move:OXM_OF_ETH_DST[]->OXM_OF_ETH_SRC[]
 actions=push:NXM_NX_REG0[0..31],pop:NXM_NX_REG0[]
 vlan_tci=0x1123/0x1fff,actions=drop
+actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CHECK([ovs-ofctl -F nxm -mmm parse-flows flows.txt], [0], [stdout], [stderr])
 AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0],
@@ -274,6 +283,7 @@ NXT_FLOW_MOD: ADD NXM_NX_REG0(0000007b) actions=move:NXM_NX_REG0[0..5]->NXM_NX_R
 NXT_FLOW_MOD: ADD <any> actions=move:NXM_OF_ETH_DST[]->NXM_OF_ETH_SRC[]
 NXT_FLOW_MOD: ADD <any> actions=push:NXM_NX_REG0[],pop:NXM_NX_REG0[]
 NXT_FLOW_MOD: ADD NXM_OF_VLAN_TCI_W(1123/1fff) actions=drop
+NXT_FLOW_MOD: ADD <any> actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
 AT_CLEANUP
 
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 3cc618d..27c502a 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1241,6 +1241,30 @@ flow's creation, not since the receipt of the FIN or RST.)
 .RE
 .IP
 This action was added in Open vSwitch 1.5.90.
+.
+.IP "\fBsample(\fIargument\fR[\fB,\fIargument\fR]...\fB)\fR"
+Samples packets and sends one sample for every sampled packet.
+.IP
+\fIargument\fR takes the following forms:
+.RS
+.IP "\fBprobability=\fIpackets\fR"
+The number of sampled packets out of 65535.  Must be greater or equal to 1.
+.IP "\fBcollector_set_id=\fIid\fR"
+The unsigned 32-bit integer identifier of the set of sample collectors
+to send sampled packets to.  Defaults to 0.
+.IP "\fBobs_domain_id=\fIid\fR"
+When sending samples to IPFIX collectors, the unsigned 32-bit integer
+Observation Domain ID sent in every IPFIX flow record.  Defaults to 0.
+.IP "\fBobs_point_id=\fIid\fR"
+When sending samples to IPFIX collectors, the unsigned 32-bit integer
+Observation Point ID sent in every IPFIX flow record.  Defaults to 0.
+.RE
+.IP
+Refer to \fBovs\-vswitchd.conf.db\fR(8) for more details on
+configuring sample collector sets.
+.IP
+This action was added in Open vSwitch 1.9.90.
+.
 .IP "\fBexit\fR"
 This action causes Open vSwitch to immediately halt execution of further
 actions.  Those actions which have already been executed are unaffected.  Any
@@ -1555,3 +1579,4 @@ Prints the flow entries in the switch.
 .BR ovs\-appctl (8),
 .BR ovs\-controller (8),
 .BR ovs\-vswitchd (8)
+.BR ovs\-vswitchd.conf.db (8)
-- 
1.8.1.3




More information about the dev mailing list