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

Romain Lenglet rlenglet at vmware.com
Tue Dec 11 17:54:50 UTC 2012


Define NXAST_SAMPLE OpenFlow vendor action and the corresponding
OFPACT_SAMPLE OVS action.

Signed-off-by: Romain Lenglet <rlenglet at vmware.com>
---
 NEWS                          |  1 +
 include/openflow/nicira-ext.h | 16 +++++++++++++++
 lib/ofp-actions.c             | 45 +++++++++++++++++++++++++++++++++++++++++++
 lib/ofp-actions.h             | 10 ++++++++++
 lib/ofp-parse.c               | 21 ++++++++++++++++++++
 lib/ofp-util.def              |  1 +
 ofproto/ofproto-dpif.c        |  6 ++++++
 tests/ofp-actions.at          |  6 ++++++
 tests/ovs-ofctl.at            | 10 ++++++++++
 9 files changed, 116 insertions(+)

diff --git a/NEWS b/NEWS
index 2255805..d578c83 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ post-v1.9.0
       http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-02).
     - New "vlog/disable-rate-limit" and "vlog/enable-rate-limit" commands
       available through ovs-appctl allow control over logging rate limits.
+    - New "sample" action.
 
 
 v1.9.0 - xx xxx xxxx
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 91c96b3..2940bee 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,               /* struct nx_action_sample */
 };
 
 /* Header for Nicira-defined actions. */
@@ -2212,4 +2213,19 @@ struct nx_action_write_metadata {
 };
 OFP_ASSERT(sizeof(struct nx_action_write_metadata) == 32);
 
+/* Action structure for NXAST_SAMPLE.
+ *
+ * Samples matching packets with the given probability.  Every sampled
+ * packet is associated the given observation point ID. */
+struct nx_action_sample {
+    ovs_be16 type;                  /* OFPAT_VENDOR. */
+    ovs_be16 len;                   /* Length is 24. */
+    ovs_be32 vendor;                /* NX_VENDOR_ID. */
+    ovs_be16 subtype;               /* NXAST_SAMPLE. */
+    uint8_t zeros[6];               /* Must be zero. */
+    ovs_be32 probability;           /* Fraction of packets to sample. */
+    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 b758c7c..a3b1e5d 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_from_openflow(const struct nx_action_sample *nas,
+                     struct ofpbuf *out)
+{
+    struct ofpact_sample *sample;
+
+    sample = ofpact_put_SAMPLE(out);
+    sample->probability = ntohl(nas->probability);
+    sample->obs_point_id = ntohl(nas->obs_point_id);
+}
+
 static enum ofperr
 decode_nxast_action(const union ofp_action *a, enum ofputil_action_code *code)
 {
@@ -401,6 +412,10 @@ 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:
+        sample_from_openflow((const struct nx_action_sample *) a, out);
+        break;
     }
 
     return error;
@@ -1118,6 +1133,11 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports)
     case OFPACT_EXIT:
         return 0;
 
+    case OFPACT_SAMPLE:
+        /* TODO: Check that SAMPLE actions are always the first actions
+         * in a flow. */
+        return 0;
+
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_WRITE_METADATA:
     case OFPACT_GOTO_TABLE:
@@ -1297,6 +1317,17 @@ 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 = htonl(os->probability);
+    nas->obs_point_id = htonl(os->obs_point_id);
+}
+
+static void
 ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
 {
     switch (a->type) {
@@ -1369,6 +1400,10 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
         ofputil_put_NXAST_EXIT(out);
         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:
@@ -1496,6 +1531,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_AUTOPATH:
     case OFPACT_NOTE:
     case OFPACT_EXIT:
+    case OFPACT_SAMPLE:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -1638,6 +1674,7 @@ ofpact_to_openflow11(const struct ofpact *a, struct ofpbuf *out)
     case OFPACT_AUTOPATH:
     case OFPACT_NOTE:
     case OFPACT_EXIT:
+    case OFPACT_SAMPLE:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -1761,6 +1798,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
     case OFPACT_AUTOPATH:
     case OFPACT_NOTE:
     case OFPACT_EXIT:
+    case OFPACT_SAMPLE:
     case OFPACT_CLEAR_ACTIONS:
     case OFPACT_GOTO_TABLE:
     default:
@@ -1853,6 +1891,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) {
@@ -2036,6 +2075,12 @@ 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=%"PRIu32",obs_point_id=%"PRIu32")",
+                      sample->probability, 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 b6cf4ba..e1ee793 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,          ofpact_sample,        ofpact)    \
                                                                     \
     /* Instructions */                                              \
     /* TODO:XXX Write-Actions */                                    \
@@ -421,6 +422,15 @@ struct ofpact_note {
     uint8_t data[];
 };
 
+/* OFPACT_SAMPLE.
+ *
+ * Used for NXAST_SAMPLE. */
+struct ofpact_sample {
+    struct ofpact ofpact;
+    uint32_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 65f023a..b319a76 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(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_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);
+        }
+    }
+}
+
+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:
+        parse_sample(ofpacts, arg);
+        break;
     }
 }
 
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index 6d08d8a..366b1e3 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,          nx_action_sample,       0, "sample")
 
 #undef OFPAT10_ACTION
 #undef OFPAT11_ACTION
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index ca0a065..854ad29 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -6051,6 +6051,12 @@ 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:
+            /* TODO: Check that SAMPLE actions are always the first
+             * actions in a flow. */
+            /* TODO: Actually implement the translation here. */
+            break;
         }
     }
 
diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at
index 30fcf51..87b0919 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(probability=12345,obs_point_id=23456)
+ffff 0018 00002320 0017 000000000000 00003039 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(probability=12345,obs_point_id=23456)
+ffff 0018 00002320 0017 000000000000 00003039 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 7b8f38f..3a66528 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,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(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(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(probability=12345,obs_point_id=23456)
 ]])
 AT_CLEANUP
 
@@ -104,6 +108,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,obs_point_id=23456)
 ]])
 
 AT_CHECK([ovs-ofctl parse-flows flows.txt
@@ -138,6 +143,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,obs_point_id=23456)
 ]])
 AT_CLEANUP
 
@@ -171,6 +177,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,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
@@ -203,6 +210,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,obs_point_id=23456)
 ])
 AT_CLEANUP
 
@@ -233,6 +241,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(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],
@@ -262,6 +271,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(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.
-- 
1.8.0.1




More information about the dev mailing list