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

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
...@@ -1940,6 +1940,40 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, ...@@ -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, static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
struct vxlan_rdst *rdst, bool did_rsc) struct vxlan_rdst *rdst, bool did_rsc)
{ {
...@@ -2038,27 +2072,19 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -2038,27 +2072,19 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
dst_cache, info); dst_cache, info);
if (IS_ERR(rt)) if (IS_ERR(rt))
goto tx_error; goto tx_error;
sk = sock4->sock->sk;
sk = sock4->sock->sk;
/* Bypass encapsulation if the destination is local */ /* Bypass encapsulation if the destination is local */
if (!info && rt->rt_flags & RTCF_LOCAL && if (!info) {
!(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))) { err = encap_bypass_if_local(skb, dev, vxlan, dst,
struct vxlan_dev *dst_vxlan; dst_port, vni, &rt->dst,
rt->rt_flags);
ip_rt_put(rt); if (err)
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);
return; return;
}
if (!info)
udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX); 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); df = htons(IP_DF);
}
ndst = &rt->dst; ndst = &rt->dst;
tos = ip_tunnel_ecn_encap(tos, old_iph, skb); 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, ...@@ -2074,7 +2100,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
} else { } else {
struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock); struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
u32 rt6i_flags;
ndst = vxlan6_get_route(vxlan, dev, sock6, skb, ndst = vxlan6_get_route(vxlan, dev, sock6, skb,
rdst ? rdst->remote_ifindex : 0, tos, rdst ? rdst->remote_ifindex : 0, tos,
...@@ -2087,24 +2112,16 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -2087,24 +2112,16 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
} }
sk = sock6->sock->sk; sk = sock6->sock->sk;
/* Bypass encapsulation if the destination is local */ if (!info) {
rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags; u32 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;
dst_vxlan = vxlan_find_vni(vxlan->net, vni, err = encap_bypass_if_local(skb, dev, vxlan, dst,
dst->sa.sa_family, dst_port, dst_port, vni, ndst,
vxlan->flags); rt6i_flags);
if (!dst_vxlan) if (err)
goto tx_error;
dst_release(ndst);
vxlan_encap_bypass(skb, vxlan, dst_vxlan);
return; return;
}
if (!info)
udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
}
tos = ip_tunnel_ecn_encap(tos, old_iph, skb); tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
ttl = ttl ? : ip6_dst_hoplimit(ndst); ttl = ttl ? : ip6_dst_hoplimit(ndst);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment