From patchwork Tue Feb 13 14:43:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 872884 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 3zglgw0tTDz9s7h for ; Wed, 14 Feb 2018 01:45:16 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 29870100C; Tue, 13 Feb 2018 14:44:18 +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 831241010 for ; Tue, 13 Feb 2018 14:44:17 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wr0-f194.google.com (mail-wr0-f194.google.com [209.85.128.194]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 9229C35F for ; Tue, 13 Feb 2018 14:44:16 +0000 (UTC) Received: by mail-wr0-f194.google.com with SMTP id w77so4372071wrc.6 for ; Tue, 13 Feb 2018 06:44:16 -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=RI0qpfjE/9wnxoUUGwTHIK+sbOtZLYEFiaJ/c70PfKo=; b=Cb6Dbyb1NH3U+Y0ej8cveR5gPs+LLGmN2vqtfGEJURvPRO0cn+LGSawf2EU/0WYc5B FkkA1H3hnaVhlM5N/cfkHAEAT1g46eTfqOCqqysVTW79M4YRLiCYZfAlVuG1A1CIYHER yLNOuojgQoCVkjG//RZAoI98JgKq2aQmbkXIb2kaf8pVqG5M1GuRplYEKAwM1ZUfstXB 6oSvWuQNZAsiEc2SoATsGNgvtQfjusUuS58DqHeBdO9+e9TB/AAh4hH4vPlpVkJEpScD eGuZhQT5QOP/5tgNTBPE7L4Dz9FD/4nSa8VoIC8Sme1jZXRcTtowr86vatyImIEeCXGf 21MA== X-Gm-Message-State: APf1xPB3gruGMGZXz1G6RK0RmQvT1OYZZzE7AuOBty0vNd5BOOTUMO8G foEOdtP4yq8ETdsOh1rxPOjAd9s1htQ= X-Google-Smtp-Source: AH8x224ijKjFTak3CpcobragvIoO47C3J2EpMN60eAaOYzasyF7fii4ekGW8HhVMPARJnjERYQ1gWw== X-Received: by 10.223.145.199 with SMTP id 65mr1404543wri.264.1518533054927; Tue, 13 Feb 2018 06:44:14 -0800 (PST) Received: from localhost.localdomain.com (nat-pool-mxp-t.redhat.com. [149.6.153.186]) by smtp.gmail.com with ESMTPSA id q186sm10771004wmb.33.2018.02.13.06.44.14 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 13 Feb 2018 06:44:14 -0800 (PST) From: Lorenzo Bianconi To: dev@openvswitch.org Date: Tue, 13 Feb 2018 15:43:51 +0100 Message-Id: <50f10aa459107d9d58d638c31f04ba7f0783f7aa.1518532822.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 2/3] 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) - 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 | 51 +++++++++++++++++++++++++++++++++++++++++++++++ ovn/lib/actions.c | 22 ++++++++++++++++++++ ovn/ovn-sb.xml | 4 ---- ovn/utilities/ovn-trace.c | 28 ++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 4 deletions(-) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 9554a395d..16bea3f41 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(ICMP, 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_ICMP, }; /* Header. */ diff --git a/ovn/controller/pinctrl.c b/ovn/controller/pinctrl.c index 14c95ff54..6fe0f64dd 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -217,6 +217,53 @@ pinctrl_handle_arp(const struct flow *ip_flow, const struct match *md, dp_packet_uninit(&packet); } +static void +pinctrl_handle_icmp(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, "ICMP action on non-IP packet (Ethertype %"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, 0, 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, @@ -1020,6 +1067,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_ICMP: + pinctrl_handle_icmp(&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..6e1bf541e 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_ICMP(struct action_context *ctx) +{ + parse_nested_action(ctx, OVNACT_ICMP, "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_ICMP(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_ICMP(const struct ovnact_nest *on, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_nested_actions(on, ep, ACTION_OPCODE_ICMP, 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_ICMP(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..1d8d7e604 100644 --- a/ovn/ovn-sb.xml +++ b/ovn/ovn-sb.xml @@ -1729,10 +1729,6 @@
  • icmp4.code = 1 (host unreachable)
  • -

    - Details TBD. -

    -

    Prerequisite: ip4

    diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index 7e88594fa..9f06d28b4 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -1534,6 +1534,29 @@ execute_nd_ns(const struct ovnact_nest *on, const struct ovntrace_datapath *dp, table_id, pipeline, &node->subs); } +static void +execute_icmp(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 icmp_flow = *uflow; + + /* Update fields for ICMP. */ + icmp_flow.dl_dst = uflow->dl_dst; + icmp_flow.dl_src = uflow->dl_src; + icmp_flow.nw_dst = uflow->nw_dst; + icmp_flow.nw_src = uflow->nw_src; + icmp_flow.nw_proto = IPPROTO_ICMP; + icmp_flow.tp_src = htons(ICMP4_DST_UNREACH); /* icmp type */ + icmp_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, &icmp_flow, + table_id, pipeline, &node->subs); +} + static void execute_get_mac_bind(const struct ovnact_get_mac_bind *bind, const struct ovntrace_datapath *dp, @@ -1892,6 +1915,11 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, case OVNACT_SET_METER: /* Nothing to do. */ break; + + case OVNACT_ICMP: + execute_icmp(ovnact_get_ICMP(a), dp, uflow, table_id, pipeline, + super); + break; } }