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

ip_tunnel: Add ip tunnel tun_info type dst_cache in ip_tunnel_xmit

ip l add dev tun type gretap key 1000

Non-tunnel-dst ip tunnel device can send packet through lwtunnel
This patch provide the tun_inf dst cache support for this mode.

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

authored by

wenxu and committed by
David S. Miller
186d9366 169431ed

+27 -11
+27 -11
net/ipv4/ip_tunnel.c
··· 654 654 const struct iphdr *tnl_params, u8 protocol) 655 655 { 656 656 struct ip_tunnel *tunnel = netdev_priv(dev); 657 + struct ip_tunnel_info *tun_info = NULL; 657 658 const struct iphdr *inner_iph; 658 - struct flowi4 fl4; 659 - u8 tos, ttl; 660 - __be16 df; 661 - struct rtable *rt; /* Route to the other host */ 662 659 unsigned int max_headroom; /* The extra header space needed */ 663 - __be32 dst; 660 + struct rtable *rt = NULL; /* Route to the other host */ 661 + bool use_cache = false; 662 + struct flowi4 fl4; 663 + bool md = false; 664 664 bool connected; 665 + u8 tos, ttl; 666 + __be32 dst; 667 + __be16 df; 665 668 666 669 inner_iph = (const struct iphdr *)skb_inner_network_header(skb); 667 670 connected = (tunnel->parms.iph.daddr != 0); ··· 674 671 dst = tnl_params->daddr; 675 672 if (dst == 0) { 676 673 /* NBMA tunnel */ 677 - struct ip_tunnel_info *tun_info; 678 674 679 675 if (!skb_dst(skb)) { 680 676 dev->stats.tx_fifo_errors++; ··· 683 681 tun_info = skb_tunnel_info(skb); 684 682 if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) && 685 683 ip_tunnel_info_af(tun_info) == AF_INET && 686 - tun_info->key.u.ipv4.dst) 684 + tun_info->key.u.ipv4.dst) { 687 685 dst = tun_info->key.u.ipv4.dst; 686 + md = true; 687 + connected = true; 688 + } 688 689 else if (skb->protocol == htons(ETH_P_IP)) { 689 690 rt = skb_rtable(skb); 690 691 dst = rt_nexthop(rt, inner_iph->daddr); ··· 726 721 else 727 722 goto tx_error; 728 723 729 - connected = false; 724 + if (!md) 725 + connected = false; 730 726 } 731 727 732 728 tos = tnl_params->tos; ··· 749 743 if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) 750 744 goto tx_error; 751 745 752 - rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr) : 753 - NULL; 746 + if (connected && md) { 747 + use_cache = ip_tunnel_dst_cache_usable(skb, tun_info); 748 + if (use_cache) 749 + rt = dst_cache_get_ip4(&tun_info->dst_cache, 750 + &fl4.saddr); 751 + } else { 752 + rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, 753 + &fl4.saddr) : NULL; 754 + } 754 755 755 756 if (!rt) { 756 757 rt = ip_route_output_key(tunnel->net, &fl4); ··· 766 753 dev->stats.tx_carrier_errors++; 767 754 goto tx_error; 768 755 } 769 - if (connected) 756 + if (use_cache) 757 + dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst, 758 + fl4.saddr); 759 + else if (!md && connected) 770 760 dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, 771 761 fl4.saddr); 772 762 }