From 13e1aade24b29ce4a6425a355f482b149848928a Mon Sep 17 00:00:00 2001
From: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Date: Tue, 7 Jul 2020 17:18:26 +0200
Subject: [PATCH 06/22] Introduce icmp6_error action
Introduce icmp6_error action in order to generate an ICMPv6 packet in
response to an error in original IPv6 packet
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Numan Siddique <numans@ovn.org>
---
controller/pinctrl.c | 1 +
include/ovn/actions.h | 9 ++++++++-
lib/actions.c | 22 ++++++++++++++++++++++
ovn-sb.xml | 8 ++++++++
tests/ovn.at | 10 ++++++++++
utilities/ovn-trace.c | 5 +++++
6 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index 9231efbe3..f8be22db0 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -2772,6 +2772,7 @@ process_packet_in(struct rconn *swconn, const struct ofp_header *msg)
break;
case ACTION_OPCODE_ICMP4_ERROR:
+ case ACTION_OPCODE_ICMP6_ERROR:
pinctrl_handle_icmp(swconn, &headers, &packet, &pin.flow_metadata,
&userdata, false);
break;
diff --git a/include/ovn/actions.h b/include/ovn/actions.h
index 2b5a63a74..5abf61a40 100644
--- a/include/ovn/actions.h
+++ b/include/ovn/actions.h
@@ -94,7 +94,8 @@ struct ovn_extend_table;
OVNACT(BIND_VPORT, ovnact_bind_vport) \
OVNACT(HANDLE_SVC_CHECK, ovnact_handle_svc_check) \
OVNACT(FWD_GROUP, ovnact_fwd_group) \
- OVNACT(DHCP6_REPLY, ovnact_null)
+ OVNACT(DHCP6_REPLY, ovnact_null) \
+ OVNACT(ICMP6_ERROR, ovnact_nest)
/* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */
enum OVS_PACKED_ENUM ovnact_type {
@@ -601,6 +602,12 @@ enum action_opcode {
* The actions, in OpenFlow 1.3 format, follow the action_header.
*/
ACTION_OPCODE_DHCP6_SERVER,
+
+ /* "icmp6_error { ...actions... }".
+ *
+ * The actions, in OpenFlow 1.3 format, follow the action_header.
+ */
+ ACTION_OPCODE_ICMP6_ERROR,
};
/* Header. */
diff --git a/lib/actions.c b/lib/actions.c
index e4de97c23..515dbd2db 100644
--- a/lib/actions.c
+++ b/lib/actions.c
@@ -1408,6 +1408,12 @@ parse_ICMP6(struct action_context *ctx)
parse_nested_action(ctx, OVNACT_ICMP6, "ip6");
}
+static void
+parse_ICMP6_ERROR(struct action_context *ctx)
+{
+ parse_nested_action(ctx, OVNACT_ICMP6_ERROR, "ip6");
+}
+
static void
parse_TCP_RESET(struct action_context *ctx)
{
@@ -1471,6 +1477,12 @@ format_ICMP6(const struct ovnact_nest *nest, struct ds *s)
format_nested_action(nest, "icmp6", s);
}
+static void
+format_ICMP6_ERROR(const struct ovnact_nest *nest, struct ds *s)
+{
+ format_nested_action(nest, "icmp6_error", s);
+}
+
static void
format_IGMP(const struct ovnact_null *a OVS_UNUSED, struct ds *s)
{
@@ -1582,6 +1594,14 @@ encode_ICMP6(const struct ovnact_nest *on,
encode_nested_actions(on, ep, ACTION_OPCODE_ICMP, ofpacts);
}
+static void
+encode_ICMP6_ERROR(const struct ovnact_nest *on,
+ const struct ovnact_encode_params *ep,
+ struct ofpbuf *ofpacts)
+{
+ encode_nested_actions(on, ep, ACTION_OPCODE_ICMP6_ERROR, ofpacts);
+}
+
static void
encode_IGMP(const struct ovnact_null *a OVS_UNUSED,
const struct ovnact_encode_params *ep OVS_UNUSED,
@@ -3558,6 +3578,8 @@ parse_action(struct action_context *ctx)
parse_ICMP4_ERROR(ctx);
} else if (lexer_match_id(ctx->lexer, "icmp6")) {
parse_ICMP6(ctx);
+ } else if (lexer_match_id(ctx->lexer, "icmp6_error")) {
+ parse_ICMP6_ERROR(ctx);
} else if (lexer_match_id(ctx->lexer, "igmp")) {
ovnact_put_IGMP(ctx->ovnacts);
} else if (lexer_match_id(ctx->lexer, "tcp_reset")) {
diff --git a/ovn-sb.xml b/ovn-sb.xml
index 709cb4c48..6d6775a45 100644
--- a/ovn-sb.xml
+++ b/ovn-sb.xml
@@ -2090,6 +2090,9 @@
</dd>
<dt><code>icmp6 { <var>action</var>; </code>...<code> };</code></dt>
+ <dt>
+ <code>icmp6_error { <var>action</var>; </code>...<code> };</code>
+ </dt>
<dd>
<p>
Temporarily replaces the IPv6 packet being processed by an ICMPv6
@@ -2112,6 +2115,11 @@
<li><code>icmp6.code = 1</code> (administratively prohibited)</li>
</ul>
+ <p>
+ <code>icmp6_error</code> action is expected to be used to
+ generate an ICMPv6 packet in response to an error in original
+ IPv6 packet.
+ </p>
<p><b>Prerequisite:</b> <code>ip6</code></p>
</dd>
diff --git a/tests/ovn.at b/tests/ovn.at
index 6866a58da..cfcfa0915 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1547,6 +1547,16 @@ icmp6 { };
encodes as controller(userdata=00.00.00.0a.00.00.00.00)
has prereqs ip6
+# icmp6_error
+icmp6_error { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
+ encodes as controller(userdata=00.00.00.14.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
+ has prereqs ip6
+
+icmp6_error { };
+ formats as icmp6_error { drop; };
+ encodes as controller(userdata=00.00.00.14.00.00.00.00)
+ has prereqs ip6
+
# tcp_reset
tcp_reset { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
encodes as controller(userdata=00.00.00.0b.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
index 647cf3075..c34517aaa 100644
--- a/utilities/ovn-trace.c
+++ b/utilities/ovn-trace.c
@@ -2319,6 +2319,11 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
super);
break;
+ case OVNACT_ICMP6_ERROR:
+ execute_icmp6(ovnact_get_ICMP6_ERROR(a), dp, uflow, table_id,
+ pipeline, super);
+ break;
+
case OVNACT_IGMP:
/* Nothing to do for tracing. */
break;
--
2.26.2