[ovs-dev] [PATCH 1/4] ofp-actions: Add the NXAST_SAMPLE_IPFIX vendor action

Romain Lenglet rlenglet at vmware.com
Fri Jan 11 17:55:41 UTC 2013


Define NXAST_SAMPLE_IPFIX OpenFlow vendor action and the corresponding
OFPACT_SAMPLE_IPFIX OVS action.

Signed-off-by: Romain Lenglet <rlenglet at vmware.com>
---
 NEWS                          |  1 +
 include/openflow/nicira-ext.h | 22 +++++++++++++++++++++
 lib/ofp-actions.c             | 45 +++++++++++++++++++++++++++++++++++++++++++
 lib/ofp-actions.h             | 10 ++++++++++
 lib/ofp-parse.c               | 21 ++++++++++++++++++++
 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      | 21 ++++++++++++++++++++
 10 files changed, 141 insertions(+)

diff --git a/NEWS b/NEWS
index 3f06a7a..6cb81e6 100644
--- a/NEWS
+++ b/NEWS
@@ -17,6 +17,7 @@ post-v1.9.0
         syntax.  OpenFlow 1.1 adds a port named ANY, which introduces a
         conflict.  ANY was rarely used in flow syntax, so we chose to
         retire that meaning of ANY in favor of the OpenFlow 1.1 meaning.
+    - New "sample_ipfix" action.
 
 
 v1.9.0 - xx xxx xxxx
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 91c96b3..84d536f 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -304,6 +304,7 @@ enum nx_action_subtype {
     NXAST_CONTROLLER,           /* struct nx_action_controller */
     NXAST_DEC_TTL_CNT_IDS,      /* struct nx_action_cnt_ids */
     NXAST_WRITE_METADATA,       /* struct nx_action_write_metadata */
+    NXAST_SAMPLE_IPFIX,         /* struct nx_action_sample_ipfix */
 };
 
 /* Header for Nicira-defined actions. */
@@ -2212,4 +2213,25 @@ struct nx_action_write_metadata {
 };
 OFP_ASSERT(sizeof(struct nx_action_write_metadata) == 32);
 
+/* Action structure for NXAST_SAMPLE_IPFIX.
+ *
+ * Samples matching packets with the given probability and sends them
+ * using the IPFIX protocol.  The probability is expressed as a number
+ * of packets to be sampled out of USHRT_MAX packets.  Every sampled
+ * packet is associated with the given observation point ID.
+ *
+ * The IPFIX packets contain the sampled packets' headers when
+ * executing this rule.  If a sampled packet's headers are modified by
+ * previous actions in the flow, those modified headers are sent in
+ * the IPFIX packet. */
+struct nx_action_sample_ipfix {
+    ovs_be16 type;                  /* OFPAT_VENDOR. */
+    ovs_be16 len;                   /* Length is 16. */
+    ovs_be32 vendor;                /* NX_VENDOR_ID. */
+    ovs_be16 subtype;               /* NXAST_SAMPLE_IPFIX. */
+    ovs_be16 probability;           /* Fraction of packets to sample. */
+    ovs_be32 obs_point_id;          /* ID of sampling observation point. */
+};
+OFP_ASSERT(sizeof(struct nx_action_sample_ipfix) == 16);
+
 #endif /* openflow/nicira-ext.h */
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index 1bc8a9c..6408611 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -217,6 +217,17 @@ dec_ttl_cnt_ids_from_openflow(const struct nx_action_cnt_ids *nac_ids,
     return 0;
 }
 
+static void
+sample_ipfix_from_openflow(const struct nx_action_sample_ipfix *nasi,
+                           struct ofpbuf *out)
+{
+    struct ofpact_sample_ipfix *sample_ipfix;
+
+    sample_ipfix = ofpact_put_SAMPLE_IPFIX(out);
+    sample_ipfix->probability = ntohs(nasi->probability);
+    sample_ipfix->obs_point_id = ntohl(nasi->obs_point_id);
+}
+
 static enum ofperr
 decode_nxast_action(const union ofp_action *a, enum ofputil_action_code *code)
 {
@@ -401,6 +412,11 @@ ofpact_from_nxast(const union ofp_action *a, enum ofputil_action_code code,
     case OFPUTIL_NXAST_CONTROLLER:
         controller_from_openflow((const struct nx_action_controller *) a, out);
         break;
+
+    case OFPUTIL_NXAST_SAMPLE_IPFIX:
+        sample_ipfix_from_openflow((const struct nx_action_sample_ipfix *) a,
+                                   out);
+        break;
     }
 
     return error;
@@ -1118,6 +1134,9 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports)
     case OFPACT_EXIT:
         return 0;
 
+    case OFPACT_SAMPLE_IPFIX:
+        return 0;
+
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_WRITE_METADATA:
     case OFPACT_GOTO_TABLE:
@@ -1312,6 +1331,17 @@ ofpact_fin_timeout_to_nxast(const struct ofpact_fin_timeout *fin_timeout,
 }
 
 static void
+ofpact_sample_ipfix_to_nxast(const struct ofpact_sample_ipfix *os,
+                             struct ofpbuf *out)
+{
+    struct nx_action_sample_ipfix *nasi;
+
+    nasi = ofputil_put_NXAST_SAMPLE_IPFIX(out);
+    nasi->probability = htons(os->probability);
+    nasi->obs_point_id = htonl(os->obs_point_id);
+}
+
+static void
 ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
 {
     switch (a->type) {
@@ -1384,6 +1414,10 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
         ofputil_put_NXAST_EXIT(out);
         break;
 
+    case OFPACT_SAMPLE_IPFIX:
+        ofpact_sample_ipfix_to_nxast(ofpact_get_SAMPLE_IPFIX(a), out);
+        break;
+
     case OFPACT_OUTPUT:
     case OFPACT_ENQUEUE:
     case OFPACT_SET_VLAN_VID:
@@ -1511,6 +1545,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_AUTOPATH:
     case OFPACT_NOTE:
     case OFPACT_EXIT:
+    case OFPACT_SAMPLE_IPFIX:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -1653,6 +1688,7 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_AUTOPATH:
     case OFPACT_NOTE:
     case OFPACT_EXIT:
+    case OFPACT_SAMPLE_IPFIX:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -1776,6 +1812,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
     case OFPACT_AUTOPATH:
     case OFPACT_NOTE:
     case OFPACT_EXIT:
+    case OFPACT_SAMPLE_IPFIX:
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_GOTO_TABLE:
     default:
@@ -1868,6 +1905,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_ipfix *sample_ipfix;
     uint16_t port;
 
     switch (a->type) {
@@ -2051,6 +2089,13 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         ds_put_cstr(s, "exit");
         break;
 
+    case OFPACT_SAMPLE_IPFIX:
+        sample_ipfix = ofpact_get_SAMPLE_IPFIX(a);
+        ds_put_format(
+            s, "sample_ipfix(probability=%"PRIu16",obs_point_id=%"PRIu32")",
+            sample_ipfix->probability, sample_ipfix->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 3989040..11a6770 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -89,6 +89,7 @@
     /* Other. */                                                    \
     DEFINE_OFPACT(NOTE,            ofpact_note,          data)      \
     DEFINE_OFPACT(EXIT,            ofpact_null,          ofpact)    \
+    DEFINE_OFPACT(SAMPLE_IPFIX,    ofpact_sample_ipfix,  ofpact)    \
                                                                     \
     /* Instructions */                                              \
     /* XXX Write-Actions */                                         \
@@ -421,6 +422,15 @@ struct ofpact_note {
     uint8_t data[];
 };
 
+/* OFPACT_SAMPLE_IPFIX.
+ *
+ * Used for NXAST_SAMPLE_IPFIX. */
+struct ofpact_sample_ipfix {
+    struct ofpact ofpact;
+    uint16_t probability;
+    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 1d0ab85..0aeb612 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -379,6 +379,23 @@ parse_metadata(struct ofpbuf *b, char *arg)
 }
 
 static void
+parse_sample_ipfix(struct ofpbuf *b, char *arg)
+{
+    struct ofpact_sample_ipfix *osi = ofpact_put_SAMPLE_IPFIX(b);
+    char *key, *value;
+
+    while (ofputil_parse_key_value(&arg, &key, &value)) {
+        if (!strcmp(key, "probability")) {
+            osi->probability = str_to_u16(value, "probability");
+        } else if (!strcmp(key, "obs_point_id")) {
+            osi->obs_point_id = str_to_u32(value);
+        } else {
+            ovs_fatal(0, "invalid key '%s' in 'sample_ipfix' argument", key);
+        }
+    }
+}
+
+static void
 parse_named_action(enum ofputil_action_code code, const struct flow *flow,
                    char *arg, struct ofpbuf *ofpacts)
 {
@@ -562,6 +579,10 @@ parse_named_action(enum ofputil_action_code code, const struct flow *flow,
     case OFPUTIL_NXAST_CONTROLLER:
         parse_controller(ofpacts, arg);
         break;
+
+    case OFPUTIL_NXAST_SAMPLE_IPFIX:
+        parse_sample_ipfix(ofpacts, arg);
+        break;
     }
 }
 
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index 6d08d8a..be91732 100644
--- a/lib/ofp-util.def
+++ b/lib/ofp-util.def
@@ -62,6 +62,7 @@ NXAST_ACTION(NXAST_CONTROLLER,      nx_action_controller,   0, "controller")
 NXAST_ACTION(NXAST_DEC_TTL_CNT_IDS, nx_action_cnt_ids,      1, NULL)
 NXAST_ACTION(NXAST_WRITE_METADATA,  nx_action_write_metadata, 0,
              "write_metadata")
+NXAST_ACTION(NXAST_SAMPLE_IPFIX,    nx_action_sample_ipfix, 0, "sample_ipfix")
 
 #undef OFPAT10_ACTION
 #undef OFPAT11_ACTION
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index bc54122..57470e0 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -6073,6 +6073,10 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             xlate_table_action(ctx, ctx->flow.in_port, ogt->table_id, true);
             break;
         }
+
+        case OFPACT_SAMPLE_IPFIX:
+            /* TODO: Actually implement the translation here. */
+            break;
         }
     }
 
diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at
index aa51e08..bb35eb9 100644
--- a/tests/ofp-actions.at
+++ b/tests/ofp-actions.at
@@ -118,6 +118,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_ipfix(probability=12345,obs_point_id=23456)
+ffff 0010 00002320 0017 3039 00005BA0
+
 ])
 sed '/^[[#&]]/d' < test-data > input.txt
 sed -n 's/^# //p; /^$/p' < test-data > expout
