Commit 1d861aa4b3fb08822055345f480850205ffe6170

Authored by David S. Miller
1 parent 16d1839907

inet: Minimize use of cached route inetpeer.

Only use it in the absolutely required cases:

1) COW'ing metrics

2) ipv4 PMTU

3) ipv4 redirects

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 5 changed files with 35 additions and 22 deletions Side-by-side Diff

... ... @@ -254,9 +254,10 @@
254 254  
255 255 /* Limit if icmp type is enabled in ratemask. */
256 256 if ((1 << type) & net->ipv4.sysctl_icmp_ratemask) {
257   - struct inet_peer *peer = rt_get_peer_create(rt, fl4->daddr);
  257 + struct inet_peer *peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, 1);
258 258 rc = inet_peer_xrlim_allow(peer,
259 259 net->ipv4.sysctl_icmp_ratelimit);
  260 + inet_putpeer(peer);
260 261 }
261 262 out:
262 263 return rc;
... ... @@ -1289,21 +1289,16 @@
1289 1289  
1290 1290 void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more)
1291 1291 {
1292   - struct rtable *rt = (struct rtable *) dst;
  1292 + struct net *net = dev_net(dst->dev);
  1293 + struct inet_peer *peer;
1293 1294  
1294   - if (rt && !(rt->dst.flags & DST_NOPEER)) {
1295   - struct inet_peer *peer = rt_get_peer_create(rt, rt->rt_dst);
  1295 + peer = inet_getpeer_v4(net->ipv4.peers, iph->daddr, 1);
  1296 + if (peer) {
  1297 + iph->id = htons(inet_getid(peer, more));
  1298 + inet_putpeer(peer);
  1299 + return;
  1300 + }
1296 1301  
1297   - /* If peer is attached to destination, it is never detached,
1298   - so that we need not to grab a lock to dereference it.
1299   - */
1300   - if (peer) {
1301   - iph->id = htons(inet_getid(peer, more));
1302   - return;
1303   - }
1304   - } else if (!rt)
1305   - pr_debug("rt_bind_peer(0) @%p\n", __builtin_return_address(0));
1306   -
1307 1302 ip_select_fb_ident(iph);
1308 1303 }
1309 1304 EXPORT_SYMBOL(__ip_select_ident);
... ... @@ -1492,6 +1487,7 @@
1492 1487 struct rtable *rt = skb_rtable(skb);
1493 1488 struct in_device *in_dev;
1494 1489 struct inet_peer *peer;
  1490 + struct net *net;
1495 1491 int log_martians;
1496 1492  
1497 1493 rcu_read_lock();
... ... @@ -1503,7 +1499,8 @@
1503 1499 log_martians = IN_DEV_LOG_MARTIANS(in_dev);
1504 1500 rcu_read_unlock();
1505 1501  
1506   - peer = rt_get_peer_create(rt, rt->rt_dst);
  1502 + net = dev_net(rt->dst.dev);
  1503 + peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1);
1507 1504 if (!peer) {
1508 1505 icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
1509 1506 return;
... ... @@ -1520,7 +1517,7 @@
1520 1517 */
1521 1518 if (peer->rate_tokens >= ip_rt_redirect_number) {
1522 1519 peer->rate_last = jiffies;
1523   - return;
  1520 + goto out_put_peer;
1524 1521 }
1525 1522  
1526 1523 /* Check for load limit; set rate_last to the latest sent
... ... @@ -1541,6 +1538,8 @@
1541 1538 &rt->rt_dst, &rt->rt_gateway);
1542 1539 #endif
1543 1540 }
  1541 +out_put_peer:
  1542 + inet_putpeer(peer);
1544 1543 }
1545 1544  
1546 1545 static int ip_error(struct sk_buff *skb)
... ... @@ -1583,7 +1582,7 @@
1583 1582 break;
1584 1583 }
1585 1584  
1586   - peer = rt_get_peer_create(rt, rt->rt_dst);
  1585 + peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1);
1587 1586  
1588 1587 send = true;
1589 1588 if (peer) {
... ... @@ -1596,6 +1595,7 @@
1596 1595 peer->rate_tokens -= ip_rt_error_cost;
1597 1596 else
1598 1597 send = false;
  1598 + inet_putpeer(peer);
1599 1599 }
1600 1600 if (send)
1601 1601 icmp_send(skb, ICMP_DEST_UNREACH, code, 0);
... ... @@ -194,8 +194,10 @@
194 194 if (rt->rt6i_dst.plen < 128)
195 195 tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
196 196  
197   - peer = rt6_get_peer_create(rt);
  197 + peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
198 198 res = inet_peer_xrlim_allow(peer, tmo);
  199 + if (peer)
  200 + inet_putpeer(peer);
199 201 }
200 202 dst_release(dst);
201 203 return res;
net/ipv6/ip6_output.c
... ... @@ -466,13 +466,15 @@
466 466 else
467 467 target = &hdr->daddr;
468 468  
469   - peer = rt6_get_peer_create(rt);
  469 + peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
470 470  
471 471 /* Limit redirects both by destination (here)
472 472 and by source (inside ndisc_send_redirect)
473 473 */
474 474 if (inet_peer_xrlim_allow(peer, 1*HZ))
475 475 ndisc_send_redirect(skb, target);
  476 + if (peer)
  477 + inet_putpeer(peer);
476 478 } else {
477 479 int addrtype = ipv6_addr_type(&hdr->saddr);
478 480  
479 481  
480 482  
... ... @@ -592,10 +594,14 @@
592 594 int old, new;
593 595  
594 596 if (rt && !(rt->dst.flags & DST_NOPEER)) {
595   - struct inet_peer *peer = rt6_get_peer_create(rt);
  597 + struct inet_peer *peer;
  598 + struct net *net;
596 599  
  600 + net = dev_net(rt->dst.dev);
  601 + peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
597 602 if (peer) {
598 603 fhdr->identification = htonl(inet_getid(peer, 0));
  604 + inet_putpeer(peer);
599 605 return;
600 606 }
601 607 }
... ... @@ -1486,6 +1486,7 @@
1486 1486 int rd_len;
1487 1487 int err;
1488 1488 u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
  1489 + bool ret;
1489 1490  
1490 1491 if (ipv6_get_lladdr(dev, &saddr_buf, IFA_F_TENTATIVE)) {
1491 1492 ND_PRINTK(2, warn, "Redirect: no link-local address on %s\n",
... ... @@ -1519,8 +1520,11 @@
1519 1520 "Redirect: destination is not a neighbour\n");
1520 1521 goto release;
1521 1522 }
1522   - peer = rt6_get_peer_create(rt);
1523   - if (!inet_peer_xrlim_allow(peer, 1*HZ))
  1523 + peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
  1524 + ret = inet_peer_xrlim_allow(peer, 1*HZ);
  1525 + if (peer)
  1526 + inet_putpeer(peer);
  1527 + if (!ret)
1524 1528 goto release;
1525 1529  
1526 1530 if (dev->addr_len) {