Skip to content

Commit ceb3320

Browse files
committed
ipv4: Kill routes during PMTU/redirect updates.
Mark them obsolete so there will be a re-lookup to fetch the FIB nexthop exception info. Signed-off-by: David S. Miller <[email protected]>
1 parent f5b0a87 commit ceb3320

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

include/net/dst.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct dst_entry {
7878
#define DST_OBSOLETE_NONE 0
7979
#define DST_OBSOLETE_DEAD 2
8080
#define DST_OBSOLETE_FORCE_CHK -1
81+
#define DST_OBSOLETE_KILL -2
8182
unsigned short header_len; /* more space at head required */
8283
unsigned short trailer_len; /* space to reserve at tail */
8384
#ifdef CONFIG_IP_ROUTE_CLASSID

net/ipv4/route.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,8 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
673673
return;
674674
}
675675

676-
static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4)
676+
static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4,
677+
bool kill_route)
677678
{
678679
__be32 new_gw = icmp_hdr(skb)->un.gateway;
679680
__be32 old_gw = ip_hdr(skb)->saddr;
@@ -728,8 +729,8 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
728729
update_or_create_fnhe(nh, fl4->daddr, new_gw,
729730
0, 0);
730731
}
731-
rt->rt_gateway = new_gw;
732-
rt->rt_flags |= RTCF_REDIRECTED;
732+
if (kill_route)
733+
rt->dst.obsolete = DST_OBSOLETE_KILL;
733734
call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
734735
}
735736
neigh_release(n);
@@ -760,7 +761,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
760761
rt = (struct rtable *) dst;
761762

762763
ip_rt_build_flow_key(&fl4, sk, skb);
763-
__ip_do_redirect(rt, skb, &fl4);
764+
__ip_do_redirect(rt, skb, &fl4, true);
764765
}
765766

766767
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
@@ -919,7 +920,7 @@ out: kfree_skb(skb);
919920
return 0;
920921
}
921922

922-
static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
923+
static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
923924
{
924925
struct fib_result res;
925926

@@ -932,8 +933,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
932933
update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
933934
jiffies + ip_rt_mtu_expires);
934935
}
935-
rt->rt_pmtu = mtu;
936-
dst_set_expires(&rt->dst, ip_rt_mtu_expires);
936+
return mtu;
937937
}
938938

939939
static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
@@ -943,7 +943,14 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
943943
struct flowi4 fl4;
944944

945945
ip_rt_build_flow_key(&fl4, sk, skb);
946-
__ip_rt_update_pmtu(rt, &fl4, mtu);
946+
mtu = __ip_rt_update_pmtu(rt, &fl4, mtu);
947+
948+
if (!rt->rt_pmtu) {
949+
dst->obsolete = DST_OBSOLETE_KILL;
950+
} else {
951+
rt->rt_pmtu = mtu;
952+
dst_set_expires(&rt->dst, ip_rt_mtu_expires);
953+
}
947954
}
948955

949956
void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
@@ -989,7 +996,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net *net,
989996
RT_TOS(iph->tos), protocol, mark, flow_flags);
990997
rt = __ip_route_output_key(net, &fl4);
991998
if (!IS_ERR(rt)) {
992-
__ip_do_redirect(rt, skb, &fl4);
999+
__ip_do_redirect(rt, skb, &fl4, false);
9931000
ip_rt_put(rt);
9941001
}
9951002
}
@@ -1004,7 +1011,7 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
10041011
__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
10051012
rt = __ip_route_output_key(sock_net(sk), &fl4);
10061013
if (!IS_ERR(rt)) {
1007-
__ip_do_redirect(rt, skb, &fl4);
1014+
__ip_do_redirect(rt, skb, &fl4, false);
10081015
ip_rt_put(rt);
10091016
}
10101017
}
@@ -1014,7 +1021,15 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
10141021
{
10151022
struct rtable *rt = (struct rtable *) dst;
10161023

1017-
if (rt_is_expired(rt))
1024+
/* All IPV4 dsts are created with ->obsolete set to the value
1025+
* DST_OBSOLETE_FORCE_CHK which forces validation calls down
1026+
* into this function always.
1027+
*
1028+
* When a PMTU/redirect information update invalidates a
1029+
* route, this is indicated by setting obsolete to
1030+
* DST_OBSOLETE_KILL.
1031+
*/
1032+
if (dst->obsolete == DST_OBSOLETE_KILL || rt_is_expired(rt))
10181033
return NULL;
10191034
return dst;
10201035
}
@@ -1186,8 +1201,10 @@ static void rt_bind_exception(struct rtable *rt, struct fib_nh *nh, __be32 daddr
11861201
dst_set_expires(&rt->dst, diff);
11871202
}
11881203
}
1189-
if (gw)
1204+
if (gw) {
1205+
rt->rt_flags |= RTCF_REDIRECTED;
11901206
rt->rt_gateway = gw;
1207+
}
11911208
fnhe->fnhe_stamp = jiffies;
11921209
break;
11931210
}

0 commit comments

Comments
 (0)