|
|
ebb439 |
From 6fc44a540fdb1bc9ac0d0cc1ef5786efadbee13c Mon Sep 17 00:00:00 2001
|
|
|
ebb439 |
From: Numan Siddique <numans@ovn.org>
|
|
|
ebb439 |
Date: Tue, 29 Sep 2020 15:25:43 +0530
|
|
|
ebb439 |
Subject: [PATCH 3/5] actions: Add a new OVN action - reject {}.
|
|
|
ebb439 |
|
|
|
ebb439 |
This action is similar to tcp_reset and icmp4/icmp6 action. If the matching
|
|
|
ebb439 |
packet is an IPv4 of IPv6 TCP packet, it sends out TCP RST packet else it
|
|
|
ebb439 |
sends out ICMPv4 or ICMPv6 Destination unreachable packet.
|
|
|
ebb439 |
|
|
|
ebb439 |
While transforming the original packet to the reject packet, this action
|
|
|
ebb439 |
implicitly swaps the eth source with eth destination and IP source with
|
|
|
ebb439 |
IP destination.
|
|
|
ebb439 |
|
|
|
ebb439 |
A future patch will make use of this action for reject ACL.
|
|
|
ebb439 |
|
|
|
ebb439 |
Acked-by: Mark Michelson <mmichels@redhat.com>
|
|
|
ebb439 |
Acked-by: Dumitru Ceara <dceara@redhat.com>
|
|
|
ebb439 |
Signed-off-by: Numan Siddique <numans@ovn.org>
|
|
|
ebb439 |
|
|
|
ebb439 |
(cherry-picked from upstream master commit 64f8c9e9ff1ce26d06831995514cf66319f16b34)
|
|
|
ebb439 |
|
|
|
ebb439 |
Change-Id: Iacabf30344f21daf51d53989b4774fbdbafe00be
|
|
|
ebb439 |
---
|
|
|
ebb439 |
controller/pinctrl.c | 64 +++++++++++++++++++++++--------
|
|
|
ebb439 |
include/ovn/actions.h | 9 ++++-
|
|
|
ebb439 |
lib/actions.c | 22 +++++++++++
|
|
|
ebb439 |
ovn-sb.xml | 16 ++++++++
|
|
|
ebb439 |
tests/ovn.at | 8 ++++
|
|
|
ebb439 |
utilities/ovn-trace.c | 88 ++++++++++++++++++++++++++++++++-----------
|
|
|
ebb439 |
6 files changed, 168 insertions(+), 39 deletions(-)
|
|
|
ebb439 |
|
|
|
ebb439 |
diff --git a/controller/pinctrl.c b/controller/pinctrl.c
|
|
|
ebb439 |
index 7099687eb..d85ba504d 100644
|
|
|
ebb439 |
--- a/controller/pinctrl.c
|
|
|
ebb439 |
+++ b/controller/pinctrl.c
|
|
|
ebb439 |
@@ -1542,7 +1542,7 @@ static void
|
|
|
ebb439 |
pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
|
|
|
ebb439 |
struct dp_packet *pkt_in,
|
|
|
ebb439 |
const struct match *md, struct ofpbuf *userdata,
|
|
|
ebb439 |
- bool set_icmp_code)
|
|
|
ebb439 |
+ bool set_icmp_code, bool loopback)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
/* This action only works for IP packets, and the switch should only send
|
|
|
ebb439 |
* us IP packets this way, but check here just to be sure. */
|
|
|
ebb439 |
@@ -1563,8 +1563,8 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
|
|
|
ebb439 |
packet.packet_type = htonl(PT_ETH);
|
|
|
ebb439 |
|
|
|
ebb439 |
struct eth_header *eh = dp_packet_put_zeros(&packet, sizeof *eh);
|
|
|
ebb439 |
- eh->eth_dst = ip_flow->dl_dst;
|
|
|
ebb439 |
- eh->eth_src = ip_flow->dl_src;
|
|
|
ebb439 |
+ eh->eth_dst = loopback ? ip_flow->dl_src : ip_flow->dl_dst;
|
|
|
ebb439 |
+ eh->eth_src = loopback ? ip_flow->dl_dst : ip_flow->dl_src;
|
|
|
ebb439 |
|
|
|
ebb439 |
if (get_dl_type(ip_flow) == htons(ETH_TYPE_IP)) {
|
|
|
ebb439 |
struct ip_header *in_ip = dp_packet_l3(pkt_in);
|
|
|
ebb439 |
@@ -1586,8 +1586,9 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
|
|
|
ebb439 |
sizeof(struct icmp_header));
|
|
|
ebb439 |
nh->ip_proto = IPPROTO_ICMP;
|
|
|
ebb439 |
nh->ip_frag_off = htons(IP_DF);
|
|
|
ebb439 |
- packet_set_ipv4(&packet, ip_flow->nw_src, ip_flow->nw_dst,
|
|
|
ebb439 |
- ip_flow->nw_tos, 255);
|
|
|
ebb439 |
+ ovs_be32 nw_src = loopback ? ip_flow->nw_dst : ip_flow->nw_src;
|
|
|
ebb439 |
+ ovs_be32 nw_dst = loopback ? ip_flow->nw_src : ip_flow->nw_dst;
|
|
|
ebb439 |
+ packet_set_ipv4(&packet, nw_src, nw_dst, ip_flow->nw_tos, 255);
|
|
|
ebb439 |
|
|
|
ebb439 |
uint8_t icmp_code = 1;
|
|
|
ebb439 |
if (set_icmp_code && in_ip->ip_proto == IPPROTO_UDP) {
|
|
|
ebb439 |
@@ -1634,8 +1635,12 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
|
|
|
ebb439 |
nh->ip6_vfc = 0x60;
|
|
|
ebb439 |
nh->ip6_nxt = IPPROTO_ICMPV6;
|
|
|
ebb439 |
nh->ip6_plen = htons(ICMP6_DATA_HEADER_LEN);
|
|
|
ebb439 |
- packet_set_ipv6(&packet, &ip_flow->ipv6_src, &ip_flow->ipv6_dst,
|
|
|
ebb439 |
- ip_flow->nw_tos, ip_flow->ipv6_label, 255);
|
|
|
ebb439 |
+ const struct in6_addr *ip6_src =
|
|
|
ebb439 |
+ loopback ? &ip_flow->ipv6_dst : &ip_flow->ipv6_src;
|
|
|
ebb439 |
+ const struct in6_addr *ip6_dst =
|
|
|
ebb439 |
+ loopback ? &ip_flow->ipv6_src : &ip_flow->ipv6_dst;
|
|
|
ebb439 |
+ packet_set_ipv6(&packet, ip6_src, ip6_dst, ip_flow->nw_tos,
|
|
|
ebb439 |
+ ip_flow->ipv6_label, 255);
|
|
|
ebb439 |
|
|
|
ebb439 |
ih = dp_packet_put_zeros(&packet, sizeof *ih);
|
|
|
ebb439 |
dp_packet_set_l4(&packet, ih);
|
|
|
ebb439 |
@@ -1692,7 +1697,8 @@ pinctrl_handle_icmp(struct rconn *swconn, const struct flow *ip_flow,
|
|
|
ebb439 |
static void
|
|
|
ebb439 |
pinctrl_handle_tcp_reset(struct rconn *swconn, const struct flow *ip_flow,
|
|
|
ebb439 |
struct dp_packet *pkt_in,
|
|
|
ebb439 |
- const struct match *md, struct ofpbuf *userdata)
|
|
|
ebb439 |
+ const struct match *md, struct ofpbuf *userdata,
|
|
|
ebb439 |
+ bool loopback)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
/* This action only works for TCP segments, and the switch should only send
|
|
|
ebb439 |
* us TCP segments this way, but check here just to be sure. */
|
|
|
ebb439 |
@@ -1707,14 +1713,23 @@ pinctrl_handle_tcp_reset(struct rconn *swconn, const struct flow *ip_flow,
|
|
|
ebb439 |
|
|
|
ebb439 |
dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub);
|
|
|
ebb439 |
packet.packet_type = htonl(PT_ETH);
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+ struct eth_addr eth_src = loopback ? ip_flow->dl_dst : ip_flow->dl_src;
|
|
|
ebb439 |
+ struct eth_addr eth_dst = loopback ? ip_flow->dl_src : ip_flow->dl_dst;
|
|
|
ebb439 |
+
|
|
|
ebb439 |
if (get_dl_type(ip_flow) == htons(ETH_TYPE_IPV6)) {
|
|
|
ebb439 |
- pinctrl_compose_ipv6(&packet, ip_flow->dl_src, ip_flow->dl_dst,
|
|
|
ebb439 |
- (struct in6_addr *)&ip_flow->ipv6_src,
|
|
|
ebb439 |
- (struct in6_addr *)&ip_flow->ipv6_dst,
|
|
|
ebb439 |
+ const struct in6_addr *ip6_src =
|
|
|
ebb439 |
+ loopback ? &ip_flow->ipv6_dst : &ip_flow->ipv6_src;
|
|
|
ebb439 |
+ const struct in6_addr *ip6_dst =
|
|
|
ebb439 |
+ loopback ? &ip_flow->ipv6_src : &ip_flow->ipv6_dst;
|
|
|
ebb439 |
+ pinctrl_compose_ipv6(&packet, eth_src, eth_dst,
|
|
|
ebb439 |
+ (struct in6_addr *) ip6_src,
|
|
|
ebb439 |
+ (struct in6_addr *) ip6_dst,
|
|
|
ebb439 |
IPPROTO_TCP, 63, TCP_HEADER_LEN);
|
|
|
ebb439 |
} else {
|
|
|
ebb439 |
- pinctrl_compose_ipv4(&packet, ip_flow->dl_src, ip_flow->dl_dst,
|
|
|
ebb439 |
- ip_flow->nw_src, ip_flow->nw_dst,
|
|
|
ebb439 |
+ ovs_be32 nw_src = loopback ? ip_flow->nw_dst : ip_flow->nw_src;
|
|
|
ebb439 |
+ ovs_be32 nw_dst = loopback ? ip_flow->nw_src : ip_flow->nw_dst;
|
|
|
ebb439 |
+ pinctrl_compose_ipv4(&packet, eth_src, eth_dst, nw_src, nw_dst,
|
|
|
ebb439 |
IPPROTO_TCP, 63, TCP_HEADER_LEN);
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
@@ -1745,6 +1760,18 @@ pinctrl_handle_tcp_reset(struct rconn *swconn, const struct flow *ip_flow,
|
|
|
ebb439 |
dp_packet_uninit(&packet);
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
+static void
|
|
|
ebb439 |
+pinctrl_handle_reject(struct rconn *swconn, const struct flow *ip_flow,
|
|
|
ebb439 |
+ struct dp_packet *pkt_in,
|
|
|
ebb439 |
+ const struct match *md, struct ofpbuf *userdata)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ if (ip_flow->nw_proto == IPPROTO_TCP) {
|
|
|
ebb439 |
+ pinctrl_handle_tcp_reset(swconn, ip_flow, pkt_in, md, userdata, true);
|
|
|
ebb439 |
+ } else {
|
|
|
ebb439 |
+ pinctrl_handle_icmp(swconn, ip_flow, pkt_in, md, userdata, true, true);
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
static bool
|
|
|
ebb439 |
is_dhcp_flags_broadcast(ovs_be16 flags)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
@@ -2848,18 +2875,23 @@ process_packet_in(struct rconn *swconn, const struct ofp_header *msg)
|
|
|
ebb439 |
|
|
|
ebb439 |
case ACTION_OPCODE_ICMP:
|
|
|
ebb439 |
pinctrl_handle_icmp(swconn, &headers, &packet, &pin.flow_metadata,
|
|
|
ebb439 |
- &userdata, true);
|
|
|
ebb439 |
+ &userdata, true, false);
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
case ACTION_OPCODE_ICMP4_ERROR:
|
|
|
ebb439 |
case ACTION_OPCODE_ICMP6_ERROR:
|
|
|
ebb439 |
pinctrl_handle_icmp(swconn, &headers, &packet, &pin.flow_metadata,
|
|
|
ebb439 |
- &userdata, false);
|
|
|
ebb439 |
+ &userdata, false, false);
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
case ACTION_OPCODE_TCP_RESET:
|
|
|
ebb439 |
pinctrl_handle_tcp_reset(swconn, &headers, &packet, &pin.flow_metadata,
|
|
|
ebb439 |
- &userdata);
|
|
|
ebb439 |
+ &userdata, false);
|
|
|
ebb439 |
+ break;
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+ case ACTION_OPCODE_REJECT:
|
|
|
ebb439 |
+ pinctrl_handle_reject(swconn, &headers, &packet, &pin.flow_metadata,
|
|
|
ebb439 |
+ &userdata);
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
case ACTION_OPCODE_PUT_ICMP4_FRAG_MTU:
|
|
|
ebb439 |
diff --git a/include/ovn/actions.h b/include/ovn/actions.h
|
|
|
ebb439 |
index 636cb4bc1..b4e5acabb 100644
|
|
|
ebb439 |
--- a/include/ovn/actions.h
|
|
|
ebb439 |
+++ b/include/ovn/actions.h
|
|
|
ebb439 |
@@ -95,7 +95,8 @@ struct ovn_extend_table;
|
|
|
ebb439 |
OVNACT(HANDLE_SVC_CHECK, ovnact_handle_svc_check) \
|
|
|
ebb439 |
OVNACT(FWD_GROUP, ovnact_fwd_group) \
|
|
|
ebb439 |
OVNACT(DHCP6_REPLY, ovnact_null) \
|
|
|
ebb439 |
- OVNACT(ICMP6_ERROR, ovnact_nest)
|
|
|
ebb439 |
+ OVNACT(ICMP6_ERROR, ovnact_nest) \
|
|
|
ebb439 |
+ OVNACT(REJECT, ovnact_nest) \
|
|
|
ebb439 |
|
|
|
ebb439 |
/* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */
|
|
|
ebb439 |
enum OVS_PACKED_ENUM ovnact_type {
|
|
|
ebb439 |
@@ -605,6 +606,12 @@ enum action_opcode {
|
|
|
ebb439 |
/* MTU value (to put in the icmp6 header field - frag_mtu) follow the
|
|
|
ebb439 |
* action header. */
|
|
|
ebb439 |
ACTION_OPCODE_PUT_ICMP6_FRAG_MTU,
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+ /* "reject { ...actions... }".
|
|
|
ebb439 |
+ *
|
|
|
ebb439 |
+ * The actions, in OpenFlow 1.3 format, follow the action_header.
|
|
|
ebb439 |
+ */
|
|
|
ebb439 |
+ ACTION_OPCODE_REJECT,
|
|
|
ebb439 |
};
|
|
|
ebb439 |
|
|
|
ebb439 |
/* Header. */
|
|
|
ebb439 |
diff --git a/lib/actions.c b/lib/actions.c
|
|
|
ebb439 |
index 5fe0a3897..1e1bdeff2 100644
|
|
|
ebb439 |
--- a/lib/actions.c
|
|
|
ebb439 |
+++ b/lib/actions.c
|
|
|
ebb439 |
@@ -1386,6 +1386,12 @@ parse_CLONE(struct action_context *ctx)
|
|
|
ebb439 |
parse_nested_action(ctx, OVNACT_CLONE, NULL, WR_DEFAULT);
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
+static void
|
|
|
ebb439 |
+parse_REJECT(struct action_context *ctx)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ parse_nested_action(ctx, OVNACT_REJECT, NULL, ctx->scope);
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
static void
|
|
|
ebb439 |
format_nested_action(const struct ovnact_nest *on, const char *name,
|
|
|
ebb439 |
struct ds *s)
|
|
|
ebb439 |
@@ -1479,6 +1485,12 @@ format_TRIGGER_EVENT(const struct ovnact_controller_event *event,
|
|
|
ebb439 |
ds_put_cstr(s, ");");
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
+static void
|
|
|
ebb439 |
+format_REJECT(const struct ovnact_nest *nest, struct ds *s)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ format_nested_action(nest, "reject", s);
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
static void
|
|
|
ebb439 |
encode_nested_actions(const struct ovnact_nest *on,
|
|
|
ebb439 |
const struct ovnact_encode_params *ep,
|
|
|
ebb439 |
@@ -1560,6 +1572,14 @@ encode_TCP_RESET(const struct ovnact_nest *on,
|
|
|
ebb439 |
encode_nested_actions(on, ep, ACTION_OPCODE_TCP_RESET, ofpacts);
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
+static void
|
|
|
ebb439 |
+encode_REJECT(const struct ovnact_nest *on,
|
|
|
ebb439 |
+ const struct ovnact_encode_params *ep,
|
|
|
ebb439 |
+ struct ofpbuf *ofpacts)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ encode_nested_actions(on, ep, ACTION_OPCODE_REJECT, ofpacts);
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
static void
|
|
|
ebb439 |
encode_ND_NA(const struct ovnact_nest *on,
|
|
|
ebb439 |
const struct ovnact_encode_params *ep,
|
|
|
ebb439 |
@@ -3567,6 +3587,8 @@ parse_action(struct action_context *ctx)
|
|
|
ebb439 |
parse_fwd_group_action(ctx);
|
|
|
ebb439 |
} else if (lexer_match_id(ctx->lexer, "handle_dhcpv6_reply")) {
|
|
|
ebb439 |
ovnact_put_DHCP6_REPLY(ctx->ovnacts);
|
|
|
ebb439 |
+ } else if (lexer_match_id(ctx->lexer, "reject")) {
|
|
|
ebb439 |
+ parse_REJECT(ctx);
|
|
|
ebb439 |
} else {
|
|
|
ebb439 |
lexer_syntax_error(ctx->lexer, "expecting action");
|
|
|
ebb439 |
}
|
|
|
ebb439 |
diff --git a/ovn-sb.xml b/ovn-sb.xml
|
|
|
ebb439 |
index 59888a155..182ff0a8a 100644
|
|
|
ebb439 |
--- a/ovn-sb.xml
|
|
|
ebb439 |
+++ b/ovn-sb.xml
|
|
|
ebb439 |
@@ -2191,6 +2191,22 @@ tcp.flags = RST;
|
|
|
ebb439 |
Prerequisite: tcp
|
|
|
ebb439 |
|
|
|
ebb439 |
|
|
|
ebb439 |
+ reject { action; ... };
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+ If the original packet is IPv4 or IPv6 TCP packet, it replaces it
|
|
|
ebb439 |
+ with IPv4 or IPv6 TCP RST packet and executes the inner actions.
|
|
|
ebb439 |
+ Otherwise it replaces it with an ICMPv4 or ICMPv6 packet and
|
|
|
ebb439 |
+ executes the inner actions.
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+ The inner actions should not attempt to swap eth source with eth
|
|
|
ebb439 |
+ destination and IP source with IP destination as this action
|
|
|
ebb439 |
+ implicitly does that.
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+
|
|
|
ebb439 |
trigger_event;
|
|
|
ebb439 |
|
|
|
ebb439 |
|
|
|
ebb439 |
diff --git a/tests/ovn.at b/tests/ovn.at
|
|
|
ebb439 |
index 53f5d4d96..337ab4e7d 100644
|
|
|
ebb439 |
--- a/tests/ovn.at
|
|
|
ebb439 |
+++ b/tests/ovn.at
|
|
|
ebb439 |
@@ -1593,6 +1593,14 @@ tcp_reset { };
|
|
|
ebb439 |
encodes as controller(userdata=00.00.00.0b.00.00.00.00)
|
|
|
ebb439 |
has prereqs tcp
|
|
|
ebb439 |
|
|
|
ebb439 |
+# reject
|
|
|
ebb439 |
+reject { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
|
|
|
ebb439 |
+ encodes as controller(userdata=00.00.00.16.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)
|
|
|
ebb439 |
+
|
|
|
ebb439 |
+reject { };
|
|
|
ebb439 |
+ formats as reject { drop; };
|
|
|
ebb439 |
+ encodes as controller(userdata=00.00.00.16.00.00.00.00)
|
|
|
ebb439 |
+
|
|
|
ebb439 |
# trigger_event
|
|
|
ebb439 |
trigger_event(event = "empty_lb_backends", vip = "10.0.0.1:80", protocol = "tcp", load_balancer = "12345678-abcd-9876-fedc-11119f8e7d6c");
|
|
|
ebb439 |
encodes as controller(userdata=00.00.00.0f.00.00.00.00.00.00.00.00.00.01.00.0b.31.30.2e.30.2e.30.2e.31.3a.38.30.00.02.00.03.74.63.70.00.03.00.24.31.32.33.34.35.36.37.38.2d.61.62.63.64.2d.39.38.37.36.2d.66.65.64.63.2d.31.31.31.31.39.66.38.65.37.64.36.63)
|
|
|
ebb439 |
diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
|
|
|
ebb439 |
index 0920ae159..ad33f8e36 100644
|
|
|
ebb439 |
--- a/utilities/ovn-trace.c
|
|
|
ebb439 |
+++ b/utilities/ovn-trace.c
|
|
|
ebb439 |
@@ -1638,16 +1638,23 @@ execute_nd_ns(const struct ovnact_nest *on, const struct ovntrace_datapath *dp,
|
|
|
ebb439 |
static void
|
|
|
ebb439 |
execute_icmp4(const struct ovnact_nest *on,
|
|
|
ebb439 |
const struct ovntrace_datapath *dp,
|
|
|
ebb439 |
- const struct flow *uflow, uint8_t table_id,
|
|
|
ebb439 |
+ const struct flow *uflow, uint8_t table_id, bool loopback,
|
|
|
ebb439 |
enum ovnact_pipeline pipeline, struct ovs_list *super)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
struct flow icmp4_flow = *uflow;
|
|
|
ebb439 |
|
|
|
ebb439 |
/* Update fields for ICMP. */
|
|
|
ebb439 |
- icmp4_flow.dl_dst = uflow->dl_dst;
|
|
|
ebb439 |
- icmp4_flow.dl_src = uflow->dl_src;
|
|
|
ebb439 |
- icmp4_flow.nw_dst = uflow->nw_dst;
|
|
|
ebb439 |
- icmp4_flow.nw_src = uflow->nw_src;
|
|
|
ebb439 |
+ if (loopback) {
|
|
|
ebb439 |
+ icmp4_flow.dl_dst = uflow->dl_src;
|
|
|
ebb439 |
+ icmp4_flow.dl_src = uflow->dl_dst;
|
|
|
ebb439 |
+ icmp4_flow.nw_dst = uflow->nw_src;
|
|
|
ebb439 |
+ icmp4_flow.nw_src = uflow->nw_dst;
|
|
|
ebb439 |
+ } else {
|
|
|
ebb439 |
+ icmp4_flow.dl_dst = uflow->dl_dst;
|
|
|
ebb439 |
+ icmp4_flow.dl_src = uflow->dl_src;
|
|
|
ebb439 |
+ icmp4_flow.nw_dst = uflow->nw_dst;
|
|
|
ebb439 |
+ icmp4_flow.nw_src = uflow->nw_src;
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
icmp4_flow.nw_proto = IPPROTO_ICMP;
|
|
|
ebb439 |
icmp4_flow.nw_ttl = 255;
|
|
|
ebb439 |
icmp4_flow.tp_src = htons(ICMP4_DST_UNREACH); /* icmp type */
|
|
|
ebb439 |
@@ -1663,16 +1670,23 @@ execute_icmp4(const struct ovnact_nest *on,
|
|
|
ebb439 |
static void
|
|
|
ebb439 |
execute_icmp6(const struct ovnact_nest *on,
|
|
|
ebb439 |
const struct ovntrace_datapath *dp,
|
|
|
ebb439 |
- const struct flow *uflow, uint8_t table_id,
|
|
|
ebb439 |
+ const struct flow *uflow, uint8_t table_id, bool loopback,
|
|
|
ebb439 |
enum ovnact_pipeline pipeline, struct ovs_list *super)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
struct flow icmp6_flow = *uflow;
|
|
|
ebb439 |
|
|
|
ebb439 |
/* Update fields for ICMPv6. */
|
|
|
ebb439 |
- icmp6_flow.dl_dst = uflow->dl_dst;
|
|
|
ebb439 |
- icmp6_flow.dl_src = uflow->dl_src;
|
|
|
ebb439 |
- icmp6_flow.ipv6_dst = uflow->ipv6_dst;
|
|
|
ebb439 |
- icmp6_flow.ipv6_src = uflow->ipv6_src;
|
|
|
ebb439 |
+ if (loopback) {
|
|
|
ebb439 |
+ icmp6_flow.dl_dst = uflow->dl_src;
|
|
|
ebb439 |
+ icmp6_flow.dl_src = uflow->dl_dst;
|
|
|
ebb439 |
+ icmp6_flow.ipv6_dst = uflow->ipv6_src;
|
|
|
ebb439 |
+ icmp6_flow.ipv6_src = uflow->ipv6_dst;
|
|
|
ebb439 |
+ } else {
|
|
|
ebb439 |
+ icmp6_flow.dl_dst = uflow->dl_dst;
|
|
|
ebb439 |
+ icmp6_flow.dl_src = uflow->dl_src;
|
|
|
ebb439 |
+ icmp6_flow.ipv6_dst = uflow->ipv6_dst;
|
|
|
ebb439 |
+ icmp6_flow.ipv6_src = uflow->ipv6_src;
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
icmp6_flow.nw_proto = IPPROTO_ICMPV6;
|
|
|
ebb439 |
icmp6_flow.nw_ttl = 255;
|
|
|
ebb439 |
icmp6_flow.tp_src = htons(ICMP6_DST_UNREACH); /* icmp type */
|
|
|
ebb439 |
@@ -1689,15 +1703,23 @@ static void
|
|
|
ebb439 |
execute_tcp_reset(const struct ovnact_nest *on,
|
|
|
ebb439 |
const struct ovntrace_datapath *dp,
|
|
|
ebb439 |
const struct flow *uflow, uint8_t table_id,
|
|
|
ebb439 |
- enum ovnact_pipeline pipeline, struct ovs_list *super)
|
|
|
ebb439 |
+ bool loopback, enum ovnact_pipeline pipeline,
|
|
|
ebb439 |
+ struct ovs_list *super)
|
|
|
ebb439 |
{
|
|
|
ebb439 |
struct flow tcp_flow = *uflow;
|
|
|
ebb439 |
|
|
|
ebb439 |
/* Update fields for TCP segment. */
|
|
|
ebb439 |
- tcp_flow.dl_dst = uflow->dl_dst;
|
|
|
ebb439 |
- tcp_flow.dl_src = uflow->dl_src;
|
|
|
ebb439 |
- tcp_flow.nw_dst = uflow->nw_dst;
|
|
|
ebb439 |
- tcp_flow.nw_src = uflow->nw_src;
|
|
|
ebb439 |
+ if (loopback) {
|
|
|
ebb439 |
+ tcp_flow.dl_dst = uflow->dl_src;
|
|
|
ebb439 |
+ tcp_flow.dl_src = uflow->dl_dst;
|
|
|
ebb439 |
+ tcp_flow.nw_dst = uflow->nw_src;
|
|
|
ebb439 |
+ tcp_flow.nw_src = uflow->nw_dst;
|
|
|
ebb439 |
+ } else {
|
|
|
ebb439 |
+ tcp_flow.dl_dst = uflow->dl_dst;
|
|
|
ebb439 |
+ tcp_flow.dl_src = uflow->dl_src;
|
|
|
ebb439 |
+ tcp_flow.nw_dst = uflow->nw_dst;
|
|
|
ebb439 |
+ tcp_flow.nw_src = uflow->nw_src;
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
tcp_flow.nw_proto = IPPROTO_TCP;
|
|
|
ebb439 |
tcp_flow.nw_ttl = 255;
|
|
|
ebb439 |
tcp_flow.tp_src = uflow->tp_src;
|
|
|
ebb439 |
@@ -1711,6 +1733,23 @@ execute_tcp_reset(const struct ovnact_nest *on,
|
|
|
ebb439 |
table_id, pipeline, &node->subs);
|
|
|
ebb439 |
}
|
|
|
ebb439 |
|
|
|
ebb439 |
+static void
|
|
|
ebb439 |
+execute_reject(const struct ovnact_nest *on,
|
|
|
ebb439 |
+ const struct ovntrace_datapath *dp,
|
|
|
ebb439 |
+ const struct flow *uflow, uint8_t table_id,
|
|
|
ebb439 |
+ enum ovnact_pipeline pipeline, struct ovs_list *super)
|
|
|
ebb439 |
+{
|
|
|
ebb439 |
+ if (uflow->nw_proto == IPPROTO_TCP) {
|
|
|
ebb439 |
+ execute_tcp_reset(on, dp, uflow, table_id, true, pipeline, super);
|
|
|
ebb439 |
+ } else {
|
|
|
ebb439 |
+ if (get_dl_type(uflow) == htons(ETH_TYPE_IP)) {
|
|
|
ebb439 |
+ execute_icmp4(on, dp, uflow, table_id, true, pipeline, super);
|
|
|
ebb439 |
+ } else {
|
|
|
ebb439 |
+ execute_icmp6(on, dp, uflow, table_id, true, pipeline, super);
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
+ }
|
|
|
ebb439 |
+}
|
|
|
ebb439 |
+
|
|
|
ebb439 |
static void
|
|
|
ebb439 |
execute_get_mac_bind(const struct ovnact_get_mac_bind *bind,
|
|
|
ebb439 |
const struct ovntrace_datapath *dp,
|
|
|
ebb439 |
@@ -2315,23 +2354,23 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
case OVNACT_ICMP4:
|
|
|
ebb439 |
- execute_icmp4(ovnact_get_ICMP4(a), dp, uflow, table_id, pipeline,
|
|
|
ebb439 |
- super);
|
|
|
ebb439 |
+ execute_icmp4(ovnact_get_ICMP4(a), dp, uflow, table_id, false,
|
|
|
ebb439 |
+ pipeline, super);
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
case OVNACT_ICMP4_ERROR:
|
|
|
ebb439 |
execute_icmp4(ovnact_get_ICMP4_ERROR(a), dp, uflow, table_id,
|
|
|
ebb439 |
- pipeline, super);
|
|
|
ebb439 |
+ false, pipeline, super);
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
case OVNACT_ICMP6:
|
|
|
ebb439 |
- execute_icmp6(ovnact_get_ICMP6(a), dp, uflow, table_id, pipeline,
|
|
|
ebb439 |
- super);
|
|
|
ebb439 |
+ execute_icmp6(ovnact_get_ICMP6(a), dp, uflow, table_id, false,
|
|
|
ebb439 |
+ pipeline, super);
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
case OVNACT_ICMP6_ERROR:
|
|
|
ebb439 |
execute_icmp6(ovnact_get_ICMP6_ERROR(a), dp, uflow, table_id,
|
|
|
ebb439 |
- pipeline, super);
|
|
|
ebb439 |
+ false, pipeline, super);
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
case OVNACT_IGMP:
|
|
|
ebb439 |
@@ -2340,13 +2379,18 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len,
|
|
|
ebb439 |
|
|
|
ebb439 |
case OVNACT_TCP_RESET:
|
|
|
ebb439 |
execute_tcp_reset(ovnact_get_TCP_RESET(a), dp, uflow, table_id,
|
|
|
ebb439 |
- pipeline, super);
|
|
|
ebb439 |
+ false, pipeline, super);
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
case OVNACT_OVNFIELD_LOAD:
|
|
|
ebb439 |
execute_ovnfield_load(ovnact_get_OVNFIELD_LOAD(a), super);
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
+ case OVNACT_REJECT:
|
|
|
ebb439 |
+ execute_reject(ovnact_get_REJECT(a), dp, uflow, table_id,
|
|
|
ebb439 |
+ pipeline, super);
|
|
|
ebb439 |
+ break;
|
|
|
ebb439 |
+
|
|
|
ebb439 |
case OVNACT_TRIGGER_EVENT:
|
|
|
ebb439 |
break;
|
|
|
ebb439 |
|
|
|
ebb439 |
--
|
|
|
ebb439 |
2.26.2
|
|
|
ebb439 |
|