[ovs-dev] [PATCH 1/4] ofp-actions: Add the NXAST_SAMPLE_IPFIX vendor action
Romain Lenglet
rlenglet at vmware.com
Tue Dec 18 19:52:09 UTC 2012
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 2255805..94bf1a5 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_ipfix" action.
v1.9.0 - xx xxx xxxx
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 91c96b3..33fdd49 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 send 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 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 186275c..3d92682 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:
@@ -1297,6 +1316,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) {
@@ -1369,6 +1399,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:
@@ -1496,6 +1530,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;
}
@@ -1638,6 +1673,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;
}
@@ -1761,6 +1797,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:
@@ -1853,6 +1890,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) {
@@ -2036,6 +2074,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 b6cf4ba..98b85a7 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 */ \
/* TODO: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 65f023a..79d78b2 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 ca0a065..991ce37 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -6051,6 +6051,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 30fcf51..f26673d 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 8616226..45e3a85 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 5ac4f97..5b9b430 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1197,6 +1197,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 (8)\fR 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
@@ -1511,3 +1531,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.0.1
More information about the dev
mailing list