Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'consolidate-udp-ipv6-route-lookups'

Beniamino Galvani says:

====================
net: consolidate IPv6 route lookup for UDP tunnels

At the moment different UDP tunnels rely on different functions for
IPv6 route lookup, and those functions all implement the same
logic.

Extend the generic lookup function so that it is suitable for all UDP
tunnel implementations, and then adapt bareudp, geneve and vxlan to
use it.

This is similar to what already done for IPv4.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+147 -250
+8 -5
drivers/net/bareudp.c
··· 371 371 if (!sock) 372 372 return -ESHUTDOWN; 373 373 374 - dst = ip6_dst_lookup_tunnel(skb, dev, bareudp->net, sock, &saddr, info, 375 - IPPROTO_UDP, use_cache); 374 + dst = udp_tunnel6_dst_lookup(skb, dev, bareudp->net, sock, 0, &saddr, 375 + key, 0, 0, key->tos, 376 + use_cache ? 377 + (struct dst_cache *) &info->dst_cache : NULL); 376 378 if (IS_ERR(dst)) 377 379 return PTR_ERR(dst); 378 380 ··· 500 498 struct in6_addr saddr; 501 499 struct socket *sock = rcu_dereference(bareudp->sock); 502 500 503 - dst = ip6_dst_lookup_tunnel(skb, dev, bareudp->net, sock, 504 - &saddr, info, IPPROTO_UDP, 505 - use_cache); 501 + dst = udp_tunnel6_dst_lookup(skb, dev, bareudp->net, sock, 502 + 0, &saddr, &info->key, 503 + 0, 0, info->key.tos, 504 + use_cache ? &info->dst_cache : NULL); 506 505 if (IS_ERR(dst)) 507 506 return PTR_ERR(dst); 508 507
+31 -65
drivers/net/geneve.c
··· 800 800 return dsfield; 801 801 } 802 802 803 - #if IS_ENABLED(CONFIG_IPV6) 804 - static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, 805 - struct net_device *dev, 806 - struct geneve_sock *gs6, 807 - struct flowi6 *fl6, 808 - const struct ip_tunnel_info *info, 809 - __be16 dport, __be16 sport) 810 - { 811 - bool use_cache = ip_tunnel_dst_cache_usable(skb, info); 812 - struct geneve_dev *geneve = netdev_priv(dev); 813 - struct dst_entry *dst = NULL; 814 - struct dst_cache *dst_cache; 815 - __u8 prio; 816 - 817 - if (!gs6) 818 - return ERR_PTR(-EIO); 819 - 820 - memset(fl6, 0, sizeof(*fl6)); 821 - fl6->flowi6_mark = skb->mark; 822 - fl6->flowi6_proto = IPPROTO_UDP; 823 - fl6->daddr = info->key.u.ipv6.dst; 824 - fl6->saddr = info->key.u.ipv6.src; 825 - fl6->fl6_dport = dport; 826 - fl6->fl6_sport = sport; 827 - 828 - prio = geneve_get_dsfield(skb, dev, info, &use_cache); 829 - fl6->flowlabel = ip6_make_flowinfo(prio, info->key.label); 830 - dst_cache = (struct dst_cache *)&info->dst_cache; 831 - if (use_cache) { 832 - dst = dst_cache_get_ip6(dst_cache, &fl6->saddr); 833 - if (dst) 834 - return dst; 835 - } 836 - dst = ipv6_stub->ipv6_dst_lookup_flow(geneve->net, gs6->sock->sk, fl6, 837 - NULL); 838 - if (IS_ERR(dst)) { 839 - netdev_dbg(dev, "no route to %pI6\n", &fl6->daddr); 840 - return ERR_PTR(-ENETUNREACH); 841 - } 842 - if (dst->dev == dev) { /* is this necessary? */ 843 - netdev_dbg(dev, "circular route to %pI6\n", &fl6->daddr); 844 - dst_release(dst); 845 - return ERR_PTR(-ELOOP); 846 - } 847 - 848 - if (use_cache) 849 - dst_cache_set_ip6(dst_cache, dst, &fl6->saddr); 850 - return dst; 851 - } 852 - #endif 853 - 854 803 static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, 855 804 struct geneve_dev *geneve, 856 805 const struct ip_tunnel_info *info) ··· 916 967 struct geneve_sock *gs6 = rcu_dereference(geneve->sock6); 917 968 const struct ip_tunnel_key *key = &info->key; 918 969 struct dst_entry *dst = NULL; 919 - struct flowi6 fl6; 970 + struct in6_addr saddr; 971 + bool use_cache; 920 972 __u8 prio, ttl; 921 973 __be16 sport; 922 974 int err; ··· 925 975 if (!pskb_inet_may_pull(skb)) 926 976 return -EINVAL; 927 977 978 + if (!gs6) 979 + return -EIO; 980 + 981 + use_cache = ip_tunnel_dst_cache_usable(skb, info); 982 + prio = geneve_get_dsfield(skb, dev, info, &use_cache); 928 983 sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); 929 - dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info, 930 - geneve->cfg.info.key.tp_dst, sport); 984 + 985 + dst = udp_tunnel6_dst_lookup(skb, dev, geneve->net, gs6->sock, 0, 986 + &saddr, key, sport, 987 + geneve->cfg.info.key.tp_dst, prio, 988 + use_cache ? 989 + (struct dst_cache *)&info->dst_cache : NULL); 931 990 if (IS_ERR(dst)) 932 991 return PTR_ERR(dst); 933 992 ··· 958 999 return -ENOMEM; 959 1000 } 960 1001 961 - unclone->key.u.ipv6.dst = fl6.saddr; 962 - unclone->key.u.ipv6.src = fl6.daddr; 1002 + unclone->key.u.ipv6.dst = saddr; 1003 + unclone->key.u.ipv6.src = info->key.u.ipv6.dst; 963 1004 } 964 1005 965 1006 if (!pskb_may_pull(skb, ETH_HLEN)) { ··· 973 1014 return -EMSGSIZE; 974 1015 } 975 1016 1017 + prio = ip_tunnel_ecn_encap(prio, ip_hdr(skb), skb); 976 1018 if (geneve->cfg.collect_md) { 977 - prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb); 978 1019 ttl = key->ttl; 979 1020 } else { 980 - prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel), 981 - ip_hdr(skb), skb); 982 1021 if (geneve->cfg.ttl_inherit) 983 1022 ttl = ip_tunnel_get_ttl(ip_hdr(skb), skb); 984 1023 else ··· 989 1032 return err; 990 1033 991 1034 udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev, 992 - &fl6.saddr, &fl6.daddr, prio, ttl, 1035 + &saddr, &key->u.ipv6.dst, prio, ttl, 993 1036 info->key.label, sport, geneve->cfg.info.key.tp_dst, 994 1037 !(info->key.tun_flags & TUNNEL_CSUM)); 995 1038 return 0; ··· 1083 1126 #if IS_ENABLED(CONFIG_IPV6) 1084 1127 } else if (ip_tunnel_info_af(info) == AF_INET6) { 1085 1128 struct dst_entry *dst; 1086 - struct flowi6 fl6; 1087 - 1088 1129 struct geneve_sock *gs6 = rcu_dereference(geneve->sock6); 1130 + struct in6_addr saddr; 1131 + bool use_cache; 1132 + u8 prio; 1133 + 1134 + if (!gs6) 1135 + return -EIO; 1136 + 1137 + use_cache = ip_tunnel_dst_cache_usable(skb, info); 1138 + prio = geneve_get_dsfield(skb, dev, info, &use_cache); 1089 1139 sport = udp_flow_src_port(geneve->net, skb, 1090 1140 1, USHRT_MAX, true); 1091 1141 1092 - dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info, 1093 - geneve->cfg.info.key.tp_dst, sport); 1142 + dst = udp_tunnel6_dst_lookup(skb, dev, geneve->net, gs6->sock, 0, 1143 + &saddr, &info->key, sport, 1144 + geneve->cfg.info.key.tp_dst, prio, 1145 + use_cache ? &info->dst_cache : NULL); 1094 1146 if (IS_ERR(dst)) 1095 1147 return PTR_ERR(dst); 1096 1148 1097 1149 dst_release(dst); 1098 - info->key.u.ipv6.src = fl6.saddr; 1150 + info->key.u.ipv6.src = saddr; 1099 1151 #endif 1100 1152 } else { 1101 1153 return -EINVAL;
+30 -106
drivers/net/vxlan/vxlan_core.c
··· 2215 2215 return 0; 2216 2216 } 2217 2217 2218 - #if IS_ENABLED(CONFIG_IPV6) 2219 - static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan, 2220 - struct net_device *dev, 2221 - struct vxlan_sock *sock6, 2222 - struct sk_buff *skb, int oif, u8 tos, 2223 - __be32 label, 2224 - const struct in6_addr *daddr, 2225 - struct in6_addr *saddr, 2226 - __be16 dport, __be16 sport, 2227 - struct dst_cache *dst_cache, 2228 - const struct ip_tunnel_info *info) 2229 - { 2230 - bool use_cache = ip_tunnel_dst_cache_usable(skb, info); 2231 - struct dst_entry *ndst; 2232 - struct flowi6 fl6; 2233 - 2234 - if (!sock6) 2235 - return ERR_PTR(-EIO); 2236 - 2237 - if (tos && !info) 2238 - use_cache = false; 2239 - if (use_cache) { 2240 - ndst = dst_cache_get_ip6(dst_cache, saddr); 2241 - if (ndst) 2242 - return ndst; 2243 - } 2244 - 2245 - memset(&fl6, 0, sizeof(fl6)); 2246 - fl6.flowi6_oif = oif; 2247 - fl6.daddr = *daddr; 2248 - fl6.saddr = *saddr; 2249 - fl6.flowlabel = ip6_make_flowinfo(tos, label); 2250 - fl6.flowi6_mark = skb->mark; 2251 - fl6.flowi6_proto = IPPROTO_UDP; 2252 - fl6.fl6_dport = dport; 2253 - fl6.fl6_sport = sport; 2254 - 2255 - ndst = ipv6_stub->ipv6_dst_lookup_flow(vxlan->net, sock6->sock->sk, 2256 - &fl6, NULL); 2257 - if (IS_ERR(ndst)) { 2258 - netdev_dbg(dev, "no route to %pI6\n", daddr); 2259 - return ERR_PTR(-ENETUNREACH); 2260 - } 2261 - 2262 - if (unlikely(ndst->dev == dev)) { 2263 - netdev_dbg(dev, "circular route to %pI6\n", daddr); 2264 - dst_release(ndst); 2265 - return ERR_PTR(-ELOOP); 2266 - } 2267 - 2268 - *saddr = fl6.saddr; 2269 - if (use_cache) 2270 - dst_cache_set_ip6(dst_cache, ndst, saddr); 2271 - return ndst; 2272 - } 2273 - #endif 2274 - 2275 2218 /* Bypass encapsulation if the destination is local */ 2276 2219 static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan, 2277 2220 struct vxlan_dev *dst_vxlan, __be32 vni, ··· 2268 2325 2269 2326 static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev, 2270 2327 struct vxlan_dev *vxlan, 2271 - union vxlan_addr *daddr, 2328 + int addr_family, 2272 2329 __be16 dst_port, int dst_ifindex, __be32 vni, 2273 2330 struct dst_entry *dst, 2274 2331 u32 rt_flags) ··· 2288 2345 2289 2346 dst_release(dst); 2290 2347 dst_vxlan = vxlan_find_vni(vxlan->net, dst_ifindex, vni, 2291 - daddr->sa.sa_family, dst_port, 2348 + addr_family, dst_port, 2292 2349 vxlan->cfg.flags); 2293 2350 if (!dst_vxlan) { 2294 2351 dev->stats.tx_errors++; ··· 2314 2371 struct ip_tunnel_key key; 2315 2372 struct vxlan_dev *vxlan = netdev_priv(dev); 2316 2373 const struct iphdr *old_iph = ip_hdr(skb); 2317 - union vxlan_addr *dst; 2318 - union vxlan_addr remote_ip; 2319 2374 struct vxlan_metadata _md; 2320 2375 struct vxlan_metadata *md = &_md; 2321 2376 unsigned int pkt_len = skb->len; 2322 2377 __be16 src_port = 0, dst_port; 2323 2378 struct dst_entry *ndst = NULL; 2379 + int addr_family; 2324 2380 __u8 tos, ttl; 2325 2381 int ifindex; 2326 2382 int err; ··· 2328 2386 bool udp_sum = false; 2329 2387 bool xnet = !net_eq(vxlan->net, dev_net(vxlan->dev)); 2330 2388 __be32 vni = 0; 2331 - #if IS_ENABLED(CONFIG_IPV6) 2332 - union vxlan_addr local_ip; 2333 - __be32 label; 2334 - #endif 2335 2389 2336 2390 info = skb_tunnel_info(skb); 2337 2391 use_cache = ip_tunnel_dst_cache_usable(skb, info); 2338 2392 2339 2393 if (rdst) { 2340 - dst = &rdst->remote_ip; 2341 2394 memset(&key, 0, sizeof(key)); 2342 2395 pkey = &key; 2343 2396 2344 - if (vxlan_addr_any(dst)) { 2397 + if (vxlan_addr_any(&rdst->remote_ip)) { 2345 2398 if (did_rsc) { 2346 2399 /* short-circuited back to local bridge */ 2347 2400 vxlan_encap_bypass(skb, vxlan, vxlan, ··· 2346 2409 goto drop; 2347 2410 } 2348 2411 2412 + addr_family = vxlan->cfg.saddr.sa.sa_family; 2349 2413 dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; 2350 2414 vni = (rdst->remote_vni) ? : default_vni; 2351 2415 ifindex = rdst->remote_ifindex; 2352 2416 2353 - if (dst->sa.sa_family == AF_INET) { 2417 + if (addr_family == AF_INET) { 2354 2418 key.u.ipv4.src = vxlan->cfg.saddr.sin.sin_addr.s_addr; 2355 2419 key.u.ipv4.dst = rdst->remote_ip.sin.sin_addr.s_addr; 2356 2420 } else { ··· 2365 2427 ttl = ip_tunnel_get_ttl(old_iph, skb); 2366 2428 } else { 2367 2429 ttl = vxlan->cfg.ttl; 2368 - if (!ttl && vxlan_addr_multicast(dst)) 2430 + if (!ttl && vxlan_addr_multicast(&rdst->remote_ip)) 2369 2431 ttl = 1; 2370 2432 } 2371 - 2372 2433 tos = vxlan->cfg.tos; 2373 2434 if (tos == 1) 2374 2435 tos = ip_tunnel_get_dsfield(old_iph, skb); 2375 2436 if (tos && !info) 2376 2437 use_cache = false; 2377 2438 2378 - if (dst->sa.sa_family == AF_INET) 2439 + if (addr_family == AF_INET) 2379 2440 udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM_TX); 2380 2441 else 2381 2442 udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX); 2382 2443 #if IS_ENABLED(CONFIG_IPV6) 2383 - local_ip = vxlan->cfg.saddr; 2384 - label = vxlan->cfg.label; 2444 + key.label = vxlan->cfg.label; 2385 2445 #endif 2386 2446 } else { 2387 2447 if (!info) { ··· 2387 2451 dev->name); 2388 2452 goto drop; 2389 2453 } 2390 - remote_ip.sa.sa_family = ip_tunnel_info_af(info); 2391 - if (remote_ip.sa.sa_family == AF_INET) { 2392 - remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; 2393 - } else { 2394 - remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst; 2395 - #if IS_ENABLED(CONFIG_IPV6) 2396 - local_ip.sin6.sin6_addr = info->key.u.ipv6.src; 2397 - #endif 2398 - } 2399 - dst = &remote_ip; 2400 2454 pkey = &info->key; 2455 + addr_family = ip_tunnel_info_af(info); 2401 2456 dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; 2402 2457 vni = tunnel_id_to_key32(info->key.tun_id); 2403 2458 ifindex = 0; ··· 2400 2473 } 2401 2474 ttl = info->key.ttl; 2402 2475 tos = info->key.tos; 2403 - #if IS_ENABLED(CONFIG_IPV6) 2404 - label = info->key.label; 2405 - #endif 2406 2476 udp_sum = !!(info->key.tun_flags & TUNNEL_CSUM); 2407 2477 } 2408 2478 src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min, 2409 2479 vxlan->cfg.port_max, true); 2410 2480 2411 2481 rcu_read_lock(); 2412 - if (dst->sa.sa_family == AF_INET) { 2482 + if (addr_family == AF_INET) { 2413 2483 struct vxlan_sock *sock4 = rcu_dereference(vxlan->vn4_sock); 2414 2484 struct rtable *rt; 2415 2485 __be16 df = 0; ··· 2425 2501 2426 2502 if (!info) { 2427 2503 /* Bypass encapsulation if the destination is local */ 2428 - err = encap_bypass_if_local(skb, dev, vxlan, dst, 2504 + err = encap_bypass_if_local(skb, dev, vxlan, AF_INET, 2429 2505 dst_port, ifindex, vni, 2430 2506 &rt->dst, rt->rt_flags); 2431 2507 if (err) ··· 2479 2555 #if IS_ENABLED(CONFIG_IPV6) 2480 2556 } else { 2481 2557 struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock); 2558 + struct in6_addr saddr; 2482 2559 2483 2560 if (!ifindex) 2484 2561 ifindex = sock6->sock->sk->sk_bound_dev_if; 2485 2562 2486 - ndst = vxlan6_get_route(vxlan, dev, sock6, skb, ifindex, tos, 2487 - label, &dst->sin6.sin6_addr, 2488 - &local_ip.sin6.sin6_addr, 2489 - dst_port, src_port, 2490 - dst_cache, info); 2563 + ndst = udp_tunnel6_dst_lookup(skb, dev, vxlan->net, sock6->sock, 2564 + ifindex, &saddr, pkey, 2565 + src_port, dst_port, tos, 2566 + use_cache ? dst_cache : NULL); 2491 2567 if (IS_ERR(ndst)) { 2492 2568 err = PTR_ERR(ndst); 2493 2569 ndst = NULL; ··· 2497 2573 if (!info) { 2498 2574 u32 rt6i_flags = ((struct rt6_info *)ndst)->rt6i_flags; 2499 2575 2500 - err = encap_bypass_if_local(skb, dev, vxlan, dst, 2576 + err = encap_bypass_if_local(skb, dev, vxlan, AF_INET6, 2501 2577 dst_port, ifindex, vni, 2502 2578 ndst, rt6i_flags); 2503 2579 if (err) ··· 2512 2588 } else if (err) { 2513 2589 if (info) { 2514 2590 struct ip_tunnel_info *unclone; 2515 - struct in6_addr src, dst; 2516 2591 2517 2592 unclone = skb_tunnel_info_unclone(skb); 2518 2593 if (unlikely(!unclone)) 2519 2594 goto tx_error; 2520 2595 2521 - src = remote_ip.sin6.sin6_addr; 2522 - dst = local_ip.sin6.sin6_addr; 2523 - unclone->key.u.ipv6.src = src; 2524 - unclone->key.u.ipv6.dst = dst; 2596 + unclone->key.u.ipv6.src = pkey->u.ipv6.dst; 2597 + unclone->key.u.ipv6.dst = saddr; 2525 2598 } 2526 2599 2527 2600 vxlan_encap_bypass(skb, vxlan, vxlan, vni, false); ··· 2535 2614 goto tx_error; 2536 2615 2537 2616 udp_tunnel6_xmit_skb(ndst, sock6->sock->sk, skb, dev, 2538 - &local_ip.sin6.sin6_addr, 2539 - &dst->sin6.sin6_addr, tos, ttl, 2540 - label, src_port, dst_port, !udp_sum); 2617 + &saddr, &pkey->u.ipv6.dst, tos, ttl, 2618 + pkey->label, src_port, dst_port, !udp_sum); 2541 2619 #endif 2542 2620 } 2543 2621 vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX, pkt_len); ··· 3187 3267 struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock); 3188 3268 struct dst_entry *ndst; 3189 3269 3190 - ndst = vxlan6_get_route(vxlan, dev, sock6, skb, 0, info->key.tos, 3191 - info->key.label, &info->key.u.ipv6.dst, 3192 - &info->key.u.ipv6.src, dport, sport, 3193 - &info->dst_cache, info); 3270 + if (!sock6) 3271 + return -EIO; 3272 + 3273 + ndst = udp_tunnel6_dst_lookup(skb, dev, vxlan->net, sock6->sock, 3274 + 0, &info->key.u.ipv6.src, 3275 + &info->key, 3276 + sport, dport, info->key.tos, 3277 + &info->dst_cache); 3194 3278 if (IS_ERR(ndst)) 3195 3279 return PTR_ERR(ndst); 3196 3280 dst_release(ndst);
-6
include/net/ipv6.h
··· 1133 1133 struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, 1134 1134 const struct in6_addr *final_dst, 1135 1135 bool connected); 1136 - struct dst_entry *ip6_dst_lookup_tunnel(struct sk_buff *skb, 1137 - struct net_device *dev, 1138 - struct net *net, struct socket *sock, 1139 - struct in6_addr *saddr, 1140 - const struct ip_tunnel_info *info, 1141 - u8 protocol, bool use_cache); 1142 1136 struct dst_entry *ip6_blackhole_route(struct net *net, 1143 1137 struct dst_entry *orig_dst); 1144 1138
+8
include/net/udp_tunnel.h
··· 169 169 const struct ip_tunnel_key *key, 170 170 __be16 sport, __be16 dport, u8 tos, 171 171 struct dst_cache *dst_cache); 172 + struct dst_entry *udp_tunnel6_dst_lookup(struct sk_buff *skb, 173 + struct net_device *dev, 174 + struct net *net, 175 + struct socket *sock, int oif, 176 + struct in6_addr *saddr, 177 + const struct ip_tunnel_key *key, 178 + __be16 sport, __be16 dport, u8 dsfield, 179 + struct dst_cache *dst_cache); 172 180 173 181 struct metadata_dst *udp_tun_rx_dst(struct sk_buff *skb, unsigned short family, 174 182 __be16 flags, __be64 tunnel_id,
-68
net/ipv6/ip6_output.c
··· 1283 1283 } 1284 1284 EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); 1285 1285 1286 - /** 1287 - * ip6_dst_lookup_tunnel - perform route lookup on tunnel 1288 - * @skb: Packet for which lookup is done 1289 - * @dev: Tunnel device 1290 - * @net: Network namespace of tunnel device 1291 - * @sock: Socket which provides route info 1292 - * @saddr: Memory to store the src ip address 1293 - * @info: Tunnel information 1294 - * @protocol: IP protocol 1295 - * @use_cache: Flag to enable cache usage 1296 - * This function performs a route lookup on a tunnel 1297 - * 1298 - * It returns a valid dst pointer and stores src address to be used in 1299 - * tunnel in param saddr on success, else a pointer encoded error code. 1300 - */ 1301 - 1302 - struct dst_entry *ip6_dst_lookup_tunnel(struct sk_buff *skb, 1303 - struct net_device *dev, 1304 - struct net *net, 1305 - struct socket *sock, 1306 - struct in6_addr *saddr, 1307 - const struct ip_tunnel_info *info, 1308 - u8 protocol, 1309 - bool use_cache) 1310 - { 1311 - struct dst_entry *dst = NULL; 1312 - #ifdef CONFIG_DST_CACHE 1313 - struct dst_cache *dst_cache; 1314 - #endif 1315 - struct flowi6 fl6; 1316 - __u8 prio; 1317 - 1318 - #ifdef CONFIG_DST_CACHE 1319 - dst_cache = (struct dst_cache *)&info->dst_cache; 1320 - if (use_cache) { 1321 - dst = dst_cache_get_ip6(dst_cache, saddr); 1322 - if (dst) 1323 - return dst; 1324 - } 1325 - #endif 1326 - memset(&fl6, 0, sizeof(fl6)); 1327 - fl6.flowi6_mark = skb->mark; 1328 - fl6.flowi6_proto = protocol; 1329 - fl6.daddr = info->key.u.ipv6.dst; 1330 - fl6.saddr = info->key.u.ipv6.src; 1331 - prio = info->key.tos; 1332 - fl6.flowlabel = ip6_make_flowinfo(prio, info->key.label); 1333 - 1334 - dst = ipv6_stub->ipv6_dst_lookup_flow(net, sock->sk, &fl6, 1335 - NULL); 1336 - if (IS_ERR(dst)) { 1337 - netdev_dbg(dev, "no route to %pI6\n", &fl6.daddr); 1338 - return ERR_PTR(-ENETUNREACH); 1339 - } 1340 - if (dst->dev == dev) { /* is this necessary? */ 1341 - netdev_dbg(dev, "circular route to %pI6\n", &fl6.daddr); 1342 - dst_release(dst); 1343 - return ERR_PTR(-ELOOP); 1344 - } 1345 - #ifdef CONFIG_DST_CACHE 1346 - if (use_cache) 1347 - dst_cache_set_ip6(dst_cache, dst, &fl6.saddr); 1348 - #endif 1349 - *saddr = fl6.saddr; 1350 - return dst; 1351 - } 1352 - EXPORT_SYMBOL_GPL(ip6_dst_lookup_tunnel); 1353 - 1354 1286 static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, 1355 1287 gfp_t gfp) 1356 1288 {
+70
net/ipv6/ip6_udp_tunnel.c
··· 1 + 1 2 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/module.h> 3 4 #include <linux/errno.h> ··· 112 111 return 0; 113 112 } 114 113 EXPORT_SYMBOL_GPL(udp_tunnel6_xmit_skb); 114 + 115 + /** 116 + * udp_tunnel6_dst_lookup - perform route lookup on UDP tunnel 117 + * @skb: Packet for which lookup is done 118 + * @dev: Tunnel device 119 + * @net: Network namespace of tunnel device 120 + * @sock: Socket which provides route info 121 + * @oif: Index of the output interface 122 + * @saddr: Memory to store the src ip address 123 + * @key: Tunnel information 124 + * @sport: UDP source port 125 + * @dport: UDP destination port 126 + * @dsfield: The traffic class field 127 + * @dst_cache: The dst cache to use for lookup 128 + * This function performs a route lookup on a UDP tunnel 129 + * 130 + * It returns a valid dst pointer and stores src address to be used in 131 + * tunnel in param saddr on success, else a pointer encoded error code. 132 + */ 133 + 134 + struct dst_entry *udp_tunnel6_dst_lookup(struct sk_buff *skb, 135 + struct net_device *dev, 136 + struct net *net, 137 + struct socket *sock, 138 + int oif, 139 + struct in6_addr *saddr, 140 + const struct ip_tunnel_key *key, 141 + __be16 sport, __be16 dport, u8 dsfield, 142 + struct dst_cache *dst_cache) 143 + { 144 + struct dst_entry *dst = NULL; 145 + struct flowi6 fl6; 146 + 147 + #ifdef CONFIG_DST_CACHE 148 + if (dst_cache) { 149 + dst = dst_cache_get_ip6(dst_cache, saddr); 150 + if (dst) 151 + return dst; 152 + } 153 + #endif 154 + memset(&fl6, 0, sizeof(fl6)); 155 + fl6.flowi6_mark = skb->mark; 156 + fl6.flowi6_proto = IPPROTO_UDP; 157 + fl6.flowi6_oif = oif; 158 + fl6.daddr = key->u.ipv6.dst; 159 + fl6.saddr = key->u.ipv6.src; 160 + fl6.fl6_sport = sport; 161 + fl6.fl6_dport = dport; 162 + fl6.flowlabel = ip6_make_flowinfo(dsfield, key->label); 163 + 164 + dst = ipv6_stub->ipv6_dst_lookup_flow(net, sock->sk, &fl6, 165 + NULL); 166 + if (IS_ERR(dst)) { 167 + netdev_dbg(dev, "no route to %pI6\n", &fl6.daddr); 168 + return ERR_PTR(-ENETUNREACH); 169 + } 170 + if (dst->dev == dev) { /* is this necessary? */ 171 + netdev_dbg(dev, "circular route to %pI6\n", &fl6.daddr); 172 + dst_release(dst); 173 + return ERR_PTR(-ELOOP); 174 + } 175 + #ifdef CONFIG_DST_CACHE 176 + if (dst_cache) 177 + dst_cache_set_ip6(dst_cache, dst, &fl6.saddr); 178 + #endif 179 + *saddr = fl6.saddr; 180 + return dst; 181 + } 182 + EXPORT_SYMBOL_GPL(udp_tunnel6_dst_lookup); 115 183 116 184 MODULE_LICENSE("GPL");