1. Update actions.h, actions.c to handle multipath action in ovn-controller. 2. Update ovn-trace to simulate action of multipath. It helps multipath debugging.
Signed-off-by: Zhenyu Gao <[email protected]> --- include/ovn/actions.h | 32 ++++++++- ovn/lib/actions.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++ ovn/utilities/ovn-trace.c | 34 ++++++++++ 3 files changed, 233 insertions(+), 1 deletion(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 0a04af7..574cc9d 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -72,7 +72,8 @@ struct simap; OVNACT(PUT_DHCPV6_OPTS, ovnact_put_dhcp_opts) \ OVNACT(SET_QUEUE, ovnact_set_queue) \ OVNACT(DNS_LOOKUP, ovnact_dns_lookup) \ - OVNACT(LOG, ovnact_log) + OVNACT(LOG, ovnact_log) \ + OVNACT(MULTIPATH, ovnact_multipath) /* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */ enum OVS_PACKED_ENUM ovnact_type { @@ -274,6 +275,35 @@ struct ovnact_log { char *name; }; +/* Fields to use when hashing flows. */ +enum ovnact_hash_fields { + OVNACT_HASH_FIELDS_ETH_SRC, + OVNACT_HASH_FIELDS_SYMMETRIC_L4, + OVNACT_HASH_FIELDS_SYMMETRIC_L3L4, + OVNACT_HASH_FIELDS_SYMMETRIC_L3L4_UDP, + OVNACT_HASH_FIELDS_NW_SRC, + OVNACT_HASH_FIELDS_NW_DST +}; + +/* Multipath link choice algorithm to apply. */ +enum ovnact_mp_algorithm { + OVNACT_MP_ALG_MODULO_N, + OVNACT_MP_ALG_HASH_THRESHOLD, + OVNACT_MP_ALG_HRW, + OVNACT_MP_ALG_ITER_HASH +}; + +/* OVNACT_MULTIPATH. */ +struct ovnact_multipath { + struct ovnact ovnact; + enum ovnact_hash_fields fields; + uint16_t basis; + enum ovnact_mp_algorithm algorithm; + uint16_t n_links; + uint32_t arg; + struct expr_field dst; +}; + /* 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/ovn/lib/actions.c b/ovn/lib/actions.c index d0d73b6..8b41af2 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -1873,6 +1873,172 @@ ovnact_log_free(struct ovnact_log *log) free(log->name); } +static void +parse_multipath(struct action_context *ctx) +{ + int basis; + int n_links; + int arg; + struct ovnact_multipath *put_multipath = + ovnact_put_MULTIPATH(ctx->ovnacts); + + if (!lexer_force_match(ctx->lexer, LEX_T_LPAREN)) { + lexer_error(ctx->lexer, " expecting parenthesis \"(\" "); + return; + } + + if (lexer_match_id(ctx->lexer, "eth_src")) { + put_multipath->fields = OVNACT_HASH_FIELDS_ETH_SRC; + } else if (lexer_match_id(ctx->lexer, "symmetric_l4")) { + put_multipath->fields = OVNACT_HASH_FIELDS_SYMMETRIC_L4; + } else if (lexer_match_id(ctx->lexer, "symmetric_l3l4")) { + put_multipath->fields = OVNACT_HASH_FIELDS_SYMMETRIC_L3L4; + } else if (lexer_match_id(ctx->lexer, "symmetric_l3l4+udp")) { + put_multipath->fields = OVNACT_HASH_FIELDS_SYMMETRIC_L3L4_UDP; + } else if (lexer_match_id(ctx->lexer, "nw_src")) { + put_multipath->fields = OVNACT_HASH_FIELDS_NW_SRC; + } else if (lexer_match_id(ctx->lexer, "nw_dst")) { + put_multipath->fields = OVNACT_HASH_FIELDS_NW_DST; + } else { + lexer_error(ctx->lexer, "multipath gets invalid hash fields type"); + return; + } + + lexer_match(ctx->lexer, LEX_T_COMMA); + + if (!lexer_get_int(ctx->lexer, &basis)) { + lexer_error(ctx->lexer, "multipath requires numeric value for basis"); + return; + } + if (basis < 0 || basis >= 65535) { + lexer_error(ctx->lexer, "multipath basis is not in valid range"); + return; + } + + put_multipath->basis = basis; + lexer_match(ctx->lexer, LEX_T_COMMA); + + if (lexer_match_id(ctx->lexer, "modulo_n")) { + put_multipath->algorithm = OVNACT_MP_ALG_MODULO_N; + } else if (lexer_match_id(ctx->lexer, "hash_threshold")) { + put_multipath->algorithm = OVNACT_MP_ALG_HASH_THRESHOLD; + } else if (lexer_match_id(ctx->lexer, "hrw")) { + put_multipath->algorithm = OVNACT_MP_ALG_HRW; + } else if (lexer_match_id(ctx->lexer, "iter_hash")) { + put_multipath->algorithm = OVNACT_MP_ALG_ITER_HASH; + } else { + lexer_error(ctx->lexer, "multipath gets invalid algorithm type"); + return; + } + lexer_match(ctx->lexer, LEX_T_COMMA); + + if (!lexer_get_int(ctx->lexer, &n_links)) { + lexer_error(ctx->lexer, + "multipath requires numeric value for n_links"); + return; + } + if (n_links < 0 || n_links >= 65535) { + lexer_error(ctx->lexer, "multipath n_links is not in valid range"); + return; + } + put_multipath->n_links = n_links; + lexer_match(ctx->lexer, LEX_T_COMMA); + + if (!lexer_get_int(ctx->lexer, &arg)) { + lexer_error(ctx->lexer, "multipath requires numeric value for args"); + return; + } + if (arg < 0) { + lexer_error(ctx->lexer, "multipath arg is not in valid range"); + return; + } + put_multipath->arg = arg; + lexer_match(ctx->lexer, LEX_T_COMMA); + + if (!expr_field_parse(ctx->lexer, ctx->pp->symtab, + &put_multipath->dst, &ctx->prereqs)) { + lexer_error(ctx->lexer, "multipath gets wrong dst register"); + return; + } + + lexer_force_match(ctx->lexer, LEX_T_RPAREN); +} + +static void +format_MULTIPATH(const struct ovnact_multipath *multipath, + struct ds *s) +{ + const char *fields, *algorithm; + + switch (multipath->fields) { + case OVNACT_HASH_FIELDS_ETH_SRC: + fields = "eth_src"; + break; + case OVNACT_HASH_FIELDS_SYMMETRIC_L4: + fields = "symmetric_l4"; + break; + case OVNACT_HASH_FIELDS_SYMMETRIC_L3L4: + fields = "symmetric_l3l4"; + break; + case OVNACT_HASH_FIELDS_SYMMETRIC_L3L4_UDP: + fields = "symmetric_l3l4+udp"; + break; + case OVNACT_HASH_FIELDS_NW_SRC: + fields = "nw_src"; + break; + case OVNACT_HASH_FIELDS_NW_DST: + fields = "nw_dst"; + break; + default: + fields = "<unknown>"; + } + + switch (multipath->algorithm) { + case OVNACT_MP_ALG_MODULO_N: + algorithm = "modulo_n"; + break; + case OVNACT_MP_ALG_HASH_THRESHOLD: + algorithm = "hash_threshold"; + break; + case OVNACT_MP_ALG_HRW: + algorithm = "hrw"; + break; + case OVNACT_MP_ALG_ITER_HASH: + algorithm = "iter_hash"; + break; + default: + algorithm = "<unknown>"; + } + + ds_put_format(s, "multipath(%s,%u,%s,%u,%u,", + fields, multipath->basis, + algorithm, multipath->n_links, + multipath->arg); + expr_field_format(&multipath->dst, s); + ds_put_format(s, ");"); +} + +static void +encode_MULTIPATH(const struct ovnact_multipath *ovnact_mp, + const struct ovnact_encode_params *ep OVS_UNUSED, + struct ofpbuf *ofpacts) +{ + struct ofpact_multipath *ofpact_mp = ofpact_put_MULTIPATH(ofpacts); + + ofpact_init_MULTIPATH(ofpact_mp); + ofpact_mp->fields = ovnact_mp->fields; + ofpact_mp->basis = ovnact_mp->basis; + ofpact_mp->algorithm = ovnact_mp->algorithm; + ofpact_mp->max_link = ovnact_mp->n_links - 1; + ofpact_mp->arg = ovnact_mp->arg; + ofpact_mp->dst = expr_resolve_field(&ovnact_mp->dst); +} + +static void +ovnact_multipath_free(struct ovnact_multipath *mp OVS_UNUSED) +{ +} + /* Parses an assignment or exchange or put_dhcp_opts action. */ static void parse_set_action(struct action_context *ctx) @@ -1954,6 +2120,8 @@ parse_action(struct action_context *ctx) parse_SET_QUEUE(ctx); } else if (lexer_match_id(ctx->lexer, "log")) { parse_LOG(ctx); + } else if (lexer_match_id(ctx->lexer, "multipath")) { + parse_multipath(ctx); } else { lexer_syntax_error(ctx->lexer, "expecting action"); } diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index 59083ee..af0c7da 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -25,6 +25,7 @@ #include "fatal-signal.h" #include "flow.h" #include "nx-match.h" +#include "multipath.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" #include "openvswitch/ofp-actions.h" @@ -1695,6 +1696,36 @@ execute_log(const struct ovnact_log *log, struct flow *uflow, } static void +execute_multipath(const struct ovnact_multipath *ovnact_mp, + struct flow *uflow, + struct ovs_list *super) +{ + struct ofpact_multipath ofpact_mp; + struct flow_wildcards wc; + union mf_subvalue cst; + struct ds s = DS_EMPTY_INITIALIZER; + + ofpact_init_MULTIPATH(&ofpact_mp); + ofpact_mp.fields = ovnact_mp->fields; + ofpact_mp.basis = ovnact_mp->basis; + ofpact_mp.algorithm = ovnact_mp->algorithm; + ofpact_mp.max_link = ovnact_mp->n_links - 1; + ofpact_mp.arg = ovnact_mp->arg; + ofpact_mp.dst = expr_resolve_field(&ovnact_mp->dst); + + multipath_execute(&ofpact_mp, uflow, &wc); + + expr_field_format(&ovnact_mp->dst, &s); + ds_put_cstr(&s, " = "); + mf_read_subfield(&ofpact_mp.dst, uflow, &cst); + ds_put_hex(&s, &cst, sizeof cst); + ds_put_cstr(&s, "(multipath hash result)"); + + ovntrace_node_append(super, OVNTRACE_NODE_TRANSFORMATION, + "%s", ds_cstr(&s)); +} + +static void trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, const struct ovntrace_datapath *dp, struct flow *uflow, uint8_t table_id, enum ovnact_pipeline pipeline, @@ -1833,6 +1864,9 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, case OVNACT_LOG: execute_log(ovnact_get_LOG(a), uflow, super); break; + case OVNACT_MULTIPATH: + execute_multipath(ovnact_get_MULTIPATH(a), uflow, super); + break; } } -- 1.8.3.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
