Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ceb33206 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parent f5b0a874
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ struct dst_entry {
#define DST_OBSOLETE_NONE	0
#define DST_OBSOLETE_DEAD	2
#define DST_OBSOLETE_FORCE_CHK	-1
#define DST_OBSOLETE_KILL	-2
	unsigned short		header_len;	/* more space at head required */
	unsigned short		trailer_len;	/* space to reserve at tail */
#ifdef CONFIG_IP_ROUTE_CLASSID
+29 −12
Original line number Diff line number Diff line
@@ -673,7 +673,8 @@ out_unlock:
	return;
}

static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4)
static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4,
			     bool kill_route)
{
	__be32 new_gw = icmp_hdr(skb)->un.gateway;
	__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
				update_or_create_fnhe(nh, fl4->daddr, new_gw,
						      0, 0);
			}
			rt->rt_gateway = new_gw;
			rt->rt_flags |= RTCF_REDIRECTED;
			if (kill_route)
				rt->dst.obsolete = DST_OBSOLETE_KILL;
			call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
		}
		neigh_release(n);
@@ -760,7 +761,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
	rt = (struct rtable *) dst;

	ip_rt_build_flow_key(&fl4, sk, skb);
	__ip_do_redirect(rt, skb, &fl4);
	__ip_do_redirect(rt, skb, &fl4, true);
}

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

static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
{
	struct fib_result res;

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

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,
	struct flowi4 fl4;

	ip_rt_build_flow_key(&fl4, sk, skb);
	__ip_rt_update_pmtu(rt, &fl4, mtu);
	mtu = __ip_rt_update_pmtu(rt, &fl4, mtu);

	if (!rt->rt_pmtu) {
		dst->obsolete = DST_OBSOLETE_KILL;
	} else {
		rt->rt_pmtu = mtu;
		dst_set_expires(&rt->dst, ip_rt_mtu_expires);
	}
}

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,
			 RT_TOS(iph->tos), protocol, mark, flow_flags);
	rt = __ip_route_output_key(net, &fl4);
	if (!IS_ERR(rt)) {
		__ip_do_redirect(rt, skb, &fl4);
		__ip_do_redirect(rt, skb, &fl4, false);
		ip_rt_put(rt);
	}
}
@@ -1004,7 +1011,7 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
	rt = __ip_route_output_key(sock_net(sk), &fl4);
	if (!IS_ERR(rt)) {
		__ip_do_redirect(rt, skb, &fl4);
		__ip_do_redirect(rt, skb, &fl4, false);
		ip_rt_put(rt);
	}
}
@@ -1014,7 +1021,15 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
{
	struct rtable *rt = (struct rtable *) dst;

	if (rt_is_expired(rt))
	/* All IPV4 dsts are created with ->obsolete set to the value
	 * DST_OBSOLETE_FORCE_CHK which forces validation calls down
	 * into this function always.
	 *
	 * When a PMTU/redirect information update invalidates a
	 * route, this is indicated by setting obsolete to
	 * DST_OBSOLETE_KILL.
	 */
	if (dst->obsolete == DST_OBSOLETE_KILL || rt_is_expired(rt))
		return NULL;
	return dst;
}
@@ -1186,8 +1201,10 @@ restart:
				dst_set_expires(&rt->dst, diff);
			}
		}
		if (gw)
		if (gw) {
			rt->rt_flags |= RTCF_REDIRECTED;
			rt->rt_gateway = gw;
		}
		fnhe->fnhe_stamp = jiffies;
		break;
	}