sample ovn action encodes into the OFPACT_SAMPLE ovs action. The only extra bit of logic is the ability to specify the macro $cookie as observation_point_id that makes the encoding logic use the lflow's first 32bits as observation_point_id.
Signed-off-by: Adrian Moreno <[email protected]> --- include/ovn/actions.h | 11 +++++ lib/actions.c | 111 ++++++++++++++++++++++++++++++++++++++++++ tests/ovn.at | 8 +++ tests/test-ovn.c | 2 + utilities/ovn-trace.c | 3 ++ 5 files changed, 135 insertions(+) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index f55d77d47..9e078b403 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -116,6 +116,7 @@ struct ovn_extend_table; OVNACT(PUT_FDB, ovnact_put_fdb) \ OVNACT(GET_FDB, ovnact_get_fdb) \ OVNACT(LOOKUP_FDB, ovnact_lookup_fdb) \ + OVNACT(SAMPLE, ovnact_sample) \ /* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */ enum OVS_PACKED_ENUM ovnact_type { @@ -451,6 +452,16 @@ struct ovnact_lookup_fdb { struct expr_field dst; /* 1-bit destination field. */ }; +/* OVNACT_SAMPLE */ +struct ovnact_sample { + struct ovnact ovnact; + uint16_t probability; /* probability over UINT16_MAX. */ + uint32_t collector_set_id; /* colector_set_id. */ + uint32_t obs_domain_id; /* observation domain id. */ + uint32_t obs_point_id; /* observation point id. */ + bool use_cookie; /* use cookie as obs_point_id */ +}; + /* Internal use by the helpers below. */ void ovnact_init(struct ovnact *, enum ovnact_type, size_t len); void *ovnact_put(struct ofpbuf *, enum ovnact_type, size_t len); diff --git a/lib/actions.c b/lib/actions.c index 7fe80f458..53869ce9f 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -4216,6 +4216,115 @@ ovnact_lookup_fdb_free(struct ovnact_lookup_fdb *get_fdb OVS_UNUSED) { } +static void +format_SAMPLE(const struct ovnact_sample *sample, struct ds *s) +{ + ds_put_format(s, "sample(probability=%"PRId16, sample->probability); + + ds_put_format(s, ",collector_set=%"PRId32, sample->collector_set_id); + ds_put_format(s, ",obs_domain=%"PRId32, sample->obs_domain_id); + if (sample->use_cookie) { + ds_put_cstr(s, ",obs_point=$cookie"); + } else { + ds_put_format(s, ",obs_point=%"PRId32, sample->obs_point_id); + } + ds_put_format(s, ");"); +} + +static void +encode_SAMPLE(const struct ovnact_sample *sample, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + struct ofpact_sample *os = ofpact_put_SAMPLE(ofpacts); + os->probability = sample->probability; + os->collector_set_id = sample->collector_set_id; + os->obs_domain_id= sample->obs_domain_id; + if (sample->use_cookie) { + os->obs_point_id = ep->lflow_uuid.parts[0]; + } else { + os->obs_point_id = sample->obs_point_id; + } + os->sampling_port = OFPP_NONE; +} + +static void +parse_sample_arg(struct action_context *ctx, struct ovnact_sample *sample) +{ + if (lexer_match_id(ctx->lexer, "probability")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + if (!action_parse_uint16(ctx, &sample->probability, + "probability")) { + return; + } + } + } else if (lexer_match_id(ctx->lexer, "obs_point")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_MACRO && + !strcmp(ctx->lexer->token.s, "cookie")) { + sample->use_cookie = true; + lexer_get(ctx->lexer); + } else if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + sample->obs_point_id = ntohll(ctx->lexer->token.value.integer); + lexer_get(ctx->lexer); + } else { + lexer_syntax_error(ctx->lexer, + "Malformed sample observation_point_id"); + } + } else if (lexer_match_id(ctx->lexer, "obs_domain")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + sample->obs_domain_id = ntohll(ctx->lexer->token.value.integer); + } + lexer_get(ctx->lexer); + } else if (lexer_match_id(ctx->lexer, "collector_set")) { + if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) { + return; + } + if (ctx->lexer->token.type == LEX_T_INTEGER + && ctx->lexer->token.format == LEX_F_DECIMAL) { + sample->collector_set_id = ntohll(ctx->lexer->token.value.integer); + } + lexer_get(ctx->lexer); + } else { + lexer_syntax_error(ctx->lexer, "Malformed sample action"); + } +} +static void +parse_sample(struct action_context *ctx) +{ + struct ovnact_sample * sample = ovnact_put_SAMPLE(ctx->ovnacts); + + if (lexer_match(ctx->lexer, LEX_T_LPAREN)) { + while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) { + parse_sample_arg(ctx, sample); + if (ctx->lexer->error) { + return; + } + lexer_match(ctx->lexer, LEX_T_COMMA); + } + } + if (!sample->probability) { + lexer_error(ctx->lexer, "probability must be greater than zero"); + return; + } +} + +static void +ovnact_sample_free(struct ovnact_sample *sample OVS_UNUSED) +{ +} + /* Parses an assignment or exchange or put_dhcp_opts action. */ static void parse_set_action(struct action_context *ctx) @@ -4388,6 +4497,8 @@ parse_action(struct action_context *ctx) ovnact_put_CT_SNAT_TO_VIP(ctx->ovnacts); } else if (lexer_match_id(ctx->lexer, "put_fdb")) { parse_put_fdb(ctx, ovnact_put_PUT_FDB(ctx->ovnacts)); + } else if (lexer_match_id(ctx->lexer, "sample")) { + parse_sample(ctx); } else { lexer_syntax_error(ctx->lexer, "expecting action"); } diff --git a/tests/ovn.at b/tests/ovn.at index f9551b843..d1b062fb3 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -2006,6 +2006,14 @@ pop(eth.type); push(abc); Syntax error at `abc' expecting field name. +# sample +sample(probability=100,collector_set=200,obs_domain=10,obs_point=1000); + encodes as sample(probability=100,collector_set_id=200,obs_domain_id=10,obs_point_id=1000) + +sample(probability=100,collector_set=200,obs_domain=10,obs_point=$cookie); + encodes as sample(probability=100,collector_set_id=200,obs_domain_id=10,obs_point_id=2863311530) + + # Miscellaneous negative tests. ; Syntax error at `;'. diff --git a/tests/test-ovn.c b/tests/test-ovn.c index d79c6a5bc..f9a70c8a3 100644 --- a/tests/test-ovn.c +++ b/tests/test-ovn.c @@ -1351,6 +1351,8 @@ test_parse_actions(struct ovs_cmdl_context *ctx OVS_UNUSED) .ct_snat_vip_ptable = OFTABLE_CT_SNAT_HAIRPIN, .fdb_ptable = OFTABLE_GET_FDB, .fdb_lookup_ptable = OFTABLE_LOOKUP_FDB, + .lflow_uuid.parts = + { 0xaaaaaaaa, 0xbbbbbbbb, 0xcccccccc, 0xdddddddd}, }; struct ofpbuf ofpacts; ofpbuf_init(&ofpacts, 0); diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 4b652828d..390ddc763 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -2890,6 +2890,9 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, case OVNACT_LOOKUP_FDB: execute_lookup_fdb(ovnact_get_LOOKUP_FDB(a), dp, uflow, super); break; + + case OVNACT_SAMPLE: + break; } } ofpbuf_uninit(&stack); -- 2.35.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
