Skip to content

Commit 5943634

Browse files
committed
ipv4: Maintain redirect and PMTU info in struct rtable again.
Maintaining this in the inetpeer entries was not the right way to do this at all. Signed-off-by: David S. Miller <[email protected]>
1 parent 87a5069 commit 5943634

File tree

5 files changed

+41
-154
lines changed

5 files changed

+41
-154
lines changed

include/net/inetpeer.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ struct inet_peer {
3636
u32 metrics[RTAX_MAX];
3737
u32 rate_tokens; /* rate limiting for ICMP */
3838
unsigned long rate_last;
39-
unsigned long pmtu_expires;
40-
u32 pmtu_orig;
41-
u32 pmtu_learned;
42-
struct inetpeer_addr_base redirect_learned;
4339
union {
4440
struct list_head gc_list;
4541
struct rcu_head gc_rcu;

include/net/route.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ struct rtable {
6565
__be32 rt_gateway;
6666

6767
/* Miscellaneous cached information */
68-
u32 rt_peer_genid;
68+
u32 rt_pmtu;
6969
unsigned long _peer; /* long-living peer info */
7070
struct fib_info *fi; /* for client ref to shared metrics */
7171
};

net/ipv4/inetpeer.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -511,9 +511,6 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
511511
p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
512512
p->rate_tokens = 0;
513513
p->rate_last = 0;
514-
p->pmtu_expires = 0;
515-
p->pmtu_orig = 0;
516-
memset(&p->redirect_learned, 0, sizeof(p->redirect_learned));
517514
INIT_LIST_HEAD(&p->gc_list);
518515

519516
/* Link the node. */

net/ipv4/route.c

Lines changed: 39 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ static inline int rt_fast_clean(struct rtable *rth)
669669
static inline int rt_valuable(struct rtable *rth)
670670
{
671671
return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) ||
672-
(rt_has_peer(rth) && rt_peer_ptr(rth)->pmtu_expires);
672+
rth->dst.expires;
673673
}
674674

675675
static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2)
@@ -1242,13 +1242,6 @@ static struct rtable *rt_intern_hash(unsigned int hash, struct rtable *rt,
12421242
return rt;
12431243
}
12441244

1245-
static atomic_t __rt_peer_genid = ATOMIC_INIT(0);
1246-
1247-
static u32 rt_peer_genid(void)
1248-
{
1249-
return atomic_read(&__rt_peer_genid);
1250-
}
1251-
12521245
void rt_bind_peer(struct rtable *rt, __be32 daddr, int create)
12531246
{
12541247
struct inet_peer_base *base;
@@ -1262,8 +1255,6 @@ void rt_bind_peer(struct rtable *rt, __be32 daddr, int create)
12621255
if (peer) {
12631256
if (!rt_set_peer(rt, peer))
12641257
inet_putpeer(peer);
1265-
else
1266-
rt->rt_peer_genid = rt_peer_genid();
12671258
}
12681259
}
12691260

@@ -1323,30 +1314,6 @@ static void rt_del(unsigned int hash, struct rtable *rt)
13231314
spin_unlock_bh(rt_hash_lock_addr(hash));
13241315
}
13251316

1326-
static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
1327-
{
1328-
struct rtable *rt = (struct rtable *) dst;
1329-
__be32 orig_gw = rt->rt_gateway;
1330-
struct neighbour *n;
1331-
1332-
dst_confirm(&rt->dst);
1333-
1334-
rt->rt_gateway = peer->redirect_learned.a4;
1335-
1336-
n = ipv4_neigh_lookup(&rt->dst, NULL, &rt->rt_gateway);
1337-
if (!n) {
1338-
rt->rt_gateway = orig_gw;
1339-
return;
1340-
}
1341-
if (!(n->nud_state & NUD_VALID)) {
1342-
neigh_event_send(n, NULL);
1343-
} else {
1344-
rt->rt_flags |= RTCF_REDIRECTED;
1345-
call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
1346-
}
1347-
neigh_release(n);
1348-
}
1349-
13501317
/* called in rcu_read_lock() section */
13511318
void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
13521319
__be32 saddr, struct net_device *dev)
@@ -1355,7 +1322,6 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
13551322
struct in_device *in_dev = __in_dev_get_rcu(dev);
13561323
__be32 skeys[2] = { saddr, 0 };
13571324
int ikeys[2] = { dev->ifindex, 0 };
1358-
struct inet_peer *peer;
13591325
struct net *net;
13601326

13611327
if (!in_dev)
@@ -1388,6 +1354,8 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
13881354
rthp = &rt_hash_table[hash].chain;
13891355

13901356
while ((rt = rcu_dereference(*rthp)) != NULL) {
1357+
struct neighbour *n;
1358+
13911359
rthp = &rt->dst.rt_next;
13921360

13931361
if (rt->rt_key_dst != daddr ||
@@ -1401,13 +1369,16 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
14011369
rt->rt_gateway != old_gw)
14021370
continue;
14031371

1404-
peer = rt_get_peer_create(rt, rt->rt_dst);
1405-
if (peer) {
1406-
if (peer->redirect_learned.a4 != new_gw) {
1407-
peer->redirect_learned.a4 = new_gw;
1408-
atomic_inc(&__rt_peer_genid);
1372+
n = ipv4_neigh_lookup(&rt->dst, NULL, &new_gw);
1373+
if (n) {
1374+
if (!(n->nud_state & NUD_VALID)) {
1375+
neigh_event_send(n, NULL);
1376+
} else {
1377+
rt->rt_gateway = new_gw;
1378+
rt->rt_flags |= RTCF_REDIRECTED;
1379+
call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
14091380
}
1410-
check_peer_redir(&rt->dst, peer);
1381+
neigh_release(n);
14111382
}
14121383
}
14131384
}
@@ -1425,23 +1396,6 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
14251396
;
14261397
}
14271398

1428-
static bool peer_pmtu_expired(struct inet_peer *peer)
1429-
{
1430-
unsigned long orig = ACCESS_ONCE(peer->pmtu_expires);
1431-
1432-
return orig &&
1433-
time_after_eq(jiffies, orig) &&
1434-
cmpxchg(&peer->pmtu_expires, orig, 0) == orig;
1435-
}
1436-
1437-
static bool peer_pmtu_cleaned(struct inet_peer *peer)
1438-
{
1439-
unsigned long orig = ACCESS_ONCE(peer->pmtu_expires);
1440-
1441-
return orig &&
1442-
cmpxchg(&peer->pmtu_expires, orig, 0) == orig;
1443-
}
1444-
14451399
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
14461400
{
14471401
struct rtable *rt = (struct rtable *)dst;
@@ -1451,16 +1405,13 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
14511405
if (dst->obsolete > 0) {
14521406
ip_rt_put(rt);
14531407
ret = NULL;
1454-
} else if (rt->rt_flags & RTCF_REDIRECTED) {
1408+
} else if ((rt->rt_flags & RTCF_REDIRECTED) ||
1409+
rt->dst.expires) {
14551410
unsigned int hash = rt_hash(rt->rt_key_dst, rt->rt_key_src,
14561411
rt->rt_oif,
14571412
rt_genid(dev_net(dst->dev)));
14581413
rt_del(hash, rt);
14591414
ret = NULL;
1460-
} else if (rt_has_peer(rt)) {
1461-
struct inet_peer *peer = rt_peer_ptr(rt);
1462-
if (peer_pmtu_expired(peer))
1463-
dst_metric_set(dst, RTAX_MTU, peer->pmtu_orig);
14641415
}
14651416
}
14661417
return ret;
@@ -1604,50 +1555,17 @@ out: kfree_skb(skb);
16041555
return 0;
16051556
}
16061557

