[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