From patchwork Wed Jan 20 06:15:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Horman X-Patchwork-Id: 570524 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (unknown [IPv6:2600:3c00::f03c:91ff:fe6e:bdf7]) by ozlabs.org (Postfix) with ESMTP id CCBFC140BF8 for ; Wed, 20 Jan 2016 17:15:45 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=netronome-com.20150623.gappssmtp.com header.i=@netronome-com.20150623.gappssmtp.com header.b=cY+wjU+S; dkim-atps=neutral Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id A11BD108F3; Tue, 19 Jan 2016 22:15:32 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e3.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id 8B06A108DB for ; Tue, 19 Jan 2016 22:15:31 -0800 (PST) Received: from bar5.cudamail.com (localhost [127.0.0.1]) by mx1e3.cudamail.com (Postfix) with ESMTPS id 0070642004F for ; Tue, 19 Jan 2016 23:15:31 -0700 (MST) X-ASG-Debug-ID: 1453270529-09eadd63be1a3f20001-byXFYA Received: from mx1-pf2.cudamail.com ([192.168.24.2]) by bar5.cudamail.com with ESMTP id BD2Jz8BXekafIiMR (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 19 Jan 2016 23:15:29 -0700 (MST) X-Barracuda-Envelope-From: simon.horman@netronome.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.2 Received: from unknown (HELO mail-pf0-f173.google.com) (209.85.192.173) by mx1-pf2.cudamail.com with ESMTPS (RC4-SHA encrypted); 20 Jan 2016 06:15:29 -0000 Received-SPF: none (mx1-pf2.cudamail.com: domain at netronome.com does not designate permitted sender hosts) X-Barracuda-RBL-Trusted-Forwarder: 209.85.192.173 Received: by mail-pf0-f173.google.com with SMTP id 65so188751740pff.2 for ; Tue, 19 Jan 2016 22:15:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netronome-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=uH4HcuM4YZZ8oAVR/GsW8DTUU8HMM2T/07QCRrNLz1g=; b=cY+wjU+SYtEgvJ4t6T7ugTn+FrtzFodOjCaj7rRKW2XAcKKpyxwEUVgsgA2rHcnzEz 1tsg3J/8TYCk52SM50U1pO34i8CqatvLzRWAjEfMg9RpHC0HBHQCaG4dn0rfU4V2UmTM wKiE6bxBXsiQ9kAVgM240E7kJLUGEyV9uuw//SYVPMRftLZIHk3qBna/HObmrBuSP0In 43hUzt5VjlkAgd56kqCfCDXjgX75A3nOXKdEvm1mHW8kjxMopIHhLdLL3Yzgkgg3g56L KpetF5aSwpafg/PqQ4iM53gW9lYI9VcGEjs9DVtoQpKKa5I6o+tDJaC8GMYYB5e1Iwe5 TC/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=uH4HcuM4YZZ8oAVR/GsW8DTUU8HMM2T/07QCRrNLz1g=; b=g0VQOHn/dNuUU5Fem0potMwFkBmB3mqZIDa2Ivkpi9/NdDy9IfWhUY8OwFzdnDbyKt 0JQLnEJ3b7NhLKt3tCPdpTYNs3rLqyu2wXt3eSMJmr/VqjDriqP13r4dns2hMF3vyMAb wXq/AfQWJAVgONriycvWcyguI03MYZAiLgwWhs6aDSr4lceLFeznV6seKo23BmIPgDa4 fijKSofCIrqKLZPDewR6GEySFdul91c2kY8EKyPW4BPHPpvaUSKqlysbTynQdT1tceWR qGx6e3ywIF0JqIQ7wopFp/9oaX/3r14Hw0HbFTSCwtPwzXLCZMkmUkpOMp/HxJdI3V6S 32iQ== X-Gm-Message-State: ALoCoQmolT259SuJYGpGfLOqTHS4GsmP9mBLhxLVEZ0csGjrk8wcvnyola4vfF85fblwsMBjQFnD2PXwE1mZCpt0fhhyVVsjQg== X-Received: by 10.98.16.72 with SMTP id y69mr50003323pfi.95.1453270528969; Tue, 19 Jan 2016 22:15:28 -0800 (PST) Received: from reginn.isobedori.kobe.vergenet.net (p5023-ipbfp803kobeminato.hyogo.ocn.ne.jp. [123.221.39.23]) by smtp.gmail.com with ESMTPSA id c86sm45624949pfd.75.2016.01.19.22.15.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 19 Jan 2016 22:15:27 -0800 (PST) X-CudaMail-Envelope-Sender: simon.horman@netronome.com X-Barracuda-Apparent-Source-IP: 123.221.39.23 From: Simon Horman To: dev@openvswitch.org X-CudaMail-MID: CM-E2-118108511 X-CudaMail-DTE: 011916 X-CudaMail-Originating-IP: 209.85.192.173 Date: Wed, 20 Jan 2016 15:15:02 +0900 X-ASG-Orig-Subj: [##CM-E2-118108511##][PATCH v9 3/7] userspace: add support for pop_eth and push_eth actions Message-Id: <1453270506-10643-4-git-send-email-simon.horman@netronome.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1453270506-10643-1-git-send-email-simon.horman@netronome.com> References: <1453270506-10643-1-git-send-email-simon.horman@netronome.com> X-GBUdb-Analysis: 0, 209.85.192.173, Ugly c=0.446283 p=-0.368421 Source Normal X-MessageSniffer-Rules: 0-0-0-22195-c X-Barracuda-Connect: UNKNOWN[192.168.24.2] X-Barracuda-Start-Time: 1453270529 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.10 X-Barracuda-Spam-Status: No, SCORE=1.10 using per-user scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_RULE7568M, BSF_SC5_MJ1963, DKIM_SIGNED, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.26288 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.50 BSF_RULE7568M Custom Rule 7568M 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Cc: Simon Horman Subject: [ovs-dev] [PATCH v9 3/7] userspace: add support for pop_eth and push_eth actions X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" From: Lorand Jakab These actions will allow L2->L3 and L3->L2 switching, and are supposed to be added to flows installed in the datapath transparently by ovs-vswitchd. Signed-off-by: Lorand Jakab Signed-off-by: Simon Horman --- v9 [Simon Horman] * Rebased v1 - v8 [Lorand Jakub] --- datapath/linux/compat/include/linux/openvswitch.h | 13 +++++ lib/dpif-netdev.c | 2 + lib/dpif.c | 2 + lib/odp-execute.c | 18 ++++++ lib/odp-util.c | 69 ++++++++++++++++++++++- lib/odp-util.h | 5 ++ lib/packets.c | 25 ++++++++ lib/packets.h | 4 ++ ofproto/ofproto-dpif-sflow.c | 7 +++ 9 files changed, 143 insertions(+), 2 deletions(-) diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 3b39ebbc3d6a..8548d3b8b86b 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -739,6 +739,16 @@ enum ovs_nat_attr { #define OVS_NAT_ATTR_MAX (__OVS_NAT_ATTR_MAX - 1) /** + * struct ovs_action_push_eth - %OVS_ACTION_ATTR_PUSH_ETH action argument. + * @addresses: Source and destination MAC addresses. + * @eth_type: Ethernet type + */ +struct ovs_action_push_eth { + struct ovs_key_ethernet addresses; + __be16 eth_type; +}; + +/** * enum ovs_action_attr - Action types. * * @OVS_ACTION_ATTR_OUTPUT: Output packet to port. @@ -802,11 +812,14 @@ enum ovs_action_attr { * The data must be zero for the unmasked * bits. */ OVS_ACTION_ATTR_CT, /* Nested OVS_CT_ATTR_* . */ + OVS_ACTION_ATTR_PUSH_ETH, /* struct ovs_action_push_eth. */ + OVS_ACTION_ATTR_POP_ETH, /* No argument. */ #ifndef __KERNEL__ OVS_ACTION_ATTR_TUNNEL_PUSH, /* struct ovs_action_push_tnl*/ OVS_ACTION_ATTR_TUNNEL_POP, /* u32 port number. */ #endif + __OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted * from userspace. */ diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index cd72e624245e..c4416f69b1e8 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -3629,6 +3629,8 @@ dp_execute_cb(void *aux_, struct dp_packet **packets, int cnt, case OVS_ACTION_ATTR_SET_MASKED: case OVS_ACTION_ATTR_SAMPLE: case OVS_ACTION_ATTR_HASH: + case OVS_ACTION_ATTR_PUSH_ETH: + case OVS_ACTION_ATTR_POP_ETH: case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: OVS_NOT_REACHED(); diff --git a/lib/dpif.c b/lib/dpif.c index 38e40bac9ab4..379984dbf97f 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1146,6 +1146,8 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet **packets, int cnt, case OVS_ACTION_ATTR_SET: case OVS_ACTION_ATTR_SET_MASKED: case OVS_ACTION_ATTR_SAMPLE: + case OVS_ACTION_ATTR_PUSH_ETH: + case OVS_ACTION_ATTR_POP_ETH: case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: OVS_NOT_REACHED(); diff --git a/lib/odp-execute.c b/lib/odp-execute.c index b5204b270677..3d553a7d3090 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -503,6 +503,8 @@ requires_datapath_assistance(const struct nlattr *a) case OVS_ACTION_ATTR_HASH: case OVS_ACTION_ATTR_PUSH_MPLS: case OVS_ACTION_ATTR_POP_MPLS: + case OVS_ACTION_ATTR_POP_ETH: + case OVS_ACTION_ATTR_PUSH_ETH: return false; case OVS_ACTION_ATTR_UNSPEC: @@ -623,6 +625,22 @@ odp_execute_actions(void *dp, struct dp_packet **packets, int cnt, bool steal, } break; + case OVS_ACTION_ATTR_PUSH_ETH: { + const struct ovs_action_push_eth *eth = nl_attr_get(a); + + for (i = 0; i < cnt; i++) { + push_eth(packets[i], ð->addresses.eth_dst, + ð->addresses.eth_src, eth->eth_type); + } + break; + } + + case OVS_ACTION_ATTR_POP_ETH: + for (i = 0; i < cnt; i++) { + pop_eth(packets[i]); + } + break; + case OVS_ACTION_ATTR_OUTPUT: case OVS_ACTION_ATTR_TUNNEL_PUSH: case OVS_ACTION_ATTR_TUNNEL_POP: diff --git a/lib/odp-util.c b/lib/odp-util.c index 346064d56413..f8f8c0ffbe6e 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -120,6 +120,8 @@ odp_action_len(uint16_t type) case OVS_ACTION_ATTR_SET_MASKED: return ATTR_LEN_VARIABLE; case OVS_ACTION_ATTR_SAMPLE: return ATTR_LEN_VARIABLE; case OVS_ACTION_ATTR_CT: return ATTR_LEN_VARIABLE; + case OVS_ACTION_ATTR_PUSH_ETH: return sizeof(struct ovs_action_push_eth); + case OVS_ACTION_ATTR_POP_ETH: return 0; case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: @@ -827,6 +829,18 @@ format_odp_action(struct ds *ds, const struct nlattr *a) format_odp_key_attr(nl_attr_get(a), NULL, NULL, ds, true); ds_put_cstr(ds, ")"); break; + case OVS_ACTION_ATTR_PUSH_ETH: { + const struct ovs_action_push_eth *eth = nl_attr_get(a); + ds_put_format(ds, "push_eth(src="ETH_ADDR_FMT",dst="ETH_ADDR_FMT + ",type=0x%04"PRIx16")", + ETH_ADDR_ARGS(eth->addresses.eth_src), + ETH_ADDR_ARGS(eth->addresses.eth_dst), + ntohs(eth->eth_type)); + break; + } + case OVS_ACTION_ATTR_POP_ETH: + ds_put_cstr(ds, "pop_eth"); + break; case OVS_ACTION_ATTR_PUSH_VLAN: { const struct ovs_action_push_vlan *vlan = nl_attr_get(a); ds_put_cstr(ds, "push_vlan("); @@ -1011,14 +1025,43 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions) odp_put_userspace_action(pid, user_data, user_data_size, tunnel_out_port, include_actions, actions); res = n + n1; + goto out; } else if (s[n] == ')') { odp_put_userspace_action(pid, user_data, user_data_size, ODPP_NONE, include_actions, actions); res = n + 1; - } else { - res = -EINVAL; + goto out; + } + } + + { + struct ovs_action_push_eth push; + int eth_type = 0; + int n1 = -1; + + if (ovs_scan(&s[n], "push_eth(src="ETH_ADDR_SCAN_FMT"," + "dst="ETH_ADDR_SCAN_FMT",type=%i)%n", + ETH_ADDR_SCAN_ARGS(push.addresses.eth_src), + ETH_ADDR_SCAN_ARGS(push.addresses.eth_dst), + ð_type, &n1)) { + + push.eth_type = htons(eth_type); + + nl_msg_put_unspec(actions, OVS_ACTION_ATTR_PUSH_ETH, + &push, sizeof push); + + res = n + n1; + goto out; } } + + if (!strncmp(&s[n], "pop_eth", 7)) { + nl_msg_put_flag(actions, OVS_ACTION_ATTR_POP_ETH); + res = 7; + goto out; + } + + res = -EINVAL; out: ofpbuf_uninit(&buf); return res; @@ -5291,6 +5334,28 @@ odp_put_userspace_action(uint32_t pid, } void +odp_put_pop_eth_action(struct ofpbuf *odp_actions) +{ + nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_ETH); +} + +void +odp_put_push_eth_action(struct ofpbuf *odp_actions, + const struct eth_addr *eth_src, + const struct eth_addr *eth_dst, + const ovs_be16 eth_type) +{ + struct ovs_action_push_eth eth; + + eth.addresses.eth_src = *eth_src; + eth.addresses.eth_dst = *eth_dst; + eth.eth_type = eth_type; + + nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_ETH, + ð, sizeof eth); +} + +void odp_put_tunnel_action(const struct flow_tnl *tunnel, struct ofpbuf *odp_actions) { diff --git a/lib/odp-util.h b/lib/odp-util.h index 51cf5c3680e9..4d797533f32c 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -317,6 +317,11 @@ size_t odp_put_userspace_action(uint32_t pid, odp_port_t tunnel_out_port, bool include_actions, struct ofpbuf *odp_actions); +void odp_put_pop_eth_action(struct ofpbuf *odp_actions); +void odp_put_push_eth_action(struct ofpbuf *odp_actions, + const struct eth_addr *eth_src, + const struct eth_addr *eth_dst, + const ovs_be16 eth_type); void odp_put_tunnel_action(const struct flow_tnl *tunnel, struct ofpbuf *odp_actions); diff --git a/lib/packets.c b/lib/packets.c index d82341d71829..9e44253e98e9 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -220,6 +220,31 @@ eth_pop_vlan(struct dp_packet *packet) } } +/* Push Ethernet header onto 'packet' assuming it is layer 3 */ +void +push_eth(struct dp_packet *packet, const struct eth_addr *dst, + const struct eth_addr *src, ovs_be16 type) +{ + struct eth_header *eh; + + eh = dp_packet_resize_l2(packet, ETH_HEADER_LEN); + eh->eth_dst = *dst; + eh->eth_src = *src; + eh->eth_type = type; +} + +/* Removes Ethernet header, including all VLAN and MPLS headers, from 'packet'. + * + * Previous to calling this function, 'ofpbuf_l3(packet)' must not be NULL */ +void +pop_eth(struct dp_packet *packet) +{ + ovs_assert(dp_packet_l3(packet) != NULL); + + dp_packet_resize_l2_5(packet, -packet->l3_ofs); + dp_packet_set_l2_5(packet, NULL); +} + /* Set ethertype of the packet. */ static void set_ethertype(struct dp_packet *packet, ovs_be16 eth_type) diff --git a/lib/packets.h b/lib/packets.h index 834e8a4986f0..f761af906aed 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -390,6 +390,10 @@ struct eth_header { }); BUILD_ASSERT_DECL(ETH_HEADER_LEN == sizeof(struct eth_header)); +void push_eth(struct dp_packet *packet, const struct eth_addr *dst, + const struct eth_addr *src, ovs_be16 type); +void pop_eth(struct dp_packet *packet); + #define LLC_DSAP_SNAP 0xaa #define LLC_SSAP_SNAP 0xaa #define LLC_CNTL_SNAP 3 diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index f11699cd9401..015ea96c9c92 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -1171,6 +1171,13 @@ dpif_sflow_read_actions(const struct flow *flow, dpif_sflow_pop_mpls_lse(sflow_actions); break; } + case OVS_ACTION_ATTR_PUSH_ETH: + case OVS_ACTION_ATTR_POP_ETH: + /* TODO: SFlow does not currently define a MAC-in-MAC + * encapsulation structure. We could use an extension + * structure to report this. + */ + break; case OVS_ACTION_ATTR_SAMPLE: case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: