|
@@ -1980,8 +1980,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
struct dst_cache *dst_cache;
|
|
struct dst_cache *dst_cache;
|
|
struct ip_tunnel_info *info;
|
|
struct ip_tunnel_info *info;
|
|
struct vxlan_dev *vxlan = netdev_priv(dev);
|
|
struct vxlan_dev *vxlan = netdev_priv(dev);
|
|
- struct sock *sk;
|
|
|
|
- const struct iphdr *old_iph;
|
|
|
|
|
|
+ const struct iphdr *old_iph = ip_hdr(skb);
|
|
union vxlan_addr *dst;
|
|
union vxlan_addr *dst;
|
|
union vxlan_addr remote_ip, local_ip;
|
|
union vxlan_addr remote_ip, local_ip;
|
|
union vxlan_addr *src;
|
|
union vxlan_addr *src;
|
|
@@ -1990,7 +1989,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
__be16 src_port = 0, dst_port;
|
|
__be16 src_port = 0, dst_port;
|
|
struct dst_entry *ndst = NULL;
|
|
struct dst_entry *ndst = NULL;
|
|
__be32 vni, label;
|
|
__be32 vni, label;
|
|
- __be16 df = 0;
|
|
|
|
__u8 tos, ttl;
|
|
__u8 tos, ttl;
|
|
int err;
|
|
int err;
|
|
u32 flags = vxlan->flags;
|
|
u32 flags = vxlan->flags;
|
|
@@ -2000,19 +1998,40 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
info = skb_tunnel_info(skb);
|
|
info = skb_tunnel_info(skb);
|
|
|
|
|
|
if (rdst) {
|
|
if (rdst) {
|
|
|
|
+ dst = &rdst->remote_ip;
|
|
|
|
+ if (vxlan_addr_any(dst)) {
|
|
|
|
+ if (did_rsc) {
|
|
|
|
+ /* short-circuited back to local bridge */
|
|
|
|
+ vxlan_encap_bypass(skb, vxlan, vxlan);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ goto drop;
|
|
|
|
+ }
|
|
|
|
+
|
|
dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
|
|
dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
|
|
vni = rdst->remote_vni;
|
|
vni = rdst->remote_vni;
|
|
- dst = &rdst->remote_ip;
|
|
|
|
src = &vxlan->cfg.saddr;
|
|
src = &vxlan->cfg.saddr;
|
|
dst_cache = &rdst->dst_cache;
|
|
dst_cache = &rdst->dst_cache;
|
|
|
|
+ md->gbp = skb->mark;
|
|
|
|
+ ttl = vxlan->cfg.ttl;
|
|
|
|
+ if (!ttl && vxlan_addr_multicast(dst))
|
|
|
|
+ ttl = 1;
|
|
|
|
+
|
|
|
|
+ tos = vxlan->cfg.tos;
|
|
|
|
+ if (tos == 1)
|
|
|
|
+ tos = ip_tunnel_get_dsfield(old_iph, skb);
|
|
|
|
+
|
|
|
|
+ if (dst->sa.sa_family == AF_INET)
|
|
|
|
+ udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX);
|
|
|
|
+ else
|
|
|
|
+ udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
|
|
|
|
+ label = vxlan->cfg.label;
|
|
} else {
|
|
} else {
|
|
if (!info) {
|
|
if (!info) {
|
|
WARN_ONCE(1, "%s: Missing encapsulation instructions\n",
|
|
WARN_ONCE(1, "%s: Missing encapsulation instructions\n",
|
|
dev->name);
|
|
dev->name);
|
|
goto drop;
|
|
goto drop;
|
|
}
|
|
}
|
|
- dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
|
|
|
|
- vni = tunnel_id_to_key32(info->key.tun_id);
|
|
|
|
remote_ip.sa.sa_family = ip_tunnel_info_af(info);
|
|
remote_ip.sa.sa_family = ip_tunnel_info_af(info);
|
|
if (remote_ip.sa.sa_family == AF_INET) {
|
|
if (remote_ip.sa.sa_family == AF_INET) {
|
|
remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst;
|
|
remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst;
|
|
@@ -2022,48 +2041,24 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
local_ip.sin6.sin6_addr = info->key.u.ipv6.src;
|
|
local_ip.sin6.sin6_addr = info->key.u.ipv6.src;
|
|
}
|
|
}
|
|
dst = &remote_ip;
|
|
dst = &remote_ip;
|
|
|
|
+ dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
|
|
|
|
+ vni = tunnel_id_to_key32(info->key.tun_id);
|
|
src = &local_ip;
|
|
src = &local_ip;
|
|
dst_cache = &info->dst_cache;
|
|
dst_cache = &info->dst_cache;
|
|
- }
|
|
|
|
-
|
|
|
|
- if (vxlan_addr_any(dst)) {
|
|
|
|
- if (did_rsc) {
|
|
|
|
- /* short-circuited back to local bridge */
|
|
|
|
- vxlan_encap_bypass(skb, vxlan, vxlan);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- goto drop;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- old_iph = ip_hdr(skb);
|
|
|
|
-
|
|
|
|
- ttl = vxlan->cfg.ttl;
|
|
|
|
- if (!ttl && vxlan_addr_multicast(dst))
|
|
|
|
- ttl = 1;
|
|
|
|
-
|
|
|
|
- tos = vxlan->cfg.tos;
|
|
|
|
- if (tos == 1)
|
|
|
|
- tos = ip_tunnel_get_dsfield(old_iph, skb);
|
|
|
|
-
|
|
|
|
- label = vxlan->cfg.label;
|
|
|
|
- src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
|
|
|
|
- vxlan->cfg.port_max, true);
|
|
|
|
-
|
|
|
|
- if (info) {
|
|
|
|
|
|
+ if (info->options_len)
|
|
|
|
+ md = ip_tunnel_info_opts(info);
|
|
ttl = info->key.ttl;
|
|
ttl = info->key.ttl;
|
|
tos = info->key.tos;
|
|
tos = info->key.tos;
|
|
label = info->key.label;
|
|
label = info->key.label;
|
|
udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
|
|
udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM);
|
|
-
|
|
|
|
- if (info->options_len)
|
|
|
|
- md = ip_tunnel_info_opts(info);
|
|
|
|
- } else {
|
|
|
|
- md->gbp = skb->mark;
|
|
|
|
}
|
|
}
|
|
|
|
+ src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
|
|
|
|
+ vxlan->cfg.port_max, true);
|
|
|
|
|
|
if (dst->sa.sa_family == AF_INET) {
|
|
if (dst->sa.sa_family == AF_INET) {
|
|
struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock);
|
|
struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock);
|
|
struct rtable *rt;
|
|
struct rtable *rt;
|
|
|
|
+ __be16 df = 0;
|
|
|
|
|
|
rt = vxlan_get_route(vxlan, dev, sock4, skb,
|
|
rt = vxlan_get_route(vxlan, dev, sock4, skb,
|
|
rdst ? rdst->remote_ifindex : 0, tos,
|
|
rdst ? rdst->remote_ifindex : 0, tos,
|
|
@@ -2073,7 +2068,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
if (IS_ERR(rt))
|
|
if (IS_ERR(rt))
|
|
goto tx_error;
|
|
goto tx_error;
|
|
|
|
|
|
- sk = sock4->sock->sk;
|
|
|
|
/* Bypass encapsulation if the destination is local */
|
|
/* Bypass encapsulation if the destination is local */
|
|
if (!info) {
|
|
if (!info) {
|
|
err = encap_bypass_if_local(skb, dev, vxlan, dst,
|
|
err = encap_bypass_if_local(skb, dev, vxlan, dst,
|
|
@@ -2081,7 +2075,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
rt->rt_flags);
|
|
rt->rt_flags);
|
|
if (err)
|
|
if (err)
|
|
return;
|
|
return;
|
|
- 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);
|
|
}
|
|
}
|
|
@@ -2094,7 +2087,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto tx_error;
|
|
goto tx_error;
|
|
|
|
|
|
- udp_tunnel_xmit_skb(rt, sk, skb, src->sin.sin_addr.s_addr,
|
|
|
|
|
|
+ udp_tunnel_xmit_skb(rt, sock4->sock->sk, skb, src->sin.sin_addr.s_addr,
|
|
dst->sin.sin_addr.s_addr, tos, ttl, df,
|
|
dst->sin.sin_addr.s_addr, tos, ttl, df,
|
|
src_port, dst_port, xnet, !udp_sum);
|
|
src_port, dst_port, xnet, !udp_sum);
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
#if IS_ENABLED(CONFIG_IPV6)
|
|
@@ -2110,7 +2103,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
ndst = NULL;
|
|
ndst = NULL;
|
|
goto tx_error;
|
|
goto tx_error;
|
|
}
|
|
}
|
|
- sk = sock6->sock->sk;
|
|
|
|
|
|
|
|
if (!info) {
|
|
if (!info) {
|
|
u32 rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags;
|
|
u32 rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags;
|
|
@@ -2120,7 +2112,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
rt6i_flags);
|
|
rt6i_flags);
|
|
if (err)
|
|
if (err)
|
|
return;
|
|
return;
|
|
- 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);
|
|
@@ -2131,13 +2122,12 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto tx_error;
|
|
goto tx_error;
|
|
|
|
|
|
- udp_tunnel6_xmit_skb(ndst, sk, skb, dev,
|
|
|
|
|
|
+ udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev,
|
|
&src->sin6.sin6_addr,
|
|
&src->sin6.sin6_addr,
|
|
&dst->sin6.sin6_addr, tos, ttl,
|
|
&dst->sin6.sin6_addr, tos, ttl,
|
|
label, src_port, dst_port, !udp_sum);
|
|
label, src_port, dst_port, !udp_sum);
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
-
|
|
|
|
return;
|
|
return;
|
|
|
|
|
|
drop:
|
|
drop:
|