aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/ip_tunnel.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 893f013d5369..2973067b831d 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -654,14 +654,17 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
654 const struct iphdr *tnl_params, u8 protocol) 654 const struct iphdr *tnl_params, u8 protocol)
655{ 655{
656 struct ip_tunnel *tunnel = netdev_priv(dev); 656 struct ip_tunnel *tunnel = netdev_priv(dev);
657 struct ip_tunnel_info *tun_info = NULL;
657 const struct iphdr *inner_iph; 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 unsigned int max_headroom; /* The extra header space needed */ 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 bool connected; 664 bool connected;
665 u8 tos, ttl;
666 __be32 dst;
667 __be16 df;
665 668
666 inner_iph = (const struct iphdr *)skb_inner_network_header(skb); 669 inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
667 connected = (tunnel->parms.iph.daddr != 0); 670 connected = (tunnel->parms.iph.daddr != 0);
@@ -671,7 +674,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
671 dst = tnl_params->daddr; 674 dst = tnl_params->daddr;
672 if (dst == 0) { 675 if (dst == 0) {
673 /* NBMA tunnel */ 676 /* NBMA tunnel */
674 struct ip_tunnel_info *tun_info;
675 677
676 if (!skb_dst(skb)) { 678 if (!skb_dst(skb)) {
677 dev->stats.tx_fifo_errors++; 679 dev->stats.tx_fifo_errors++;
@@ -681,8 +683,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
681 tun_info = skb_tunnel_info(skb); 683 tun_info = skb_tunnel_info(skb);
682 if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) && 684 if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) &&
683 ip_tunnel_info_af(tun_info) == AF_INET && 685 ip_tunnel_info_af(tun_info) == AF_INET &&
684 tun_info->key.u.ipv4.dst) 686 tun_info->key.u.ipv4.dst) {
685 dst = tun_info->key.u.ipv4.dst; 687 dst = tun_info->key.u.ipv4.dst;
688 md = true;
689 connected = true;
690 }
686 else if (skb->protocol == htons(ETH_P_IP)) { 691 else if (skb->protocol == htons(ETH_P_IP)) {
687 rt = skb_rtable(skb); 692 rt = skb_rtable(skb);
688 dst = rt_nexthop(rt, inner_iph->daddr); 693 dst = rt_nexthop(rt, inner_iph->daddr);
@@ -721,7 +726,8 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
721 else 726 else
722 goto tx_error; 727 goto tx_error;
723 728
724 connected = false; 729 if (!md)
730 connected = false;
725 } 731 }
726 732
727 tos = tnl_params->tos; 733 tos = tnl_params->tos;
@@ -743,8 +749,15 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
743 if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0) 749 if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
744 goto tx_error; 750 goto tx_error;
745 751
746 rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache, &fl4.saddr) : 752 if (connected && md) {
747 NULL; 753 use_cache = ip_tunnel_dst_cache_usable(skb, tun_info);
754 if (use_cache)
755 rt = dst_cache_get_ip4(&tun_info->dst_cache,
756 &fl4.saddr);
757 } else {
758 rt = connected ? dst_cache_get_ip4(&tunnel->dst_cache,
759 &fl4.saddr) : NULL;
760 }
748 761
749 if (!rt) { 762 if (!rt) {
750 rt = ip_route_output_key(tunnel->net, &fl4); 763 rt = ip_route_output_key(tunnel->net, &fl4);
@@ -753,7 +766,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
753 dev->stats.tx_carrier_errors++; 766 dev->stats.tx_carrier_errors++;
754 goto tx_error; 767 goto tx_error;
755 } 768 }
756 if (connected) 769 if (use_cache)
770 dst_cache_set_ip4(&tun_info->dst_cache, &rt->dst,
771 fl4.saddr);
772 else if (!md && connected)
757 dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, 773 dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst,
758 fl4.saddr); 774 fl4.saddr);
759 } 775 }