Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fee1fad7 authored by pravin shelar's avatar pravin shelar Committed by David S. Miller
Browse files

vxlan: simplify RTF_LOCAL handling.



Avoid code duplicate code for handling RTF_LOCAL routes.

Signed-off-by: default avatarPravin B Shelar <pshelar@ovn.org>
Acked-by: default avatarJiri Benc <jbenc@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 655c3de1
Loading
Loading
Loading
Loading
+51 −34
Original line number Diff line number Diff line
@@ -1940,6 +1940,40 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
	}
}

static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
				 struct vxlan_dev *vxlan, union vxlan_addr *daddr,
				 __be32 dst_port, __be32 vni, struct dst_entry *dst,
				 u32 rt_flags)
{
#if IS_ENABLED(CONFIG_IPV6)
	/* IPv6 rt-flags are checked against RTF_LOCAL, but the value of
	 * RTF_LOCAL is equal to RTCF_LOCAL. So to keep code simple
	 * we can use RTCF_LOCAL which works for ipv4 and ipv6 route entry.
	 */
	BUILD_BUG_ON(RTCF_LOCAL != RTF_LOCAL);
#endif
	/* Bypass encapsulation if the destination is local */
	if (rt_flags & RTCF_LOCAL &&
	    !(rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
		struct vxlan_dev *dst_vxlan;

		dst_release(dst);
		dst_vxlan = vxlan_find_vni(vxlan->net, vni,
					   daddr->sa.sa_family, dst_port,
					   vxlan->flags);
		if (!dst_vxlan) {
			dev->stats.tx_errors++;
			kfree_skb(skb);

			return -ENOENT;
		}
		vxlan_encap_bypass(skb, vxlan, dst_vxlan);
		return 1;
	}

	return 0;
}

static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
			   struct vxlan_rdst *rdst, bool did_rsc)
{
@@ -2038,27 +2072,19 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
				     dst_cache, info);
		if (IS_ERR(rt))
			goto tx_error;
		sk = sock4->sock->sk;

		sk = sock4->sock->sk;
		/* Bypass encapsulation if the destination is local */
		if (!info && rt->rt_flags & RTCF_LOCAL &&
		    !(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
			struct vxlan_dev *dst_vxlan;

			ip_rt_put(rt);
			dst_vxlan = vxlan_find_vni(vxlan->net, vni,
						   dst->sa.sa_family, dst_port,
						   vxlan->flags);
			if (!dst_vxlan)
				goto tx_error;
			vxlan_encap_bypass(skb, vxlan, dst_vxlan);
		if (!info) {
			err = encap_bypass_if_local(skb, dev, vxlan, dst,
						    dst_port, vni, &rt->dst,
						    rt->rt_flags);
			if (err)
				return;
		}

		if (!info)
			udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX);
		else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT)
		} else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) {
			df = htons(IP_DF);
		}

		ndst = &rt->dst;
		tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
@@ -2074,7 +2100,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
#if IS_ENABLED(CONFIG_IPV6)
	} else {
		struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
		u32 rt6i_flags;

		ndst = vxlan6_get_route(vxlan, dev, sock6, skb,
					rdst ? rdst->remote_ifindex : 0, tos,
@@ -2087,24 +2112,16 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
		}
		sk = sock6->sock->sk;

		/* Bypass encapsulation if the destination is local */
		rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags;
		if (!info && rt6i_flags & RTF_LOCAL &&
		    !(rt6i_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) {
			struct vxlan_dev *dst_vxlan;
		if (!info) {
			u32 rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags;

			dst_vxlan = vxlan_find_vni(vxlan->net, vni,
						   dst->sa.sa_family, dst_port,
						   vxlan->flags);
			if (!dst_vxlan)
				goto tx_error;
			dst_release(ndst);
			vxlan_encap_bypass(skb, vxlan, dst_vxlan);
			err = encap_bypass_if_local(skb, dev, vxlan, dst,
						    dst_port, vni, ndst,
						    rt6i_flags);
			if (err)
				return;
		}

		if (!info)
			udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
		}

		tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
		ttl = ttl ? : ip6_dst_hoplimit(ndst);