This patch adds 2 new ovn actions, "replace_src_ip" and "replace_dst_ip"
These actions map to mod_nw_src and mod_nw_dst OVS actions respectively. These actions simply replace the source and destination IPs of the packets, while changing the L3 and L4 checksums. Signed-off-by: Ankur Sharma <ankur.sha...@nutanix.com> --- include/ovn/actions.h | 10 ++++- lib/actions.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/ovn.at | 26 +++++++++++++ utilities/ovn-trace.c | 6 +++ 4 files changed, 144 insertions(+), 1 deletion(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 145f27f..b451e95 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -86,7 +86,9 @@ struct ovn_extend_table; OVNACT(OVNFIELD_LOAD, ovnact_load) \ OVNACT(CHECK_PKT_LARGER, ovnact_check_pkt_larger) \ OVNACT(TRIGGER_EVENT, ovnact_controller_event) \ - OVNACT(BIND_VPORT, ovnact_bind_vport) + OVNACT(BIND_VPORT, ovnact_bind_vport) \ + OVNACT(REPLACE_SRC_IP, ovnact_ip_replace) \ + OVNACT(REPLACE_DST_IP, ovnact_ip_replace) /* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */ enum OVS_PACKED_ENUM ovnact_type { @@ -279,6 +281,12 @@ struct ovnact_put_opts { size_t n_options; }; +/* OVNACT_REPLACE_SRC_IP, OVNACT_REPLACE_DST_IP. */ +struct ovnact_ip_replace { + struct ovnact ovnact; + ovs_be32 ip; +}; + /* Valid arguments to SET_QUEUE action. * * QDISC_MIN_QUEUE_ID is the default queue, so user-defined queues should diff --git a/lib/actions.c b/lib/actions.c index 6a5907e..f305996 100644 --- a/lib/actions.c +++ b/lib/actions.c @@ -871,6 +871,105 @@ ovnact_ct_nat_free(struct ovnact_ct_nat *ct_nat OVS_UNUSED) { } + +static void +parse_replace_ip(struct action_context *ctx, struct ovnact_ip_replace *ipr) +{ + add_prerequisite(ctx, "ip"); + + if (lexer_match(ctx->lexer, LEX_T_LPAREN)) { + if (ctx->lexer->token.type != LEX_T_INTEGER + || ctx->lexer->token.format != LEX_F_IPV4) { + lexer_syntax_error(ctx->lexer, "expecting IPv4 address"); + return; + } + ipr->ip = ctx->lexer->token.value.ipv4; + lexer_get(ctx->lexer); + + if (!lexer_force_match(ctx->lexer, LEX_T_RPAREN)) { + return; + } + } else { + lexer_syntax_error(ctx->lexer, "Invalid token"); + } +} + +static void +parse_REPLACE_DST_IP(struct action_context *ctx) +{ + parse_replace_ip(ctx, ovnact_put_REPLACE_DST_IP(ctx->ovnacts)); +} + +static void +parse_REPLACE_SRC_IP(struct action_context *ctx) +{ + parse_replace_ip(ctx, ovnact_put_REPLACE_SRC_IP(ctx->ovnacts)); +} + +static void +format_replace_ip(const struct ovnact_ip_replace *ipr, + const char *name, struct ds *s) +{ + ds_put_cstr(s, name); + ds_put_format(s, "("IP_FMT")", IP_ARGS(ipr->ip)); + ds_put_char(s, ';'); +} + +static void +format_REPLACE_DST_IP(const struct ovnact_ip_replace *ipr, struct ds *s) +{ + format_replace_ip(ipr, "replace_dst_ip", s); +} + +static void +format_REPLACE_SRC_IP(const struct ovnact_ip_replace *ipr, struct ds *s) +{ + format_replace_ip(ipr, "replace_src_ip", s); +} + +static void +encode_replace_ip(const struct ovnact_ip_replace *ipr, + const struct ovnact_encode_params *ep OVS_UNUSED, + bool is_src, struct ofpbuf *ofpacts) +{ + struct ofpact_ipv4 *replace_ip; + const size_t ip_offset = ofpacts->size; + ofpbuf_pull(ofpacts, ip_offset); + + if (!is_src) { + replace_ip = ofpact_put_SET_IPV4_DST(ofpacts); + + } else { + replace_ip = ofpact_put_SET_IPV4_SRC(ofpacts); + } + + replace_ip->ipv4 = ipr->ip; + + ofpbuf_push_uninit(ofpacts, ip_offset); + ofpact_finish(ofpacts, &replace_ip->ofpact); +} + +static void +encode_REPLACE_SRC_IP(const struct ovnact_ip_replace *ipr, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_replace_ip(ipr, ep, true, ofpacts); +} + +static void +encode_REPLACE_DST_IP(const struct ovnact_ip_replace *ipr, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_replace_ip(ipr, ep, false, ofpacts); +} + +static void +ovnact_ip_replace_free(struct ovnact_ip_replace *ipr OVS_UNUSED) +{ +} + static void parse_ct_lb_action(struct action_context *ctx) { @@ -2798,6 +2897,10 @@ parse_action(struct action_context *ctx) parse_trigger_event(ctx, ovnact_put_TRIGGER_EVENT(ctx->ovnacts)); } else if (lexer_match_id(ctx->lexer, "bind_vport")) { parse_bind_vport(ctx); + } else if (lexer_match_id(ctx->lexer, "replace_src_ip")) { + parse_REPLACE_SRC_IP(ctx); + } else if (lexer_match_id(ctx->lexer, "replace_dst_ip")) { + parse_REPLACE_DST_IP(ctx); } else { lexer_syntax_error(ctx->lexer, "expecting action"); } diff --git a/tests/ovn.at b/tests/ovn.at index 04898dd..f4f0798 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1432,6 +1432,32 @@ bind_vport("xyzzy",; bind_vport("xyzzy", inport; Syntax error at `;' expecting `)'. +# replace_src_ip +replace_src_ip(1.2.3.4); + encodes as mod_nw_src:1.2.3.4 + has prereqs ip +replace_src_ip; + Syntax error at `;' Invalid token. +replace_src_ip(; + Syntax error at `;' expecting IPv4 address. +replace_src_ip("; + Input ends inside quoted string. +replace_src_ip(1.2.3); + Invalid numeric constant. + +# replace_dst_ip +replace_dst_ip(1.2.3.4); + encodes as mod_nw_dst:1.2.3.4 + has prereqs ip +replace_dst_ip; + Syntax error at `;' Invalid token. +replace_dst_ip(; + Syntax error at `;' expecting IPv4 address. +replace_dst_ip("; + Input ends inside quoted string. +replace_dst_ip(1.2.3); + Invalid numeric constant. + # Miscellaneous negative tests. ; Syntax error at `;'. diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c index 0583610..2924e56 100644 --- a/utilities/ovn-trace.c +++ b/utilities/ovn-trace.c @@ -2147,6 +2147,12 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, case OVNACT_BIND_VPORT: break; + + case OVNACT_REPLACE_SRC_IP: + break; + + case OVNACT_REPLACE_DST_IP: + break; } } ds_destroy(&s); -- 1.8.3.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev