diff mbox series

[ovs-dev,v1,1/3,ovn] OVN: ADD new ovn actions to replace source and destination ip

Message ID 1570154179-14525-2-git-send-email-ankur.sharma@nutanix.com
State Superseded
Headers show
Series ALLOW Stateless NAT operations | expand

Commit Message

Ankur Sharma Oct. 4, 2019, 1:55 a.m. UTC
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.sharma@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(-)

Comments

Ben Pfaff Oct. 4, 2019, 5:36 p.m. UTC | #1
On Fri, Oct 04, 2019 at 01:55:38AM +0000, Ankur Sharma wrote:
> 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.sharma@nutanix.com>

This is not necessary.  Use "ip4.dst = <address>;" or "ip4.src =
<address>:".
Ankur Sharma Oct. 4, 2019, 8:15 p.m. UTC | #2
Hi Ben,

Submitted a v2 without new OVN actions.
Ease of interpretation was the reasoning for having these actions, but
you are right they were redundant.

Regards,
Ankur

-----Original Message-----
From: Ben Pfaff <blp@ovn.org> 
Sent: Friday, October 4, 2019 10:37 AM
To: Ankur Sharma <ankur.sharma@nutanix.com>
Cc: ovs-dev@openvswitch.org
Subject: Re: [ovs-dev] [PATCH v1 1/3 ovn] OVN: ADD new ovn actions to replace source and destination ip

On Fri, Oct 04, 2019 at 01:55:38AM +0000, Ankur Sharma wrote:
> 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.sharma@nutanix.com>

This is not necessary.  Use "ip4.dst = <address>;" or "ip4.src = <address>:".
diff mbox series

Patch

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);