1607-
static void check_peer_pmtu(struct dst_entry *dst, struct inet_peer *peer)
1608-
{
1609-
unsigned long expires = ACCESS_ONCE(peer->pmtu_expires);
1610-
1611-
if (!expires)
1612-
return;
1613-
if (time_before(jiffies, expires)) {
1614-
u32 orig_dst_mtu = dst_mtu(dst);
1615-
if (peer->pmtu_learned < orig_dst_mtu) {
1616-
if (!peer->pmtu_orig)
1617-
peer->pmtu_orig = dst_metric_raw(dst, RTAX_MTU);
1618-
dst_metric_set(dst, RTAX_MTU, peer->pmtu_learned);
1619-
}
1620-
} else if (cmpxchg(&peer->pmtu_expires, expires, 0) == expires)
1621-
dst_metric_set(dst, RTAX_MTU, peer->pmtu_orig);
1622-
}
1623-
16241558
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
16251559
{
16261560
struct rtable *rt = (struct rtable *) dst;
1627-
struct inet_peer *peer;
16281561

16291562
dst_confirm(dst);
16301563

1631-
peer = rt_get_peer_create(rt, rt->rt_dst);
1632-
if (peer) {
1633-
unsigned long pmtu_expires = ACCESS_ONCE(peer->pmtu_expires);
1634-
1635-
if (mtu < ip_rt_min_pmtu)
1636-
mtu = ip_rt_min_pmtu;
1637-
if (!pmtu_expires || mtu < peer->pmtu_learned) {
1638-
1639-
pmtu_expires = jiffies + ip_rt_mtu_expires;
1640-
if (!pmtu_expires)
1641-
pmtu_expires = 1UL;
1642-
1643-
peer->pmtu_learned = mtu;
1644-
peer->pmtu_expires = pmtu_expires;
1564+
if (mtu < ip_rt_min_pmtu)
1565+
mtu = ip_rt_min_pmtu;
16451566

1646-
atomic_inc(&__rt_peer_genid);
1647-
rt->rt_peer_genid = rt_peer_genid();
1648-
}
1649-
check_peer_pmtu(dst, peer);
1650-
}
1567+
rt->rt_pmtu = mtu;
1568+
dst_set_expires(&rt->dst, ip_rt_mtu_expires);
16511569
}
16521570

16531571
void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
@@ -1679,30 +1597,12 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
16791597
}
16801598
EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu);
16811599

1682-
static void ipv4_validate_peer(struct rtable *rt)
1683-
{
1684-
if (rt->rt_peer_genid != rt_peer_genid()) {
1685-
struct inet_peer *peer = rt_get_peer(rt, rt->rt_dst);
1686-
1687-
if (peer) {
1688-
check_peer_pmtu(&rt->dst, peer);
1689-
1690-
if (peer->redirect_learned.a4 &&
1691-
peer->redirect_learned.a4 != rt->rt_gateway)
1692-
check_peer_redir(&rt->dst, peer);
1693-
}
1694-
1695-
rt->rt_peer_genid = rt_peer_genid();
1696-
}
1697-
}
1698-
16991600
static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
17001601
{
17011602
struct rtable *rt = (struct rtable *) dst;
17021603

17031604
if (rt_is_expired(rt))
17041605
return NULL;
1705-
ipv4_validate_peer(rt);
17061606
return dst;
17071607
}
17081608

@@ -1728,11 +1628,8 @@ static void ipv4_link_failure(struct sk_buff *skb)
17281628
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
17291629

17301630
rt = skb_rtable(skb);
1731-
if (rt && rt_has_peer(rt)) {
1732-
struct inet_peer *peer = rt_peer_ptr(rt);
1733-
if (peer_pmtu_cleaned(peer))
1734-
dst_metric_set(&rt->dst, RTAX_MTU, peer->pmtu_orig);
1735-
}
1631+
if (rt)
1632+
dst_set_expires(&rt->dst, 0);
17361633
}
17371634

