Define NXAST_SAMPLE OpenFlow vendor action and the corresponding OFPACT_SAMPLE OVS action.
Signed-off-by: Romain Lenglet <rleng...@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@openvswitch.org with concerns. -- 1.8.0.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev