From patchwork Wed Jan 10 17:58:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 858452 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 3zGxc72rDlz9ryQ for ; Thu, 11 Jan 2018 04:59:51 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 7D0E1FD9; Wed, 10 Jan 2018 17:59:23 +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 CEC5AFCC for ; Wed, 10 Jan 2018 17:59:21 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-wm0-f65.google.com (mail-wm0-f65.google.com [74.125.82.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 28FF114E for ; Wed, 10 Jan 2018 17:59:21 +0000 (UTC) Received: by mail-wm0-f65.google.com with SMTP id b76so658284wmg.1 for ; Wed, 10 Jan 2018 09:59:21 -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=y3vxIPWirgoGZQsJoQDB8yF+2k5Zrei3g1k7VUIdVxE=; b=Duw2HH7OsSHgEpiZu+jXQTPxwV+STRli7KobPyA6S+sxDyr5Wk3P3qyQvUI80kVDyE pZeRRr3DT8Yjg6H1NHc1IpneyU+F4m5rvnYE3f9MQdSxv4Sobi5Ee1UWRj96775AFdJ5 FI0JroIt6uUCv9qLFXbAb5o861a46J+BOC6u+X5u9MBvI/1mahdKXuB1kQbfFlZ6ZymD zFXmV0c/SplI9sMXluw4/XZqvLsQM5xuXCdywEeurq691/+8ihvz5kPCXI/61RwCrk7m jL5rBu6S7XGS8jPhzIIkFerx9wn8oBQRwX523j76A7imBQuS4l9OfAS3qiNUBH+Cx9vH /i4g== X-Gm-Message-State: AKGB3mL5CpJRtnzCsvT1kFwURJD9IkEejdGE2EDctsmxQAZsiWS9ePDN Lv/RfxiM7cJ+l6SO/7bS8fIIQZxzBbg= X-Google-Smtp-Source: ACJfBosbBPia9jKqkglUmRUPFTxFOByyc/ym48kMDgbKfOWRBh8S24HgDUAFbgk/5aMwxWmzXmcb7g== X-Received: by 10.28.107.65 with SMTP id g62mr14555896wmc.80.1515607159546; Wed, 10 Jan 2018 09:59:19 -0800 (PST) Received: from localhost.localdomain.com (nat-pool-mxp-t.redhat.com. [149.6.153.186]) by smtp.gmail.com with ESMTPSA id 187sm23591636wmu.19.2018.01.10.09.59.18 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 10 Jan 2018 09:59:19 -0800 (PST) From: Lorenzo Bianconi To: dev@openvswitch.org Date: Wed, 10 Jan 2018 18:58:59 +0100 Message-Id: X-Mailer: git-send-email 2.13.6 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] [RFC 1/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 - ip.frag = 0 - icmp4.type = 3 - icmp4.code = 1 Prerequisite: ip4 Signed-off-by: Lorenzo Bianconi --- include/ovn/actions.h | 7 +++++++ ovn/controller/pinctrl.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ ovn/lib/actions.c | 22 +++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/include/ovn/actions.h b/include/ovn/actions.h index 85a484ffa..027562c57 100644 --- a/include/ovn/actions.h +++ b/include/ovn/actions.h @@ -63,6 +63,7 @@ struct simap; 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) \ @@ -438,6 +439,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 7542db3f4..bae804eff 100644 --- a/ovn/controller/pinctrl.c +++ b/ovn/controller/pinctrl.c @@ -218,6 +218,53 @@ pinctrl_handle_arp(const struct flow *ip_flow, const struct match *md, } 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 = 0x45; + nh->ip_tot_len = htons(sizeof(struct ip_header) + + sizeof(struct icmp_header)); + nh->ip_proto = 1; + nh->ip_frag_off = 0x40; + 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, 3, 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, struct ofpbuf *userdata, struct ofpbuf *continuation) @@ -1013,6 +1060,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 69a2172a8..66362ad37 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -1186,6 +1186,12 @@ parse_ARP(struct action_context *ctx) } static void +parse_ICMP(struct action_context *ctx) +{ + parse_nested_action(ctx, OVNACT_ICMP, "ip4"); +} + +static void parse_ND_NA(struct action_context *ctx) { parse_nested_action(ctx, OVNACT_ND_NA, "nd_ns"); @@ -1219,6 +1225,12 @@ format_ARP(const struct ovnact_nest *nest, struct ds *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) { format_nested_action(nest, "nd_na", s); @@ -1269,6 +1281,14 @@ encode_ARP(const struct ovnact_nest *on, } static void +encode_ICMP(const struct ovnact_nest *on, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + encode_nested_neighbor_actions(on, ep, ACTION_OPCODE_ICMP, ofpacts); +} + +static void encode_ND_NA(const struct ovnact_nest *on, const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) @@ -2210,6 +2230,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")) {