17381635
static int ip_rt_bug(struct sk_buff *skb)
@@ -1812,7 +1709,13 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
18121709
static unsigned int ipv4_mtu(const struct dst_entry *dst)
18131710
{
18141711
const struct rtable *rt = (const struct rtable *) dst;
1815-
unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
1712+
unsigned int mtu = rt->rt_pmtu;
1713+
1714+
if (mtu && time_after_eq(jiffies, rt->dst.expires))
1715+
mtu = 0;
1716+
1717+
if (!mtu)
1718+
mtu = dst_metric_raw(dst, RTAX_MTU);
18161719

18171720
if (mtu && rt_is_output_route(rt))
18181721
return mtu;
@@ -1843,19 +1746,10 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4,
18431746
peer = inet_getpeer_v4(base, rt->rt_dst, 0);
18441747
if (peer) {
18451748
__rt_set_peer(rt, peer);
1846-
rt->rt_peer_genid = rt_peer_genid();
18471749
if (inet_metrics_new(peer))
18481750
memcpy(peer->metrics, fi->fib_metrics,
18491751
sizeof(u32) * RTAX_MAX);
18501752
dst_init_metrics(&rt->dst, peer->metrics, false);
1851-
1852-
check_peer_pmtu(&rt->dst, peer);
1853-
1854-
if (peer->redirect_learned.a4 &&
1855-
peer->redirect_learned.a4 != rt->rt_gateway) {
1856-
rt->rt_gateway = peer->redirect_learned.a4;
1857-
rt->rt_flags |= RTCF_REDIRECTED;
1858-
}
18591753
} else {
18601754
if (fi->fib_metrics != (u32 *) dst_default_metrics) {
18611755
rt->fi = fi;
@@ -1955,8 +1849,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
19551849
rth->rt_iif = dev->ifindex;
19561850
rth->rt_oif = 0;
19571851
rth->rt_mark = skb->mark;
1852+
rth->rt_pmtu = 0;
19581853
rth->rt_gateway = daddr;
1959-
rth->rt_peer_genid = 0;
19601854
rt_init_peer(rth, dev_net(dev)->ipv4.peers);
19611855
rth->fi = NULL;
19621856
if (our) {
@@ -2081,8 +1975,8 @@ static int __mkroute_input(struct sk_buff *skb,
20811975
rth->rt_iif = in_dev->dev->ifindex;
20821976
rth->rt_oif = 0;
20831977
rth->rt_mark = skb->mark;
1978+
rth->rt_pmtu = 0;
20841979
rth->rt_gateway = daddr;
2085-
rth->rt_peer_genid = 0;
20861980
rt_init_peer(rth, &res->table->tb_peers);
20871981
rth->fi = NULL;
20881982

@@ -2260,8 +2154,8 @@ out: return err;
22602154
rth->rt_iif = dev->ifindex;
22612155
rth->rt_oif = 0;
22622156
rth->rt_mark = skb->mark;
2157+
rth->rt_pmtu = 0;
22632158
rth->rt_gateway = daddr;
2264-
rth->rt_peer_genid = 0;
22652159
rt_init_peer(rth, net->ipv4.peers);
22662160
rth->fi = NULL;
22672161
if (res.type == RTN_UNREACHABLE) {
@@ -2337,7 +2231,6 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
23372231
rth->rt_mark == skb->mark &&
23382232
net_eq(dev_net(rth->dst.dev), net) &&
23392233
!rt_is_expired(rth)) {
2340-
ipv4_validate_peer(rth);
23412234
if (noref) {
23422235
dst_use_noref(&rth->dst, jiffies);
23432236
skb_dst_set_noref(skb, &rth->dst);
@@ -2459,8 +2352,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
24592352
rth->rt_iif = orig_oif ? : dev_out->ifindex;
24602353
rth->rt_oif = orig_oif;
24612354
rth->rt_mark = fl4->flowi4_mark;
2355+
rth->rt_pmtu = 0;
24622356
rth->rt_gateway = fl4->daddr;
2463-
rth->rt_peer_genid = 0;
24642357
rt_init_peer(rth, (res->table ?
24652358
&res->table->tb_peers :
24662359
dev_net(dev_out)->ipv4.peers));
@@ -2717,7 +2610,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4)
27172610
(IPTOS_RT_MASK | RTO_ONLINK)) &&
27182611
net_eq(dev_net(rth->dst.dev), net) &&
27192612
!rt_is_expired(rth)) {
2720-
ipv4_validate_peer(rth);
27212613
dst_use(&rth->dst, jiffies);
27222614
RT_CACHE_STAT_INC(out_hit);
27232615
rcu_read_unlock_bh();
@@ -2794,6 +2686,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
27942686
rt->rt_iif = ort->rt_iif;
27952687
rt->rt_oif = ort->rt_oif;
27962688
rt->rt_mark = ort->rt_mark;
2689+
rt->rt_pmtu = ort->rt_pmtu;
27972690

27982691
rt->rt_genid = rt_genid(net);
27992692
rt->rt_flags = ort->rt_flags;
@@ -2896,13 +2789,13 @@ static int rt_fill_info(struct net *net,
28962789
const struct inet_peer *peer = rt_peer_ptr(rt);
28972790
inet_peer_refcheck(peer);
28982791
id = atomic_read(&peer->ip_id_count) & 0xffff;
2899-
expires = ACCESS_ONCE(peer->pmtu_expires);
2900-
if (expires) {
2901-
if (time_before(jiffies, expires))
2902-
expires -= jiffies;
2903-
else
2904-
expires = 0;
2905-
}
2792+
}
2793+
expires = rt->dst.expires;
2794+
if (expires) {
2795+
if (time_before(jiffies, expires))
2796+
expires -= jiffies;
2797+
else
2798+
expires = 0;
29062799
}
29072800

29082801
if (rt_is_input_route(rt)) {

0 commit comments

Comments
 (0)