diff options
-rw-r--r-- | net/ipv4/ip_tunnel.c | 38 |
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 | } |