diff options
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 75 |
1 files changed, 59 insertions, 16 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 6369a5734d4c..ba363cedef80 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -1158,7 +1158,6 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, | |||
1158 | struct pcpu_sw_netstats *stats; | 1158 | struct pcpu_sw_netstats *stats; |
1159 | union vxlan_addr saddr; | 1159 | union vxlan_addr saddr; |
1160 | int err = 0; | 1160 | int err = 0; |
1161 | union vxlan_addr *remote_ip; | ||
1162 | 1161 | ||
1163 | /* For flow based devices, map all packets to VNI 0 */ | 1162 | /* For flow based devices, map all packets to VNI 0 */ |
1164 | if (vs->flags & VXLAN_F_COLLECT_METADATA) | 1163 | if (vs->flags & VXLAN_F_COLLECT_METADATA) |
@@ -1169,7 +1168,6 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, | |||
1169 | if (!vxlan) | 1168 | if (!vxlan) |
1170 | goto drop; | 1169 | goto drop; |
1171 | 1170 | ||
1172 | remote_ip = &vxlan->default_dst.remote_ip; | ||
1173 | skb_reset_mac_header(skb); | 1171 | skb_reset_mac_header(skb); |
1174 | skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev))); | 1172 | skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev))); |
1175 | skb->protocol = eth_type_trans(skb, vxlan->dev); | 1173 | skb->protocol = eth_type_trans(skb, vxlan->dev); |
@@ -1179,8 +1177,8 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb, | |||
1179 | if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) | 1177 | if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) |
1180 | goto drop; | 1178 | goto drop; |
1181 | 1179 | ||
1182 | /* Re-examine inner Ethernet packet */ | 1180 | /* Get data from the outer IP header */ |
1183 | if (remote_ip->sa.sa_family == AF_INET) { | 1181 | if (vxlan_get_sk_family(vs) == AF_INET) { |
1184 | oip = ip_hdr(skb); | 1182 | oip = ip_hdr(skb); |
1185 | saddr.sin.sin_addr.s_addr = oip->saddr; | 1183 | saddr.sin.sin_addr.s_addr = oip->saddr; |
1186 | saddr.sa.sa_family = AF_INET; | 1184 | saddr.sa.sa_family = AF_INET; |
@@ -1848,6 +1846,34 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk | |||
1848 | !(vxflags & VXLAN_F_UDP_CSUM)); | 1846 | !(vxflags & VXLAN_F_UDP_CSUM)); |
1849 | } | 1847 | } |
1850 | 1848 | ||
1849 | #if IS_ENABLED(CONFIG_IPV6) | ||
1850 | static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan, | ||
1851 | struct sk_buff *skb, int oif, | ||
1852 | const struct in6_addr *daddr, | ||
1853 | struct in6_addr *saddr) | ||
1854 | { | ||
1855 | struct dst_entry *ndst; | ||
1856 | struct flowi6 fl6; | ||
1857 | int err; | ||
1858 | |||
1859 | memset(&fl6, 0, sizeof(fl6)); | ||
1860 | fl6.flowi6_oif = oif; | ||
1861 | fl6.daddr = *daddr; | ||
1862 | fl6.saddr = vxlan->cfg.saddr.sin6.sin6_addr; | ||
1863 | fl6.flowi6_mark = skb->mark; | ||
1864 | fl6.flowi6_proto = IPPROTO_UDP; | ||
1865 | |||
1866 | err = ipv6_stub->ipv6_dst_lookup(vxlan->net, | ||
1867 | vxlan->vn6_sock->sock->sk, | ||
1868 | &ndst, &fl6); | ||
1869 | if (err < 0) | ||
1870 | return ERR_PTR(err); | ||
1871 | |||
1872 | *saddr = fl6.saddr; | ||
1873 | return ndst; | ||
1874 | } | ||
1875 | #endif | ||
1876 | |||
1851 | /* Bypass encapsulation if the destination is local */ | 1877 | /* Bypass encapsulation if the destination is local */ |
1852 | static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, | 1878 | static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, |
1853 | struct vxlan_dev *dst_vxlan) | 1879 | struct vxlan_dev *dst_vxlan) |
@@ -2035,21 +2061,17 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, | |||
2035 | #if IS_ENABLED(CONFIG_IPV6) | 2061 | #if IS_ENABLED(CONFIG_IPV6) |
2036 | } else { | 2062 | } else { |
2037 | struct dst_entry *ndst; | 2063 | struct dst_entry *ndst; |
2038 | struct flowi6 fl6; | 2064 | struct in6_addr saddr; |
2039 | u32 rt6i_flags; | 2065 | u32 rt6i_flags; |
2040 | 2066 | ||
2041 | if (!vxlan->vn6_sock) | 2067 | if (!vxlan->vn6_sock) |
2042 | goto drop; | 2068 | goto drop; |
2043 | sk = vxlan->vn6_sock->sock->sk; | 2069 | sk = vxlan->vn6_sock->sock->sk; |
2044 | 2070 | ||
2045 | memset(&fl6, 0, sizeof(fl6)); | 2071 | ndst = vxlan6_get_route(vxlan, skb, |
2046 | fl6.flowi6_oif = rdst ? rdst->remote_ifindex : 0; | 2072 | rdst ? rdst->remote_ifindex : 0, |
2047 | fl6.daddr = dst->sin6.sin6_addr; | 2073 | &dst->sin6.sin6_addr, &saddr); |
2048 | fl6.saddr = vxlan->cfg.saddr.sin6.sin6_addr; | 2074 | if (IS_ERR(ndst)) { |
2049 | fl6.flowi6_mark = skb->mark; | ||
2050 | fl6.flowi6_proto = IPPROTO_UDP; | ||
2051 | |||
2052 | if (ipv6_stub->ipv6_dst_lookup(vxlan->net, sk, &ndst, &fl6)) { | ||
2053 | netdev_dbg(dev, "no route to %pI6\n", | 2075 | netdev_dbg(dev, "no route to %pI6\n", |
2054 | &dst->sin6.sin6_addr); | 2076 | &dst->sin6.sin6_addr); |
2055 | dev->stats.tx_carrier_errors++; | 2077 | dev->stats.tx_carrier_errors++; |
@@ -2081,7 +2103,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, | |||
2081 | } | 2103 | } |
2082 | 2104 | ||
2083 | ttl = ttl ? : ip6_dst_hoplimit(ndst); | 2105 | ttl = ttl ? : ip6_dst_hoplimit(ndst); |
2084 | err = vxlan6_xmit_skb(ndst, sk, skb, dev, &fl6.saddr, &fl6.daddr, | 2106 | err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr, |
2085 | 0, ttl, src_port, dst_port, htonl(vni << 8), md, | 2107 | 0, ttl, src_port, dst_port, htonl(vni << 8), md, |
2086 | !net_eq(vxlan->net, dev_net(vxlan->dev)), | 2108 | !net_eq(vxlan->net, dev_net(vxlan->dev)), |
2087 | flags); | 2109 | flags); |
@@ -2395,9 +2417,30 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) | |||
2395 | vxlan->cfg.port_max, true); | 2417 | vxlan->cfg.port_max, true); |
2396 | dport = info->key.tp_dst ? : vxlan->cfg.dst_port; | 2418 | dport = info->key.tp_dst ? : vxlan->cfg.dst_port; |
2397 | 2419 | ||
2398 | if (ip_tunnel_info_af(info) == AF_INET) | 2420 | if (ip_tunnel_info_af(info) == AF_INET) { |
2421 | if (!vxlan->vn4_sock) | ||
2422 | return -EINVAL; | ||
2399 | return egress_ipv4_tun_info(dev, skb, info, sport, dport); | 2423 | return egress_ipv4_tun_info(dev, skb, info, sport, dport); |
2400 | return -EINVAL; | 2424 | } else { |
2425 | #if IS_ENABLED(CONFIG_IPV6) | ||
2426 | struct dst_entry *ndst; | ||
2427 | |||
2428 | if (!vxlan->vn6_sock) | ||
2429 | return -EINVAL; | ||
2430 | ndst = vxlan6_get_route(vxlan, skb, 0, | ||
2431 | &info->key.u.ipv6.dst, | ||
2432 | &info->key.u.ipv6.src); | ||
2433 | if (IS_ERR(ndst)) | ||
2434 | return PTR_ERR(ndst); | ||
2435 | dst_release(ndst); | ||
2436 | |||
2437 | info->key.tp_src = sport; | ||
2438 | info->key.tp_dst = dport; | ||
2439 | #else /* !CONFIG_IPV6 */ | ||
2440 | return -EPFNOSUPPORT; | ||
2441 | #endif | ||
2442 | } | ||
2443 | return 0; | ||
2401 | } | 2444 | } |
2402 | 2445 | ||
2403 | static const struct net_device_ops vxlan_netdev_ops = { | 2446 | static const struct net_device_ops vxlan_netdev_ops = { |