lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Tue, 02 Feb 2016 15:57:23 +0100
From:	Paolo Abeni <pabeni@...hat.com>
To:	Jiri Benc <jbenc@...hat.com>
Cc:	netdev@...r.kernel.org
Subject: Re: [PATCH net-next 5/5] vxlan: consolidate vxlan_xmit_skb and
 vxlan6_xmit_skb

On Tue, 2016-02-02 at 11:13 +0100, Jiri Benc wrote:
> There's a lot of code duplication. Factor out the duplicate code to a new
> function shared between IPv4 and IPv6 xmit path.
> 
> Signed-off-by: Jiri Benc <jbenc@...hat.com>
> ---
>  drivers/net/vxlan.c | 141 +++++++++++-----------------------------------------
>  1 file changed, 29 insertions(+), 112 deletions(-)
> 
> diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
> index d0f7723fd776..cf7de95eccfc 100644
> --- a/drivers/net/vxlan.c
> +++ b/drivers/net/vxlan.c
> @@ -1684,98 +1684,9 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags,
>  	gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK);
>  }
>  
> -#if IS_ENABLED(CONFIG_IPV6)
> -static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk,
> -			   struct sk_buff *skb,
> -			   struct net_device *dev, struct in6_addr *saddr,
> -			   struct in6_addr *daddr, __u8 prio, __u8 ttl,
> -			   __be16 src_port, __be16 dst_port, __be32 vni,
> -			   struct vxlan_metadata *md, bool xnet, u32 vxflags)
> -{
> -	struct vxlanhdr *vxh;
> -	int min_headroom;
> -	int err;
> -	bool udp_sum = !(vxflags & VXLAN_F_UDP_ZERO_CSUM6_TX);
> -	int type = udp_sum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
> -	u16 hdrlen = sizeof(struct vxlanhdr);
> -
> -	if ((vxflags & VXLAN_F_REMCSUM_TX) &&
> -	    skb->ip_summed == CHECKSUM_PARTIAL) {
> -		int csum_start = skb_checksum_start_offset(skb);
> -
> -		if (csum_start <= VXLAN_MAX_REMCSUM_START &&
> -		    !(csum_start & VXLAN_RCO_SHIFT_MASK) &&
> -		    (skb->csum_offset == offsetof(struct udphdr, check) ||
> -		     skb->csum_offset == offsetof(struct tcphdr, check))) {
> -			udp_sum = false;
> -			type |= SKB_GSO_TUNNEL_REMCSUM;
> -		}
> -	}
> -
> -	skb_scrub_packet(skb, xnet);
> -
> -	min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
> -			+ VXLAN_HLEN + sizeof(struct ipv6hdr)
> -			+ (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
> -
> -	/* Need space for new headers (invalidates iph ptr) */
> -	err = skb_cow_head(skb, min_headroom);
> -	if (unlikely(err)) {
> -		kfree_skb(skb);
> -		goto err;
> -	}
> -
> -	skb = vlan_hwaccel_push_inside(skb);
> -	if (WARN_ON(!skb)) {
> -		err = -ENOMEM;
> -		goto err;
> -	}
> -
> -	skb = iptunnel_handle_offloads(skb, udp_sum, type);
> -	if (IS_ERR(skb)) {
> -		err = -EINVAL;
> -		goto err;
> -	}
> -
> -	vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh));
> -	vxh->vx_flags = htonl(VXLAN_HF_VNI);
> -	vxh->vx_vni = vni;
> -
> -	if (type & SKB_GSO_TUNNEL_REMCSUM) {
> -		u32 data = (skb_checksum_start_offset(skb) - hdrlen) >>
> -			   VXLAN_RCO_SHIFT;
> -
> -		if (skb->csum_offset == offsetof(struct udphdr, check))
> -			data |= VXLAN_RCO_UDP;
> -
> -		vxh->vx_vni |= htonl(data);
> -		vxh->vx_flags |= htonl(VXLAN_HF_RCO);
> -
> -		if (!skb_is_gso(skb)) {
> -			skb->ip_summed = CHECKSUM_NONE;
> -			skb->encapsulation = 0;
> -		}
> -	}
> -
> -	if (vxflags & VXLAN_F_GBP)
> -		vxlan_build_gbp_hdr(vxh, vxflags, md);
> -
> -	skb_set_inner_protocol(skb, htons(ETH_P_TEB));
> -
> -	udp_tunnel6_xmit_skb(dst, sk, skb, dev, saddr, daddr, prio,
> -			     ttl, src_port, dst_port,
> -			     !!(vxflags & VXLAN_F_UDP_ZERO_CSUM6_TX));
> -	return 0;
> -err:
> -	dst_release(dst);
> -	return err;
> -}
> -#endif
> -
> -static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,
> -			  __be32 src, __be32 dst, __u8 tos, __u8 ttl, __be16 df,
> -			  __be16 src_port, __be16 dst_port, __be32 vni,
> -			  struct vxlan_metadata *md, bool xnet, u32 vxflags)
> +static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst,
> +			   int iphdr_len, __be32 vni,
> +			   struct vxlan_metadata *md, u32 vxflags)
>  {
>  	struct vxlanhdr *vxh;
>  	int min_headroom;
> @@ -1797,8 +1708,8 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk
>  		}
>  	}
>  
> -	min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
> -			+ VXLAN_HLEN + sizeof(struct iphdr)
> +	min_headroom = LL_RESERVED_SPACE(dst->dev) + dst->header_len
> +			+ VXLAN_HLEN + iphdr_len
>  			+ (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
>  
>  	/* Need space for new headers (invalidates iph ptr) */
> @@ -1840,10 +1751,6 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk
>  		vxlan_build_gbp_hdr(vxh, vxflags, md);
>  
>  	skb_set_inner_protocol(skb, htons(ETH_P_TEB));
> -
> -	udp_tunnel_xmit_skb(rt, sk, skb, src, dst, tos, ttl, df,
> -			    src_port, dst_port, xnet,
> -			    !(vxflags & VXLAN_F_UDP_CSUM));
>  	return 0;
>  }
>  
> @@ -1959,6 +1866,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
>  	__u8 tos, ttl;
>  	int err;
>  	u32 flags = vxlan->flags;
> +	bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev));
>  
>  	info = skb_tunnel_info(skb);
>  
> @@ -2065,16 +1973,15 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
>  
>  		tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
>  		ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
> -		err = vxlan_xmit_skb(rt, sk, skb, saddr,
> -				     dst->sin.sin_addr.s_addr, tos, ttl, df,
> -				     src_port, dst_port, htonl(vni << 8), md,
> -				     !net_eq(vxlan->net, dev_net(vxlan->dev)),
> -				     flags);
> -		if (err < 0) {
> -			/* skb is already freed. */
> -			skb = NULL;
> -			goto rt_tx_error;
> -		}
> +		err = vxlan_build_skb(skb, &rt->dst, sizeof(struct iphdr),
> +				      htonl(vni << 8), md, flags);
> +		if (err < 0)
> +			goto xmit_tx_error;
> +
> +		udp_tunnel_xmit_skb(rt, sk, skb, saddr,
> +				    dst->sin.sin_addr.s_addr, tos, ttl, df,
> +				    src_port, dst_port, xnet,
> +				    !(flags & VXLAN_F_UDP_CSUM));
>  #if IS_ENABLED(CONFIG_IPV6)
>  	} else {
>  		struct dst_entry *ndst;
> @@ -2127,10 +2034,17 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
>  		}
>  
>  		ttl = ttl ? : ip6_dst_hoplimit(ndst);
> -		err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr,
> -				      0, ttl, src_port, dst_port, htonl(vni << 8), md,
> -				      !net_eq(vxlan->net, dev_net(vxlan->dev)),
> -				      flags);
> +		skb_scrub_packet(skb, xnet);
> +		err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
> +				      htonl(vni << 8), md, flags);

I think there is an issue here: in vxlan_build_skb(), 'flags' will be
always tested against VXLAN_F_UDP_CSUM, but when tunneling over ipv6 we
should check VXLAN_F_UDP_ZERO_CSUM6_TX instead. 

Probably an explicit 'udp_sum' argument should be added to
vxlan_build_skb().

Paolo

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