@@ -297,6 +300,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_ipfix(probability=12345,obs_point_id=23456)
+ffff 0010 00002320 0017 3039 00005BA0
+
 ])
 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 ca68226..9d30933 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_ipfix(probability=12345,obs_point_id=23456)
 ]])
 
 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_ipfix(probability=12345,obs_point_id=23456)
 ]])
 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_ipfix(probability=12345,obs_point_id=23456)
 ]])
 
 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_ipfix(probability=12345,obs_point_id=23456)
 ]])
 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_ipfix(probability=12345,obs_point_id=23456)
 ]])
 
 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_ipfix(probability=12345,obs_point_id=23456)
 ]])
 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_ipfix(probability=12345,obs_point_id=23456)
 ])
 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_ipfix(probability=12345,obs_point_id=23456)
 ])
 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=autopath(5,NXM_NX_REG0[])
 vlan_tci=0x1123/0x1fff,actions=drop
+actions=sample_ipfix(probability=12345,obs_point_id=23456)
 ]])
 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=autopath(5,NXM_NX_REG0[])
 NXT_FLOW_MOD: ADD NXM_OF_VLAN_TCI_W(1123/1fff) actions=drop
+NXT_FLOW_MOD: ADD <any> actions=sample_ipfix(probability=12345,obs_point_id=23456)
 ]])
 AT_CHECK([[sed 's/^[^|]*|[^|]*|//' stderr]], [0], [dnl
 autopath|WARN|The autopath action is deprecated and may be removed in February 2013.  Please email dev at openvswitch.org with concerns.
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index c48645a..7322b74 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1198,6 +1198,26 @@ 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_ipfix(\fIargument\fR[\fB,\fIargument\fR]...\fB)\fR"
+Samples packets and sends one IPFIX data record for every sampled
+packet.
+.IP
+\fIargument\fR takes the following forms:
+.RS
+.IP "\fBprobability=\fIpackets\fR"
+The number of sampled packets out of 65535.  Defaults to 0.  If 0,
+this action does nothing.
+.IP "\fBobs_point_id=\fIid\fR"
+The unsigned 32-bit integer identifier of the IPFIX Observation Point
+ID associated with every sampled packet.  Defaults to 0.
+.RE
+.IP
+Refer to \fBovs\-vswitchd.conf.db\fR(8) for more details on
+configuring IPFIX.
+.IP
+This action was added in Open vSwitch 1.9.1.
+.
 .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
@@ -1512,3 +1532,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



More information about the dev mailing list