@@ -873,16 +873,13 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
873
873
struct flowi6 * fl6 , int flags )
874
874
{
875
875
struct fib6_node * fn , * saved_fn ;
876
- struct rt6_info * rt , * nrt ;
876
+ struct rt6_info * rt ;
877
877
int strict = 0 ;
878
- int attempts = 3 ;
879
- int err ;
880
878
881
879
strict |= flags & RT6_LOOKUP_F_IFACE ;
882
880
if (net -> ipv6 .devconf_all -> forwarding == 0 )
883
881
strict |= RT6_LOOKUP_F_REACHABLE ;
884
882
885
- redo_fib6_lookup_lock :
886
883
read_lock_bh (& table -> tb6_lock );
887
884
888
885
fn = fib6_lookup (& table -> tb6_root , & fl6 -> daddr , & fl6 -> saddr );
@@ -901,46 +898,12 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
901
898
strict &= ~RT6_LOOKUP_F_REACHABLE ;
902
899
fn = saved_fn ;
903
900
goto redo_rt6_select ;
904
- } else {
905
- dst_hold (& rt -> dst );
906
- read_unlock_bh (& table -> tb6_lock );
907
- goto out2 ;
908
901
}
909
902
}
910
903
911
904
dst_hold (& rt -> dst );
912
905
read_unlock_bh (& table -> tb6_lock );
913
906
914
- if (rt -> rt6i_flags & RTF_CACHE )
915
- goto out2 ;
916
-
917
- if (!rt6_is_gw_or_nonexthop (rt ) ||
918
- !(rt -> dst .flags & DST_HOST ) || !(rt -> rt6i_flags & RTF_LOCAL ))
919
- nrt = ip6_rt_cache_alloc (rt , & fl6 -> daddr , & fl6 -> saddr );
920
- else
921
- goto out2 ;
922
-
923
- ip6_rt_put (rt );
924
- rt = nrt ? : net -> ipv6 .ip6_null_entry ;
925
-
926
- dst_hold (& rt -> dst );
927
- if (nrt ) {
928
- err = ip6_ins_rt (nrt );
929
- if (!err )
930
- goto out2 ;
931
- }
932
-
933
- if (-- attempts <= 0 )
934
- goto out2 ;
935
-
936
- /*
937
- * Race condition! In the gap, when table->tb6_lock was
938
- * released someone could insert this route. Relookup.
939
- */
940
- ip6_rt_put (rt );
941
- goto redo_fib6_lookup_lock ;
942
-
943
- out2 :
944
907
rt6_dst_from_metrics_check (rt );
945
908
rt -> dst .lastuse = jiffies ;
946
909
rt -> dst .__use ++ ;
@@ -1113,24 +1076,63 @@ static void ip6_link_failure(struct sk_buff *skb)
1113
1076
}
1114
1077
}
1115
1078
1116
- static void ip6_rt_update_pmtu (struct dst_entry * dst , struct sock * sk ,
1117
- struct sk_buff * skb , u32 mtu )
1079
+ static void rt6_do_update_pmtu (struct rt6_info * rt , u32 mtu )
1080
+ {
1081
+ struct net * net = dev_net (rt -> dst .dev );
1082
+
1083
+ rt -> rt6i_flags |= RTF_MODIFIED ;
1084
+ rt -> rt6i_pmtu = mtu ;
1085
+ rt6_update_expires (rt , net -> ipv6 .sysctl .ip6_rt_mtu_expires );
1086
+ }
1087
+
1088
+ static void __ip6_rt_update_pmtu (struct dst_entry * dst , const struct sock * sk ,
1089
+ const struct ipv6hdr * iph , u32 mtu )
1118
1090
{
1119
1091
struct rt6_info * rt6 = (struct rt6_info * )dst ;
1120
1092
1121
- dst_confirm (dst );
1122
- if (mtu < dst_mtu (dst ) && (rt6 -> rt6i_flags & RTF_CACHE )) {
1123
- struct net * net = dev_net (dst -> dev );
1093
+ if (rt6 -> rt6i_flags & RTF_LOCAL )
1094
+ return ;
1124
1095
1125
- rt6 -> rt6i_flags |= RTF_MODIFIED ;
1126
- if (mtu < IPV6_MIN_MTU )
1127
- mtu = IPV6_MIN_MTU ;
1096
+ dst_confirm (dst );
1097
+ mtu = max_t (u32 , mtu , IPV6_MIN_MTU );
1098
+ if (mtu >= dst_mtu (dst ))
1099
+ return ;
1128
1100
1129
- rt6 -> rt6i_pmtu = mtu ;
1130
- rt6_update_expires (rt6 , net -> ipv6 .sysctl .ip6_rt_mtu_expires );
1101
+ if (rt6 -> rt6i_flags & RTF_CACHE ) {
1102
+ rt6_do_update_pmtu (rt6 , mtu );
1103
+ } else {
1104
+ const struct in6_addr * daddr , * saddr ;
1105
+ struct rt6_info * nrt6 ;
1106
+
1107
+ if (iph ) {
1108
+ daddr = & iph -> daddr ;
1109
+ saddr = & iph -> saddr ;
1110
+ } else if (sk ) {
1111
+ daddr = & sk -> sk_v6_daddr ;
1112
+ saddr = & inet6_sk (sk )-> saddr ;
1113
+ } else {
1114
+ return ;
1115
+ }
1116
+ nrt6 = ip6_rt_cache_alloc (rt6 , daddr , saddr );
1117
+ if (nrt6 ) {
1118
+ rt6_do_update_pmtu (nrt6 , mtu );
1119
+
1120
+ /* ip6_ins_rt(nrt6) will bump the
1121
+ * rt6->rt6i_node->fn_sernum
1122
+ * which will fail the next rt6_check() and
1123
+ * invalidate the sk->sk_dst_cache.
1124
+ */
1125
+ ip6_ins_rt (nrt6 );
1126
+ }
1131
1127
}
1132
1128
}
1133
1129
1130
+ static void ip6_rt_update_pmtu (struct dst_entry * dst , struct sock * sk ,
1131
+ struct sk_buff * skb , u32 mtu )
1132
+ {
1133
+ __ip6_rt_update_pmtu (dst , sk , skb ? ipv6_hdr (skb ) : NULL , mtu );
1134
+ }
1135
+
1134
1136
void ip6_update_pmtu (struct sk_buff * skb , struct net * net , __be32 mtu ,
1135
1137
int oif , u32 mark )
1136
1138
{
@@ -1147,7 +1149,7 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
1147
1149
1148
1150
dst = ip6_route_output (net , NULL , & fl6 );
1149
1151
if (!dst -> error )
1150
- ip6_rt_update_pmtu (dst , NULL , skb , ntohl (mtu ));
1152
+ __ip6_rt_update_pmtu (dst , NULL , iph , ntohl (mtu ));
1151
1153
dst_release (dst );
1152
1154
}
1153
1155
EXPORT_SYMBOL_GPL (ip6_update_pmtu );
0 commit comments