diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/ah4.c | 7 | ||||
-rw-r--r-- | net/ipv4/esp4.c | 7 | ||||
-rw-r--r-- | net/ipv4/ipcomp.c | 7 | ||||
-rw-r--r-- | net/ipv4/route.c | 63 |
4 files changed, 43 insertions, 41 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 2e7f1948216f..717902669d2f 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
@@ -419,12 +419,9 @@ static void ah4_err(struct sk_buff *skb, u32 info) | |||
419 | if (!x) | 419 | if (!x) |
420 | return; | 420 | return; |
421 | 421 | ||
422 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) { | 422 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) |
423 | atomic_inc(&flow_cache_genid); | ||
424 | rt_genid_bump(net); | ||
425 | |||
426 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0); | 423 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0); |
427 | } else | 424 | else |
428 | ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0); | 425 | ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0); |
429 | xfrm_state_put(x); | 426 | xfrm_state_put(x); |
430 | } | 427 | } |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 4cfe34d4cc96..ab3d814bc80a 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -502,12 +502,9 @@ static void esp4_err(struct sk_buff *skb, u32 info) | |||
502 | if (!x) | 502 | if (!x) |
503 | return; | 503 | return; |
504 | 504 | ||
505 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) { | 505 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) |
506 | atomic_inc(&flow_cache_genid); | ||
507 | rt_genid_bump(net); | ||
508 | |||
509 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); | 506 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); |
510 | } else | 507 | else |
511 | ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0); | 508 | ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0); |
512 | xfrm_state_put(x); | 509 | xfrm_state_put(x); |
513 | } | 510 | } |
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 59cb8c769056..826be4cb482a 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
@@ -47,12 +47,9 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) | |||
47 | if (!x) | 47 | if (!x) |
48 | return; | 48 | return; |
49 | 49 | ||
50 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) { | 50 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) |
51 | atomic_inc(&flow_cache_genid); | ||
52 | rt_genid_bump(net); | ||
53 | |||
54 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0); | 51 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0); |
55 | } else | 52 | else |
56 | ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0); | 53 | ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0); |
57 | xfrm_state_put(x); | 54 | xfrm_state_put(x); |
58 | } | 55 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 550781a17b34..561a37833d86 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -594,11 +594,25 @@ static inline u32 fnhe_hashfun(__be32 daddr) | |||
594 | return hval & (FNHE_HASH_SIZE - 1); | 594 | return hval & (FNHE_HASH_SIZE - 1); |
595 | } | 595 | } |
596 | 596 | ||
597 | static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnhe) | ||
598 | { | ||
599 | rt->rt_pmtu = fnhe->fnhe_pmtu; | ||
600 | rt->dst.expires = fnhe->fnhe_expires; | ||
601 | |||
602 | if (fnhe->fnhe_gw) { | ||
603 | rt->rt_flags |= RTCF_REDIRECTED; | ||
604 | rt->rt_gateway = fnhe->fnhe_gw; | ||
605 | rt->rt_uses_gateway = 1; | ||
606 | } | ||
607 | } | ||
608 | |||
597 | static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, | 609 | static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, |
598 | u32 pmtu, unsigned long expires) | 610 | u32 pmtu, unsigned long expires) |
599 | { | 611 | { |
600 | struct fnhe_hash_bucket *hash; | 612 | struct fnhe_hash_bucket *hash; |
601 | struct fib_nh_exception *fnhe; | 613 | struct fib_nh_exception *fnhe; |
614 | struct rtable *rt; | ||
615 | unsigned int i; | ||
602 | int depth; | 616 | int depth; |
603 | u32 hval = fnhe_hashfun(daddr); | 617 | u32 hval = fnhe_hashfun(daddr); |
604 | 618 | ||
@@ -627,8 +641,12 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, | |||
627 | fnhe->fnhe_gw = gw; | 641 | fnhe->fnhe_gw = gw; |
628 | if (pmtu) { | 642 | if (pmtu) { |
629 | fnhe->fnhe_pmtu = pmtu; | 643 | fnhe->fnhe_pmtu = pmtu; |
630 | fnhe->fnhe_expires = expires; | 644 | fnhe->fnhe_expires = max(1UL, expires); |
631 | } | 645 | } |
646 | /* Update all cached dsts too */ | ||
647 | rt = rcu_dereference(fnhe->fnhe_rth); | ||
648 | if (rt) | ||
649 | fill_route_from_fnhe(rt, fnhe); | ||
632 | } else { | 650 | } else { |
633 | if (depth > FNHE_RECLAIM_DEPTH) | 651 | if (depth > FNHE_RECLAIM_DEPTH) |
634 | fnhe = fnhe_oldest(hash); | 652 | fnhe = fnhe_oldest(hash); |
@@ -644,6 +662,18 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, | |||
644 | fnhe->fnhe_gw = gw; | 662 | fnhe->fnhe_gw = gw; |
645 | fnhe->fnhe_pmtu = pmtu; | 663 | fnhe->fnhe_pmtu = pmtu; |
646 | fnhe->fnhe_expires = expires; | 664 | fnhe->fnhe_expires = expires; |
665 | |||
666 | /* Exception created; mark the cached routes for the nexthop | ||
667 | * stale, so anyone caching it rechecks if this exception | ||
668 | * applies to them. | ||
669 | */ | ||
670 | for_each_possible_cpu(i) { | ||
671 | struct rtable __rcu **prt; | ||
672 | prt = per_cpu_ptr(nh->nh_pcpu_rth_output, i); | ||
673 | rt = rcu_dereference(*prt); | ||
674 | if (rt) | ||
675 | rt->dst.obsolete = DST_OBSOLETE_KILL; | ||
676 | } | ||
647 | } | 677 | } |
648 | 678 | ||
649 | fnhe->fnhe_stamp = jiffies; | 679 | fnhe->fnhe_stamp = jiffies; |
@@ -917,13 +947,6 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) | |||
917 | if (mtu < ip_rt_min_pmtu) | 947 | if (mtu < ip_rt_min_pmtu) |
918 | mtu = ip_rt_min_pmtu; | 948 | mtu = ip_rt_min_pmtu; |
919 | 949 | ||
920 | if (!rt->rt_pmtu) { | ||
921 | dst->obsolete = DST_OBSOLETE_KILL; | ||
922 | } else { | ||
923 | rt->rt_pmtu = mtu; | ||
924 | dst->expires = max(1UL, jiffies + ip_rt_mtu_expires); | ||
925 | } | ||
926 | |||
927 | rcu_read_lock(); | 950 | rcu_read_lock(); |
928 | if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) { | 951 | if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) { |
929 | struct fib_nh *nh = &FIB_RES_NH(res); | 952 | struct fib_nh *nh = &FIB_RES_NH(res); |
@@ -1063,11 +1086,11 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) | |||
1063 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down | 1086 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down |
1064 | * into this function always. | 1087 | * into this function always. |
1065 | * | 1088 | * |
1066 | * When a PMTU/redirect information update invalidates a | 1089 | * When a PMTU/redirect information update invalidates a route, |
1067 | * route, this is indicated by setting obsolete to | 1090 | * this is indicated by setting obsolete to DST_OBSOLETE_KILL or |
1068 | * DST_OBSOLETE_KILL. | 1091 | * DST_OBSOLETE_DEAD by dst_free(). |
1069 | */ | 1092 | */ |
1070 | if (dst->obsolete == DST_OBSOLETE_KILL || rt_is_expired(rt)) | 1093 | if (dst->obsolete != DST_OBSOLETE_FORCE_CHK || rt_is_expired(rt)) |
1071 | return NULL; | 1094 | return NULL; |
1072 | return dst; | 1095 | return dst; |
1073 | } | 1096 | } |
@@ -1215,20 +1238,8 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe, | |||
1215 | fnhe->fnhe_pmtu = 0; | 1238 | fnhe->fnhe_pmtu = 0; |
1216 | fnhe->fnhe_expires = 0; | 1239 | fnhe->fnhe_expires = 0; |
1217 | } | 1240 | } |
1218 | if (fnhe->fnhe_pmtu) { | 1241 | fill_route_from_fnhe(rt, fnhe); |
1219 | unsigned long expires = fnhe->fnhe_expires; | 1242 | if (!rt->rt_gateway) |
1220 | unsigned long diff = expires - jiffies; | ||
1221 | |||
1222 | if (time_before(jiffies, expires)) { | ||
1223 | rt->rt_pmtu = fnhe->fnhe_pmtu; | ||
1224 | dst_set_expires(&rt->dst, diff); | ||
1225 | } | ||
1226 | } | ||
1227 | if (fnhe->fnhe_gw) { | ||
1228 | rt->rt_flags |= RTCF_REDIRECTED; | ||
1229 | rt->rt_gateway = fnhe->fnhe_gw; | ||
1230 | rt->rt_uses_gateway = 1; | ||
1231 | } else if (!rt->rt_gateway) | ||
1232 | rt->rt_gateway = daddr; | 1243 | rt->rt_gateway = daddr; |
1233 | 1244 | ||
1234 | rcu_assign_pointer(fnhe->fnhe_rth, rt); | 1245 | rcu_assign_pointer(fnhe->fnhe_rth, rt); |