From patchwork Tue Feb 20 17:39:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 875800 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zmF7b0h8Gz9rxs for ; Wed, 21 Feb 2018 09:06:18 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 8208510AB; Tue, 20 Feb 2018 17:40:01 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 3602D10B1 for ; Tue, 20 Feb 2018 17:40:00 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wr0-f193.google.com (mail-wr0-f193.google.com [209.85.128.193]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 2E0C35BC for ; Tue, 20 Feb 2018 17:39:59 +0000 (UTC) Received: by mail-wr0-f193.google.com with SMTP id k9so16728419wre.9 for ; Tue, 20 Feb 2018 09:39:59 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=XHw1A8YuRtUmu3to8oZuWJuKvVTYD/vBypU8fKjg8kY=; b=BMOl/iJbSbEtfip7Y5uhCLw/3a+vQp69Fk3nX5ADq3R3d9PN+hvC2RBQf3UzogWUpj XvZApPM0VeB7QOTwD2tIiHtGAgxkx35p2sEN8wLsIGFa+LiYd7yRZMyNkQ2FYsu+I2rd eeDjMiXeCKDmFj7CTqJ+a7WHPbJIjXznD/88hC3xF0gwlLbFPyCjt1AqWWUWDNeL+w9g Wwx74Ac+eYBYUZdTBCeftkSPHEU/ktf8G69yyJ4kcwa6a2xC0SkhDvWwlqpAQ9nF1KIc Gn4BLAtLYqjhDiwe9ALdfUNAz5NT8R95C3udl19f7O37yrAYvkSlj2XOfCppckgO+TFx cynA== X-Gm-Message-State: APf1xPDGdW7o0K8stjllVPqC4JgkWHw8E+7pKL1jQYTpao5OSGIZ3OfG Mj+hhNn+qWHzPfZJfbV4P77pQEtgCnA= X-Google-Smtp-Source: AH8x226KYdl/ZvdrIQ/Y7cqNFQzyxkB4GicqoK3VIE7d1itmKuZa4W4/1/53i33WyTOayduKhpWdrQ== X-Received: by 10.223.158.193 with SMTP id b1mr420059wrf.156.1519148397503; Tue, 20 Feb 2018 09:39:57 -0800 (PST) Received: from localhost.localdomain.com (nat-pool-mxp-t.redhat.com. [149.6.153.186]) by smtp.gmail.com with ESMTPSA id g96sm18903296wrd.73.2018.02.20.09.39.56 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 20 Feb 2018 09:39:56 -0800 (PST) From: Lorenzo Bianconi To: dev@openvswitch.org Date: Tue, 20 Feb 2018 18:39:43 +0100 Message-Id: <9f8a8b12902562ff69ba096bd596a053d9323942.1519147772.git.lorenzo.bianconi@redhat.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: References: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 1/2] OVN: add icmp4{} action support X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org icmp4 action is used to replace the IPv4 packet been processed with an ICMPv4 packet initialized based on incoming IPv4 one. Ethernet and IPv4 fields not listed are not changed: - ip.proto = 1 (ICMPv4) - ip.frag = 0 (not a fragment) - ip.ttl = 255 - icmp4.type = 3 (destination unreachable) - icmp4.code = 1 (host unreachable) Prerequisite: ip4 Signed-off-by: Lorenzo Bianconi --- include/ovn/actions.h | 7 +++++++ ovn/controller/pinctrl.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++ ovn/lib/actions.c | 22 ++++++++++++++++++++ ovn/ovn-sb.xml | 5 +---- ovn/utilities/ovn-trace.c | 29 ++++++++++++++++++++++++++ tests/ovn.at | 10 +++++++++ 6 files changed, 122 insertions(+), 4 deletions(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 9554a395d..b1988d6aa 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -64,6 +64,7 @@ struct ovn_extend_table; OVNACT(CT_CLEAR, ovnact_null) \ OVNACT(CLONE, ovnact_nest) \ OVNACT(ARP, ovnact_nest) \ + OVNACT(ICMP4, ovnact_nest) \ OVNACT(ND_NA, ovnact_nest) \ OVNACT(GET_ARP, ovnact_get_mac_bind) \ OVNACT(PUT_ARP, ovnact_put_mac_bind) \ @@ -429,6 +430,12 @@ enum action_opcode { * The actions, in OpenFlow 1.3 format, follow the action_header. */ ACTION_OPCODE_ND_NS, + + /* "icmp4 { ...actions... }". + * + * The actions, in OpenFlow 1.3 format, follow the action_header. + */ + ACTION_OPCODE_ICMP4, }; /* Header. */ diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index e34916f5c..f08fbab59 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -219,6 +219,55 @@ pinctrl_handle_arp(const struct flow *ip_flow, const struct match *md, dp_packet_uninit(&packet); } +static void +pinctrl_handle_icmp4(const struct flow *ip_flow, const struct match *md, + struct ofpbuf *userdata) +{ + /* This action only works for IP packets, and the switch should only send + * us IP packets this way, but check here just to be sure. */ + if (ip_flow->dl_type != htons(ETH_TYPE_IP)) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + VLOG_WARN_RL(&rl, + "ICMP4 action on non-IP packet (eth_type 0x%"PRIx16")", + ntohs(ip_flow->dl_type)); + return; + } + + uint64_t packet_stub[128 / 8]; + struct dp_packet packet; + + dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); + dp_packet_clear(&packet); + packet.packet_type = htonl(PT_ETH); + + struct eth_header *eh = dp_packet_put_zeros(&packet, sizeof *eh); + eh->eth_dst = ip_flow->dl_dst; + eh->eth_src = ip_flow->dl_src; + eh->eth_type = htons(ETH_TYPE_IP); + + struct ip_header *nh = dp_packet_put_zeros(&packet, sizeof *nh); + dp_packet_set_l3(&packet, nh); + nh->ip_ihl_ver = IP_IHL_VER(5, 4); + nh->ip_tot_len = htons(sizeof(struct ip_header) + + sizeof(struct icmp_header)); + nh->ip_proto = IPPROTO_ICMP; + nh->ip_frag_off = htons(IP_DF); + packet_set_ipv4(&packet, ip_flow->nw_src, ip_flow->nw_dst, + ip_flow->nw_tos, 255); + + struct icmp_header *ih = dp_packet_put_zeros(&packet, sizeof *ih); + dp_packet_set_l4(&packet, ih); + packet_set_icmp(&packet, ICMP4_DST_UNREACH, 1); + + if (ip_flow->vlans[0].tci & htons(VLAN_CFI)) { + eth_push_vlan(&packet, htons(ETH_TYPE_VLAN_8021Q), + ip_flow->vlans[0].tci); + } + + set_actions_and_enqueue_msg(&packet, md, userdata); + dp_packet_uninit(&packet); +} + static void pinctrl_handle_put_dhcp_opts( struct dp_packet *pkt_in, struct ofputil_packet_in *pin, @@ -1022,6 +1071,10 @@ process_packet_in(const struct ofp_header *msg, struct controller_ctx *ctx) pinctrl_handle_nd_ns(&headers, &pin.flow_metadata, &userdata); break; + case ACTION_OPCODE_ICMP4: + pinctrl_handle_icmp4(&headers, &pin.flow_metadata, &userdata); + break; + default: VLOG_WARN_RL(&rl, "unrecognized packet-in opcode %"PRIu32, ntohl(ah->opcode)); diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c index fde3bff00..fc5ace1f6 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -1141,6 +1141,12 @@ parse_ARP(struct action_context *ctx) parse_nested_action(ctx, OVNACT_ARP, "ip4"); } +static void +parse_ICMP4(struct action_context *ctx) +{ + parse_nested_action(ctx, OVNACT_ICMP4, "ip4"); +} + static void parse_ND_NA(struct action_context *ctx) { @@ -1174,6 +1180,12 @@ format_ARP(const struct ovnact_nest *nest, struct ds *s) format_nested_action(nest, "arp", s); } +static void +format_ICMP4(const struct ovnact_nest *nest, struct ds *s) +{ + format_nested_action(nest, "icmp4", s); +} + static void format_ND_NA(const struct ovnact_nest *nest, struct ds *s) { @@ -1224,6 +1236,14 @@ encode_ARP(const struct ovnact_nest *on, encode_nested_actions(on, ep, ACTION_OPCODE_ARP, ofpacts); } +static void +encode_ICMP4(const struct ovnact_nest *on, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_nested_actions(on, ep, ACTION_OPCODE_ICMP4, ofpacts); +} + static void encode_ND_NA(const struct ovnact_nest *on, const struct ovnact_encode_params *ep, @@ -2247,6 +2267,8 @@ parse_action(struct action_context *ctx) parse_CLONE(ctx); } else if (lexer_match_id(ctx->lexer, "arp")) { parse_ARP(ctx); + } else if (lexer_match_id(ctx->lexer, "icmp4")) { + parse_ICMP4(ctx); } else if (lexer_match_id(ctx->lexer, "nd_na")) { parse_ND_NA(ctx); } else if (lexer_match_id(ctx->lexer, "nd_ns")) { diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml index f000b166c..67da8a7f4 100644 --- a/ovn/ovn-sb.xml +++ b/ovn/ovn-sb.xml @@ -1725,14 +1725,11 @@
  • ip.proto = 1 (ICMPv4)
  • ip.frag = 0 (not a fragment)
  • +
  • ip.ttl = 255 (not a fragment)
  • icmp4.type = 3 (destination unreachable)
  • icmp4.code = 1 (host unreachable)
-

- Details TBD. -

-

Prerequisite: ip4

diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index db39c4961..93094eea6 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -1535,6 +1535,30 @@ execute_nd_ns(const struct ovnact_nest *on, const struct ovntrace_datapath *dp, table_id, pipeline, &node->subs); } +static void +execute_icmp4(const struct ovnact_nest *on, + const struct ovntrace_datapath *dp, + const struct flow *uflow, uint8_t table_id, + enum ovnact_pipeline pipeline, struct ovs_list *super) +{ + struct flow icmp4_flow = *uflow; + + /* Update fields for ICMP. */ + icmp4_flow.dl_dst = uflow->dl_dst; + icmp4_flow.dl_src = uflow->dl_src; + icmp4_flow.nw_dst = uflow->nw_dst; + icmp4_flow.nw_src = uflow->nw_src; + icmp4_flow.nw_proto = IPPROTO_ICMP; + icmp4_flow.tp_src = htons(ICMP4_DST_UNREACH); /* icmp type */ + icmp4_flow.tp_dst = htons(1); /* icmp code */ + + struct ovntrace_node *node = ovntrace_node_append( + super, OVNTRACE_NODE_TRANSFORMATION, "icmp4"); + + trace_actions(on->nested, on->nested_len, dp, &icmp4_flow, + table_id, pipeline, &node->subs); +} + static void execute_get_mac_bind(const struct ovnact_get_mac_bind *bind, const struct ovntrace_datapath *dp, @@ -1893,6 +1917,11 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, case OVNACT_SET_METER: /* Nothing to do. */ break; + + case OVNACT_ICMP4: + execute_icmp4(ovnact_get_ICMP4(a), dp, uflow, table_id, pipeline, + super); + break; } } diff --git a/tests/ovn.at b/tests/ovn.at index 8ee3bf0b5..37e63810d 100644 --- a/tests/ovn.at +++ b/tests/ovn.at @@ -1125,6 +1125,16 @@ reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = "1500", slla = ae:01:02:03:0 reg1[0] = put_nd_ra_opts(addr_mode = "slaac", mtu = 10.0.0.4, slla = ae:01:02:03:04:10); Invalid value for "mtu" option +# icmp4 +icmp4 { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output; + encodes as controller(userdata=00.00.00.0a.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 ip4 + +icmp4 { }; + formats as icmp4 { drop; }; + encodes as controller(userdata=00.00.00.0a.00.00.00.00) + has prereqs ip4 + # Contradictionary prerequisites (allowed but not useful): ip4.src = ip6.src[0..31]; encodes as move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[]