From patchwork Mon Feb 6 13:04:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yang, Yi" X-Patchwork-Id: 724438 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 3vH4mn1CZHz9s2P for ; Mon, 6 Feb 2017 22:21:45 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id CB8DCB3F; Mon, 6 Feb 2017 11:20:07 +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 6DBBFA87 for ; Mon, 6 Feb 2017 11:20:05 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id A448CE0 for ; Mon, 6 Feb 2017 11:20:04 +0000 (UTC) Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga103.fm.intel.com with ESMTP; 06 Feb 2017 03:20:04 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.33,342,1477983600"; d="scan'208,223"; a="61666224" Received: from unknown (HELO localhost.localdomain.bj.intel.com) ([10.240.224.185]) by fmsmga005.fm.intel.com with ESMTP; 06 Feb 2017 03:20:03 -0800 From: Yi Yang To: dev@openvswitch.org Date: Mon, 6 Feb 2017 21:04:37 +0800 Message-Id: <1486386290-94788-4-git-send-email-yi.y.yang@intel.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1486386290-94788-1-git-send-email-yi.y.yang@intel.com> References: <1486386290-94788-1-git-send-email-yi.y.yang@intel.com> X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: "David S. Miller" , Jiri Benc Subject: [ovs-dev] [PATCH v3 03/16] datapath: pass mac_proto to ovs_vport_send 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 From net-next commit e2d9d8358cb961340ef88620b6a25ba4557033d5 We'll need it to alter packets sent to ARPHRD_NONE interfaces. Change do_output() to use the actual L2 header size of the packet when deciding on the minimum cutlen. The assumption here is that what matters is not the output interface hard_header_len but rather the L2 header of the particular packet. For example, ARPHRD_NONE tunnels that encapsulate Ethernet should get at least the Ethernet header. Signed-off-by: Jiri Benc Acked-by: Pravin B Shelar Signed-off-by: David S. Miller Signed-off-by: Yi Yang --- datapath/actions.c | 29 +++++++++++++++++------------ datapath/vport.c | 2 +- datapath/vport.h | 2 +- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/datapath/actions.c b/datapath/actions.c index c47aa3d..c5b5b0e 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -64,6 +64,7 @@ struct ovs_frag_data { __u16 vlan_tci; __be16 vlan_proto; unsigned int l2_len; + u8 mac_proto; u8 l2_data[MAX_L2_LEN]; }; @@ -661,7 +662,7 @@ static int ovs_vport_output(OVS_VPORT_OUTPUT_PARAMS) skb_postpush_rcsum(skb, skb->data, data->l2_len); skb_reset_mac_header(skb); - ovs_vport_send(vport, skb); + ovs_vport_send(vport, skb, data->mac_proto); return 0; } @@ -679,7 +680,8 @@ static struct dst_ops ovs_dst_ops = { /* prepare_frag() is called once per (larger-than-MTU) frame; its inverse is * ovs_vport_output(), which is called once per fragmented packet. */ -static void prepare_frag(struct vport *vport, struct sk_buff *skb) +static void prepare_frag(struct vport *vport, struct sk_buff *skb, + u8 mac_proto) { unsigned int hlen = skb_network_offset(skb); struct ovs_frag_data *data; @@ -691,6 +693,7 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb) data->inner_protocol = ovs_skb_get_inner_protocol(skb); data->vlan_tci = skb->vlan_tci; data->vlan_proto = skb->vlan_proto; + data->mac_proto = mac_proto; data->l2_len = hlen; memcpy(&data->l2_data, skb->data, hlen); @@ -699,18 +702,19 @@ static void prepare_frag(struct vport *vport, struct sk_buff *skb) } static void ovs_fragment(struct net *net, struct vport *vport, - struct sk_buff *skb, u16 mru, __be16 ethertype) + struct sk_buff *skb, u16 mru, + struct sw_flow_key *key) { if (skb_network_offset(skb) > MAX_L2_LEN) { OVS_NLERR(1, "L2 header too long to fragment"); goto err; } - if (ethertype == htons(ETH_P_IP)) { + if (key->eth.type == htons(ETH_P_IP)) { struct dst_entry ovs_dst; unsigned long orig_dst; - prepare_frag(vport, skb); + prepare_frag(vport, skb, ovs_key_mac_proto(key)); dst_init(&ovs_dst, &ovs_dst_ops, NULL, 1, DST_OBSOLETE_NONE, DST_NOCOUNT); ovs_dst.dev = vport->dev; @@ -721,7 +725,7 @@ static void ovs_fragment(struct net *net, struct vport *vport, ip_do_fragment(net, skb->sk, skb, ovs_vport_output); refdst_drop(orig_dst); - } else if (ethertype == htons(ETH_P_IPV6)) { + } else if (key->eth.type == htons(ETH_P_IPV6)) { const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops(); unsigned long orig_dst; struct rt6_info ovs_rt; @@ -730,7 +734,8 @@ static void ovs_fragment(struct net *net, struct vport *vport, goto err; } - prepare_frag(vport, skb); + prepare_frag(vport, skb, + ovs_key_mac_proto(key)); memset(&ovs_rt, 0, sizeof(ovs_rt)); dst_init(&ovs_rt.dst, &ovs_dst_ops, NULL, 1, DST_OBSOLETE_NONE, DST_NOCOUNT); @@ -747,7 +752,7 @@ static void ovs_fragment(struct net *net, struct vport *vport, refdst_drop(orig_dst); } else { WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.", - ovs_vport_name(vport), ntohs(ethertype), mru, + ovs_vport_name(vport), ntohs(key->eth.type), mru, vport->dev->mtu); goto err; } @@ -767,19 +772,19 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port, u32 cutlen = OVS_CB(skb)->cutlen; if (unlikely(cutlen > 0)) { - if (skb->len - cutlen > ETH_HLEN) + if (skb->len - cutlen > ovs_mac_header_len(key)) pskb_trim(skb, skb->len - cutlen); else - pskb_trim(skb, ETH_HLEN); + pskb_trim(skb, ovs_mac_header_len(key)); } if (likely(!mru || (skb->len <= mru + vport->dev->hard_header_len))) { - ovs_vport_send(vport, skb); + ovs_vport_send(vport, skb, ovs_key_mac_proto(key)); } else if (mru <= vport->dev->mtu) { struct net *net = ovs_dp_get_net(dp); - ovs_fragment(net, vport, skb, mru, key->eth.type); + ovs_fragment(net, vport, skb, mru, key); } else { OVS_NLERR(true, "Cannot fragment IP frames"); kfree_skb(skb); diff --git a/datapath/vport.c b/datapath/vport.c index c7ed9ea..282d513 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -541,7 +541,7 @@ static unsigned int packet_length(const struct sk_buff *skb, return length; } -void ovs_vport_send(struct vport *vport, struct sk_buff *skb) +void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto) { int mtu = vport->dev->mtu; diff --git a/datapath/vport.h b/datapath/vport.h index 47995be..853107c 100644 --- a/datapath/vport.h +++ b/datapath/vport.h @@ -201,6 +201,6 @@ int __ovs_vport_ops_register(struct vport_ops *ops); }) void ovs_vport_ops_unregister(struct vport_ops *ops); -void ovs_vport_send(struct vport *vport, struct sk_buff *skb); +void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto); #endif /* vport.h */