From patchwork Tue Jan 12 22:26:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thadeu Lima de Souza Cascardo X-Patchwork-Id: 566756 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 D196B1402A1 for ; Wed, 13 Jan 2016 09:26:14 +1100 (AEDT) Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 5DB0710A1D; Tue, 12 Jan 2016 14:26:13 -0800 (PST) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx1e4.cudamail.com (mx1.cudamail.com [69.90.118.67]) by archives.nicira.com (Postfix) with ESMTPS id 278FB10A0C for ; Tue, 12 Jan 2016 14:26:12 -0800 (PST) Received: from bar2.cudamail.com (unknown [192.168.21.12]) by mx1e4.cudamail.com (Postfix) with ESMTPS id A6EA31E02AF for ; Tue, 12 Jan 2016 15:26:11 -0700 (MST) X-ASG-Debug-ID: 1452637570-03dc531c903c7e0001-byXFYA Received: from mx1-pf2.cudamail.com ([192.168.24.2]) by bar2.cudamail.com with ESMTP id zGiZsHpMbQRy8fCb (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 12 Jan 2016 15:26:10 -0700 (MST) X-Barracuda-Envelope-From: cascardo@redhat.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.24.2 Received: from unknown (HELO mx1.redhat.com) (209.132.183.28) by mx1-pf2.cudamail.com with ESMTPS (DHE-RSA-AES256-SHA encrypted); 12 Jan 2016 22:26:09 -0000 Received-SPF: pass (mx1-pf2.cudamail.com: SPF record at _spf1.redhat.com designates 209.132.183.28 as permitted sender) X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-Barracuda-RBL-IP: 209.132.183.28 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id 0249333BF3; Tue, 12 Jan 2016 22:26:07 +0000 (UTC) Received: from indiana.gru.redhat.com (ovpn-113-43.phx2.redhat.com [10.3.113.43]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u0CMQ3wI014828 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 12 Jan 2016 17:26:06 -0500 Date: Tue, 12 Jan 2016 20:26:03 -0200 X-CudaMail-Envelope-Sender: cascardo@redhat.com From: Thadeu Lima de Souza Cascardo To: Sugesh Chandran X-CudaMail-MID: CM-E2-111090121 X-CudaMail-DTE: 011216 X-CudaMail-Originating-IP: 209.132.183.28 Message-ID: <20160112222601.GH13957@indiana.gru.redhat.com> X-ASG-Orig-Subj: [##CM-E2-111090121##]Re: [PATCH] ipv6 tunneling: Fix for performance drop introduced by ipv6 tunnel support. References: <1452606524-84399-1-git-send-email-sugesh.chandran@intel.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1452606524-84399-1-git-send-email-sugesh.chandran@intel.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-GBUdb-Analysis: 0, 209.132.183.28, Ugly c=0.142858 p=-0.5 Source Normal X-MessageSniffer-Rules: 0-0-0-32767-c X-Barracuda-Connect: UNKNOWN[192.168.24.2] X-Barracuda-Start-Time: 1452637570 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: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.5 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=4.0 tests=BSF_RULE7568M, BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.26070 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.50 BSF_RULE7568M Custom Rule 7568M 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS Cc: dev@openvswitch.org, jbenc@redhat.com Subject: Re: [ovs-dev] [PATCH] ipv6 tunneling: Fix for performance drop introduced by ipv6 tunnel support. 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: , Errors-To: dev-bounces@openvswitch.org Sender: "dev" On Tue, Jan 12, 2016 at 01:48:44PM +0000, Sugesh Chandran wrote: > Adding a new field called protocol in flow tunnel structure to verify the validity > of tunnel metadata. This field avoids the need of resetting and validating the > entire ipv4/ipv6 tunnel destination address which caused a serious performance > drop. > > Signed-off-by: Sugesh Chandran > --- > lib/flow.c | 8 +++---- > lib/match.c | 12 +++++------ > lib/meta-flow.c | 11 ++++++++-- > lib/netdev-vport.c | 5 ++--- > lib/odp-util.c | 10 ++++----- > lib/packets.c | 8 ++++++- > lib/packets.h | 50 ++++++++++++++++++++++++++++++++++++++------ > ofproto/ofproto-dpif-ipfix.c | 3 ++- > ofproto/ofproto-dpif-rid.c | 3 +-- > ofproto/ofproto-dpif-sflow.c | 6 +++--- > ofproto/tunnel.c | 14 ++++++++----- > 11 files changed, 92 insertions(+), 38 deletions(-) > Hi, Sugesh. This doesn't build with clang for me. Here is a quick fix. More comments below. > diff --git a/lib/flow.c b/lib/flow.c > index 5668d0c..34cee55 100644 > --- a/lib/flow.c > +++ b/lib/flow.c > @@ -818,15 +818,15 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata) > if (flow->tunnel.ip_src) { > match_set_tun_src(flow_metadata, flow->tunnel.ip_src); > } > - if (flow->tunnel.ip_dst) { > + if (flow->tunnel.protocol == FLOW_TUNNEL_IPV4) { > match_set_tun_dst(flow_metadata, flow->tunnel.ip_dst); > } > + else if (flow->tunnel.protocol == FLOW_TUNNEL_IPV6) { > + match_set_tun_ipv6_dst(flow_metadata, &flow->tunnel.ipv6_dst); > + } You need to follow coding style here. In this case, the else comes after the closing brace at the same line. > if (ipv6_addr_is_set(&flow->tunnel.ipv6_src)) { > match_set_tun_ipv6_src(flow_metadata, &flow->tunnel.ipv6_src); > } > - if (ipv6_addr_is_set(&flow->tunnel.ipv6_dst)) { > - match_set_tun_ipv6_dst(flow_metadata, &flow->tunnel.ipv6_dst); > - } > if (flow->tunnel.gbp_id != htons(0)) { > match_set_tun_gbp_id(flow_metadata, flow->tunnel.gbp_id); > } > diff --git a/lib/match.c b/lib/match.c > index 95d34bc..97a623e 100644 > --- a/lib/match.c > +++ b/lib/match.c > @@ -186,8 +186,8 @@ match_set_tun_dst(struct match *match, ovs_be32 dst) > void > match_set_tun_dst_masked(struct match *match, ovs_be32 dst, ovs_be32 mask) > { > - match->wc.masks.tunnel.ip_dst = mask; > - match->flow.tunnel.ip_dst = dst & mask; > + set_ipv4_dst_tnl(&match->wc.masks.tunnel, mask); > + set_ipv4_dst_tnl(&match->flow.tunnel, dst & mask); > } > > void > @@ -208,16 +208,16 @@ match_set_tun_ipv6_src_masked(struct match *match, const struct in6_addr *src, > void > match_set_tun_ipv6_dst(struct match *match, const struct in6_addr *dst) > { > - match->flow.tunnel.ipv6_dst = *dst; > - match->wc.masks.tunnel.ipv6_dst = in6addr_exact; > + set_ipv6_dst_tnl(&match->flow.tunnel, *dst); > + set_ipv6_dst_tnl(&match->wc.masks.tunnel, in6addr_exact); > } > > void > match_set_tun_ipv6_dst_masked(struct match *match, const struct in6_addr *dst, > const struct in6_addr *mask) > { > - match->flow.tunnel.ipv6_dst = ipv6_addr_bitand(dst, mask); > - match->wc.masks.tunnel.ipv6_dst = *mask; > + set_ipv6_dst_tnl(&match->flow.tunnel, ipv6_addr_bitand(dst, mask)); > + set_ipv6_dst_tnl(&match->wc.masks.tunnel, *mask); > } > > void > diff --git a/lib/meta-flow.c b/lib/meta-flow.c > index 6bd0b99..0826d1d 100644 > --- a/lib/meta-flow.c > +++ b/lib/meta-flow.c > @@ -1180,13 +1180,13 @@ mf_set_flow_value(const struct mf_field *mf, > flow->tunnel.ip_src = value->be32; > break; > case MFF_TUN_DST: > - flow->tunnel.ip_dst = value->be32; > + set_ipv4_dst_tnl(&flow->tunnel, value->be32); > break; > case MFF_TUN_IPV6_SRC: > flow->tunnel.ipv6_src = value->ipv6; > break; > case MFF_TUN_IPV6_DST: > - flow->tunnel.ipv6_dst = value->ipv6; > + set_ipv6_dst_tnl(&flow->tunnel, value->ipv6); > break; > case MFF_TUN_FLAGS: > flow->tunnel.flags = (flow->tunnel.flags & ~FLOW_TNL_PUB_F_MASK) | > @@ -1503,6 +1503,13 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str) > sizeof match->wc.masks.tunnel.ipv6_dst); > memset(&match->flow.tunnel.ipv6_dst, 0, > sizeof match->flow.tunnel.ipv6_dst); > + /* What if flow have a valid ipv4 tunnel address?? > + * Reset the flag only if thats not the case. > + */ > + match->wc.masks.tunnel.protocol = (match->wc.masks.tunnel.protocol == > + FLOW_TUNNEL_IPV4)? > + match->wc.masks.tunnel.protocol: > + FLOW_TUNNEL_UNSPEC; > break; > case MFF_TUN_FLAGS: > match_set_tun_flags_masked(match, 0, 0); > diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c > index 88f5022..d3477c3 100644 > --- a/lib/netdev-vport.c > +++ b/lib/netdev-vport.c > @@ -919,19 +919,18 @@ ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl, > ip_dst = get_16aligned_be32(&ip->ip_dst); > > tnl->ip_src = ip_src; > - tnl->ip_dst = ip_dst; > tnl->ip_tos = ip->ip_tos; > tnl->ip_ttl = ip->ip_ttl; > + set_ipv4_dst_tnl(tnl, ip_dst); > > *hlen += IP_HEADER_LEN; > > } else if (IP_VER(ip->ip_ihl_ver) == 6) { > > memcpy(tnl->ipv6_src.s6_addr, ip6->ip6_src.be16, sizeof ip6->ip6_src); > - memcpy(tnl->ipv6_dst.s6_addr, ip6->ip6_dst.be16, sizeof ip6->ip6_dst); > tnl->ip_tos = 0; > tnl->ip_ttl = ip6->ip6_hlim; > - > + set_ipv6_dst_tnl(tnl, *(struct in6_addr *)&ip6->ip6_dst); > *hlen += IPV6_HEADER_LEN; > > } else { > diff --git a/lib/odp-util.c b/lib/odp-util.c > index f16e113..26c3727 100644 > --- a/lib/odp-util.c > +++ b/lib/odp-util.c > @@ -510,7 +510,7 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data) > gnh->oam ? "oam," : "", > gnh->critical ? "crit," : "", > ntohl(get_16aligned_be32(&gnh->vni)) >> 8); > - > + > if (gnh->opt_len) { > ds_put_cstr(ds, ",options("); > format_geneve_opts(gnh->options, NULL, gnh->opt_len * 4, > @@ -1864,13 +1864,13 @@ odp_tun_key_from_attr__(const struct nlattr *attr, > tun->ip_src = nl_attr_get_be32(a); > break; > case OVS_TUNNEL_KEY_ATTR_IPV4_DST: > - tun->ip_dst = nl_attr_get_be32(a); > + set_ipv4_dst_tnl(tun, nl_attr_get_be32(a)); > break; > case OVS_TUNNEL_KEY_ATTR_IPV6_SRC: > tun->ipv6_src = nl_attr_get_in6_addr(a); > break; > case OVS_TUNNEL_KEY_ATTR_IPV6_DST: > - tun->ipv6_dst = nl_attr_get_in6_addr(a); > + set_ipv6_dst_tnl(tun, nl_attr_get_in6_addr(a)); > break; > case OVS_TUNNEL_KEY_ATTR_TOS: > tun->ip_tos = nl_attr_get_u8(a); > @@ -1961,13 +1961,13 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key, > if (tun_key->ip_src) { > nl_msg_put_be32(a, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, tun_key->ip_src); > } > - if (tun_key->ip_dst) { > + if (tun_key->protocol == FLOW_TUNNEL_IPV4) { > nl_msg_put_be32(a, OVS_TUNNEL_KEY_ATTR_IPV4_DST, tun_key->ip_dst); > } > if (ipv6_addr_is_set(&tun_key->ipv6_src)) { > nl_msg_put_in6_addr(a, OVS_TUNNEL_KEY_ATTR_IPV6_SRC, &tun_key->ipv6_src); > } > - if (ipv6_addr_is_set(&tun_key->ipv6_dst)) { > + if (tun_key->protocol == FLOW_TUNNEL_IPV6) { > nl_msg_put_in6_addr(a, OVS_TUNNEL_KEY_ATTR_IPV6_DST, &tun_key->ipv6_dst); > } > if (tun_key->ip_tos) { > diff --git a/lib/packets.c b/lib/packets.c > index d82341d..ed6c5ad 100644 > --- a/lib/packets.c > +++ b/lib/packets.c > @@ -39,7 +39,13 @@ const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT; > struct in6_addr > flow_tnl_dst(const struct flow_tnl *tnl) > { > - return tnl->ip_dst ? in6_addr_mapped_ipv4(tnl->ip_dst) : tnl->ipv6_dst; > + if(tnl->protocol == FLOW_TUNNEL_IPV4) { > + return in6_addr_mapped_ipv4(tnl->ip_dst); > + } > + else if(tnl->protocol == FLOW_TUNNEL_IPV6) { > + return tnl->ipv6_dst; > + } > + return in6addr_any; > } > > struct in6_addr > diff --git a/lib/packets.h b/lib/packets.h > index 834e8a4..53a6ec0 100644 > --- a/lib/packets.h > +++ b/lib/packets.h > @@ -35,8 +35,21 @@ > struct dp_packet; > struct ds; > > +/* Each type tunnel uses one bitfield. all bits are unset for unconfigured > + * tunnel address.*/ > +enum flow_tnl_proto_type { > + FLOW_TUNNEL_UNSPEC = 0, > + FLOW_TUNNEL_IPV4 = 1, //1st bit for ipv4 tunnel > + FLOW_TUNNEL_IPV6 = 2 //2nd bit for ipv6 tunnel > +}; > + You introduced an enum. My suggestion was that you don't do that and use 0, ETH_TYPE_IP and ETH_TYPE_IPV6 instead. Or AF_UNSPEC, AF_INET, AF_INET6. > /* Tunnel information used in flow key and metadata. */ > struct flow_tnl { > + /* The tunnel destination ip/ipv6 address are not initializing anywhere due to > + * the performance constrains. the enum 'flow_tnl_proto_type' is used to > + * validate the destination addresses. > + */ > + enum flow_tnl_proto_type protocol; > ovs_be32 ip_dst; > struct in6_addr ipv6_dst; > ovs_be32 ip_src; > @@ -49,7 +62,7 @@ struct flow_tnl { > ovs_be16 tp_dst; > ovs_be16 gbp_id; > uint8_t gbp_flags; > - uint8_t pad1[5]; /* Pad to 64 bits. */ > + uint8_t pad1[1]; /* Pad to 64 bits. */ > struct tun_metadata metadata; > }; > > @@ -76,10 +89,36 @@ struct flow_tnl { > > static inline bool ipv6_addr_is_set(const struct in6_addr *addr); > > +static inline void > +set_ipv4_dst_tnl(struct flow_tnl *tnl, ovs_be32 ip_dst) { > + if(tnl) { > + tnl->ip_dst = ip_dst; > + if(tnl->ip_dst) { > + tnl->protocol = FLOW_TUNNEL_IPV4; > + } > + else { > + tnl->protocol = FLOW_TUNNEL_UNSPEC; > + } > + } > +} > + > +static inline void > +set_ipv6_dst_tnl(struct flow_tnl *tnl, struct in6_addr ipv6_dst) { > + if(tnl) { > + tnl->ipv6_dst = ipv6_dst; > + if(ipv6_addr_is_set(&tnl->ipv6_dst)) { > + tnl->protocol = FLOW_TUNNEL_IPV6; > + } > + else { > + tnl->protocol = FLOW_TUNNEL_UNSPEC; > + } > + } > +} > + > static inline bool > flow_tnl_dst_is_set(const struct flow_tnl *tnl) > { > - return tnl->ip_dst || ipv6_addr_is_set(&tnl->ipv6_dst); > + return (tnl->protocol != FLOW_TUNNEL_UNSPEC); > } > > struct in6_addr flow_tnl_dst(const struct flow_tnl *tnl); > @@ -90,8 +129,8 @@ static inline size_t > flow_tnl_size(const struct flow_tnl *src) > { > if (!flow_tnl_dst_is_set(src)) { > - /* Covers ip_dst and ipv6_dst only. */ > - return offsetof(struct flow_tnl, ip_src); > + /* Covers protocol flag only. */ > + return offsetof(struct flow_tnl, ip_dst); > } > if (src->flags & FLOW_TNL_F_UDPIF) { > /* Datapath format, cover all options we have. */ > @@ -157,8 +196,7 @@ pkt_metadata_init(struct pkt_metadata *md, odp_port_t port) > * we can just zero out ip_dst and the rest of the data will never be > * looked at. */ > memset(md, 0, offsetof(struct pkt_metadata, in_port)); > - md->tunnel.ip_dst = 0; > - md->tunnel.ipv6_dst = in6addr_any; > + md->tunnel.protocol = FLOW_TUNNEL_UNSPEC; > > md->in_port.odp_port = port; > } > diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c > index a610c53..e00dac7 100644 > --- a/ofproto/ofproto-dpif-ipfix.c > +++ b/ofproto/ofproto-dpif-ipfix.c > @@ -1721,7 +1721,8 @@ dpif_ipfix_bridge_sample(struct dpif_ipfix *di, const struct dp_packet *packet, > * of matched packets. */ > packet_delta_count = UINT32_MAX / di->bridge_exporter.probability; > if (di->bridge_exporter.options->enable_tunnel_sampling) { > - if (output_odp_port == ODPP_NONE && flow->tunnel.ip_dst) { > + if (output_odp_port == ODPP_NONE && > + flow->tunnel.protocol == FLOW_TUNNEL_IPV4) { > /* Input tunnel. */ > tunnel_key = &flow->tunnel; > tunnel_port = dpif_ipfix_find_port(di, input_odp_port); > diff --git a/ofproto/ofproto-dpif-rid.c b/ofproto/ofproto-dpif-rid.c > index d142933..396489c 100644 > --- a/ofproto/ofproto-dpif-rid.c > +++ b/ofproto/ofproto-dpif-rid.c > @@ -297,8 +297,7 @@ uint32_t > recirc_alloc_id(struct ofproto_dpif *ofproto) > { > struct flow_tnl tunnel; > - tunnel.ip_dst = htonl(0); > - tunnel.ipv6_dst = in6addr_any; > + tunnel.protocol = FLOW_TUNNEL_UNSPEC; > struct recirc_state state = { > .table_id = TBL_INTERNAL, > .ofproto = ofproto, > diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c > index f11699c..66686de 100644 > --- a/ofproto/ofproto-dpif-sflow.c > +++ b/ofproto/ofproto-dpif-sflow.c > @@ -899,7 +899,7 @@ sflow_read_tnl_push_action(const struct nlattr *attr, > /* IPv4 */ > /* Cannot assume alignment so just use memcpy. */ > sflow_actions->tunnel.ip_src = get_16aligned_be32(&ip->ip_src); > - sflow_actions->tunnel.ip_dst = get_16aligned_be32(&ip->ip_dst); > + set_ipv4_dst_tnl(&sflow_actions->tunnel, get_16aligned_be32(&ip->ip_dst)); > sflow_actions->tunnel.ip_tos = ip->ip_tos; > sflow_actions->tunnel.ip_ttl = ip->ip_ttl; > /* The tnl_push action can supply the ip_protocol too. */ > @@ -991,7 +991,7 @@ sflow_read_set_action(const struct nlattr *attr, > sflow_actions->tunnel.ip_src = key->ipv4_src; > } > if (key->ipv4_dst) { > - sflow_actions->tunnel.ip_dst = key->ipv4_dst; > + set_ipv4_dst_tnl(&sflow_actions->tunnel, key->ipv4_dst); > } > if (key->ipv4_proto) { > sflow_actions->tunnel_ipproto = key->ipv4_proto; > @@ -1287,7 +1287,7 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct dp_packet *packet, > fs.output = cookie->sflow.output; > > /* Input tunnel. */ > - if (flow->tunnel.ip_dst) { > + if (flow->tunnel.protocol == FLOW_TUNNEL_IPV4) { > memset(&tnlInElem, 0, sizeof(tnlInElem)); > tnlInElem.tag = SFLFLOW_EX_IPV4_TUNNEL_INGRESS; > tnlInProto = dpif_sflow_tunnel_proto(in_dsp->tunnel_type); > diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c > index 5cf6c75..95f6df3 100644 > --- a/ofproto/tunnel.c > +++ b/ofproto/tunnel.c > @@ -362,12 +362,13 @@ tnl_wc_init(struct flow *flow, struct flow_wildcards *wc) > { > if (tnl_port_should_receive(flow)) { > wc->masks.tunnel.tun_id = OVS_BE64_MAX; > - if (flow->tunnel.ip_dst) { > + if (flow->tunnel.protocol == FLOW_TUNNEL_IPV4) { > wc->masks.tunnel.ip_src = OVS_BE32_MAX; > - wc->masks.tunnel.ip_dst = OVS_BE32_MAX; > - } else { > + set_ipv4_dst_tnl(&wc->masks.tunnel, OVS_BE32_MAX); > + } > + else if(flow->tunnel.protocol == FLOW_TUNNEL_IPV6) { > wc->masks.tunnel.ipv6_src = in6addr_exact; > - wc->masks.tunnel.ipv6_dst = in6addr_exact; > + set_ipv6_dst_tnl(&wc->masks.tunnel, in6addr_exact); > } > wc->masks.tunnel.flags = (FLOW_TNL_F_DONT_FRAGMENT | > FLOW_TNL_F_CSUM | > @@ -424,7 +425,10 @@ tnl_port_send(const struct ofport_dpif *ofport, struct flow *flow, > if (!cfg->ip_dst_flow) { > flow->tunnel.ip_dst = in6_addr_get_mapped_ipv4(&tnl_port->match.ipv6_dst); > if (!flow->tunnel.ip_dst) { > - flow->tunnel.ipv6_dst = tnl_port->match.ipv6_dst; > + set_ipv6_dst_tnl(&flow->tunnel, tnl_port->match.ipv6_dst); > + } > + else { > + set_ipv4_dst_tnl(&flow->tunnel, flow->tunnel.ip_dst); > } > } > flow->pkt_mark = tnl_port->match.pkt_mark; > -- > 1.9.1 > Regards. Cascardo. diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index d3477c3..f2b25d5 100644 --- a/lib/netdev-vport.c +++ b/lib/netdev-vport.c @@ -877,7 +877,7 @@ ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl, { void *nh; struct ip_header *ip; - struct ovs_16aligned_ip6_hdr *ip6; + struct ip6_hdr *ip6; void *l4; int l3_size; @@ -927,10 +927,10 @@ ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl, } else if (IP_VER(ip->ip_ihl_ver) == 6) { - memcpy(tnl->ipv6_src.s6_addr, ip6->ip6_src.be16, sizeof ip6->ip6_src); + memcpy(tnl->ipv6_src.s6_addr, &ip6->ip6_src, sizeof ip6->ip6_src); tnl->ip_tos = 0; tnl->ip_ttl = ip6->ip6_hlim; - set_ipv6_dst_tnl(tnl, *(struct in6_addr *)&ip6->ip6_dst); + set_ipv6_dst_tnl(tnl, ip6->ip6_dst); *hlen += IPV6_HEADER_LEN; } else {