@@ -68,6 +68,54 @@ static unsigned int ip_tunnel_hash(struct ip_tunnel_net *itn,
6868 IP_TNL_HASH_BITS );
6969}
7070
71+ static inline void __tunnel_dst_set (struct ip_tunnel * t , struct dst_entry * dst )
72+ {
73+ struct dst_entry * old_dst ;
74+
75+ if (dst && (dst -> flags & DST_NOCACHE ))
76+ dst = NULL ;
77+
78+ spin_lock_bh (& t -> dst_lock );
79+ old_dst = rcu_dereference_raw (t -> dst_cache );
80+ rcu_assign_pointer (t -> dst_cache , dst );
81+ dst_release (old_dst );
82+ spin_unlock_bh (& t -> dst_lock );
83+ }
84+
85+ static inline void tunnel_dst_set (struct ip_tunnel * t , struct dst_entry * dst )
86+ {
87+ __tunnel_dst_set (t , dst );
88+ }
89+
90+ static inline void tunnel_dst_reset (struct ip_tunnel * t )
91+ {
92+ tunnel_dst_set (t , NULL );
93+ }
94+
95+ static inline struct dst_entry * tunnel_dst_get (struct ip_tunnel * t )
96+ {
97+ struct dst_entry * dst ;
98+
99+ rcu_read_lock ();
100+ dst = rcu_dereference (t -> dst_cache );
101+ if (dst )
102+ dst_hold (dst );
103+ rcu_read_unlock ();
104+ return dst ;
105+ }
106+
107+ struct dst_entry * tunnel_dst_check (struct ip_tunnel * t , u32 cookie )
108+ {
109+ struct dst_entry * dst = tunnel_dst_get (t );
110+
111+ if (dst && dst -> obsolete && dst -> ops -> check (dst , cookie ) == NULL ) {
112+ tunnel_dst_reset (t );
113+ return NULL ;
114+ }
115+
116+ return dst ;
117+ }
118+
71119/* Often modified stats are per cpu, other are shared (netdev->stats) */
72120struct rtnl_link_stats64 * ip_tunnel_get_stats64 (struct net_device * dev ,
73121 struct rtnl_link_stats64 * tot )
@@ -318,11 +366,10 @@ static struct net_device *__ip_tunnel_create(struct net *net,
318366 return ERR_PTR (err );
319367}
320368
321- static inline struct rtable * ip_route_output_tunnel (struct net * net ,
322- struct flowi4 * fl4 ,
323- int proto ,
324- __be32 daddr , __be32 saddr ,
325- __be32 key , __u8 tos , int oif )
369+ static inline void init_tunnel_flow (struct flowi4 * fl4 ,
370+ int proto ,
371+ __be32 daddr , __be32 saddr ,
372+ __be32 key , __u8 tos , int oif )
326373{
327374 memset (fl4 , 0 , sizeof (* fl4 ));
328375 fl4 -> flowi4_oif = oif ;
@@ -331,7 +378,6 @@ static inline struct rtable *ip_route_output_tunnel(struct net *net,
331378 fl4 -> flowi4_tos = tos ;
332379 fl4 -> flowi4_proto = proto ;
333380 fl4 -> fl4_gre_key = key ;
334- return ip_route_output_key (net , fl4 );
335381}
336382
337383static int ip_tunnel_bind_dev (struct net_device * dev )
@@ -350,14 +396,14 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
350396 struct flowi4 fl4 ;
351397 struct rtable * rt ;
352398
353- rt = ip_route_output_tunnel (tunnel -> net , & fl4 ,
354- tunnel -> parms .iph .protocol ,
355- iph -> daddr , iph -> saddr ,
356- tunnel -> parms .o_key ,
357- RT_TOS (iph -> tos ),
358- tunnel -> parms .link );
399+ init_tunnel_flow (& fl4 , iph -> protocol , iph -> daddr ,
400+ iph -> saddr , tunnel -> parms .o_key ,
401+ RT_TOS (iph -> tos ), tunnel -> parms .link );
402+ rt = ip_route_output_key (tunnel -> net , & fl4 );
403+
359404 if (!IS_ERR (rt )) {
360405 tdev = rt -> dst .dev ;
406+ tunnel_dst_set (tunnel , dst_clone (& rt -> dst ));
361407 ip_rt_put (rt );
362408 }
363409 if (dev -> type != ARPHRD_ETHER )
@@ -528,10 +574,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
528574 struct flowi4 fl4 ;
529575 u8 tos , ttl ;
530576 __be16 df ;
531- struct rtable * rt ; /* Route to the other host */
577+ struct rtable * rt = NULL ; /* Route to the other host */
532578 unsigned int max_headroom ; /* The extra header space needed */
533579 __be32 dst ;
534580 int err ;
581+ bool connected = true;
535582
536583 inner_iph = (const struct iphdr * )skb_inner_network_header (skb );
537584
@@ -581,27 +628,39 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
581628#endif
582629 else
583630 goto tx_error ;
631+
632+ connected = false;
584633 }
585634
586635 tos = tnl_params -> tos ;
587636 if (tos & 0x1 ) {
588637 tos &= ~0x1 ;
589- if (skb -> protocol == htons (ETH_P_IP ))
638+ if (skb -> protocol == htons (ETH_P_IP )) {
590639 tos = inner_iph -> tos ;
591- else if (skb -> protocol == htons (ETH_P_IPV6 ))
640+ connected = false;
641+ } else if (skb -> protocol == htons (ETH_P_IPV6 )) {
592642 tos = ipv6_get_dsfield ((const struct ipv6hdr * )inner_iph );
643+ connected = false;
644+ }
593645 }
594646
595- rt = ip_route_output_tunnel (tunnel -> net , & fl4 ,
596- protocol ,
597- dst , tnl_params -> saddr ,
598- tunnel -> parms .o_key ,
599- RT_TOS (tos ),
600- tunnel -> parms .link );
601- if (IS_ERR (rt )) {
602- dev -> stats .tx_carrier_errors ++ ;
603- goto tx_error ;
647+ init_tunnel_flow (& fl4 , protocol , dst , tnl_params -> saddr ,
648+ tunnel -> parms .o_key , RT_TOS (tos ), tunnel -> parms .link );
649+
650+ if (connected )
651+ rt = (struct rtable * )tunnel_dst_check (tunnel , 0 );
652+
653+ if (!rt ) {
654+ rt = ip_route_output_key (tunnel -> net , & fl4 );
655+
656+ if (IS_ERR (rt )) {
657+ dev -> stats .tx_carrier_errors ++ ;
658+ goto tx_error ;
659+ }
660+ if (connected )
661+ tunnel_dst_set (tunnel , dst_clone (& rt -> dst ));
604662 }
663+
605664 if (rt -> dst .dev == dev ) {
606665 ip_rt_put (rt );
607666 dev -> stats .collisions ++ ;
@@ -696,6 +755,7 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn,
696755 if (set_mtu )
697756 dev -> mtu = mtu ;
698757 }
758+ tunnel_dst_reset (t );
699759 netdev_state_change (dev );
700760}
701761
@@ -1001,6 +1061,9 @@ int ip_tunnel_init(struct net_device *dev)
10011061 iph -> version = 4 ;
10021062 iph -> ihl = 5 ;
10031063
1064+ tunnel -> dst_cache = NULL ;
1065+ spin_lock_init (& tunnel -> dst_lock );
1066+
10041067 return 0 ;
10051068}
10061069EXPORT_SYMBOL_GPL (ip_tunnel_init );
@@ -1015,6 +1078,8 @@ void ip_tunnel_uninit(struct net_device *dev)
10151078 /* fb_tunnel_dev will be unregisted in net-exit call. */
10161079 if (itn -> fb_tunnel_dev != dev )
10171080 ip_tunnel_del (netdev_priv (dev ));
1081+
1082+ tunnel_dst_reset (tunnel );
10181083}
10191084EXPORT_SYMBOL_GPL (ip_tunnel_uninit );
10201085
0 commit comments