Skip to content

Commit

Permalink
net: get rid of rtable->idev
Browse files Browse the repository at this point in the history
It seems idev field in struct rtable has no special purpose, but adding
extra atomic ops.

We hold refcounts on the device itself (using percpu data, so pretty
cheap in current kernel).

infiniband case is solved using dst.dev instead of idev->dev

Removal of this field means routing without route cache is now using
shared data, percpu data, and only potential contention is a pair of
atomic ops on struct neighbour per forwarded packet.

About 5% speedup on routing test.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Roland Dreier <rolandd@cisco.com>
Cc: Sean Hefty <sean.hefty@intel.com>
Cc: Hal Rosenstock <hal.rosenstock@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Nov 11, 2010
1 parent 46b13fc commit 72cdd1d
Show file tree
Hide file tree
Showing 4 changed files with 8 additions and 63 deletions.
8 changes: 4 additions & 4 deletions drivers/infiniband/core/addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,20 +200,20 @@ static int addr4_resolve(struct sockaddr_in *src_in,
src_in->sin_family = AF_INET;
src_in->sin_addr.s_addr = rt->rt_src;

if (rt->idev->dev->flags & IFF_LOOPBACK) {
if (rt->dst.dev->flags & IFF_LOOPBACK) {
ret = rdma_translate_ip((struct sockaddr *) dst_in, addr);
if (!ret)
memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
goto put;
}

/* If the device does ARP internally, return 'done' */
if (rt->idev->dev->flags & IFF_NOARP) {
rdma_copy_addr(addr, rt->idev->dev, NULL);
if (rt->dst.dev->flags & IFF_NOARP) {
rdma_copy_addr(addr, rt->dst.dev, NULL);
goto put;
}

neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
neigh_event_send(rt->dst.neighbour, NULL);
ret = -ENODATA;
Expand Down
2 changes: 0 additions & 2 deletions include/net/route.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ struct rtable {
/* Cache lookup keys */
struct flowi fl;

struct in_device *idev;

int rt_genid;
unsigned rt_flags;
__u16 rt_type;
Expand Down
37 changes: 4 additions & 33 deletions net/ipv4/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,15 @@ static unsigned long expires_ljiffies;

static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
static void ipv4_dst_destroy(struct dst_entry *dst);
static void ipv4_dst_ifdown(struct dst_entry *dst,
struct net_device *dev, int how);
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
static void ipv4_link_failure(struct sk_buff *skb);
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
static int rt_garbage_collect(struct dst_ops *ops);

static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
int how)
{
}

static struct dst_ops ipv4_dst_ops = {
.family = AF_INET,
Expand Down Expand Up @@ -1433,8 +1435,6 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
rt->dst.child = NULL;
if (rt->dst.dev)
dev_hold(rt->dst.dev);
if (rt->idev)
in_dev_hold(rt->idev);
rt->dst.obsolete = -1;
rt->dst.lastuse = jiffies;
rt->dst.path = &rt->dst;
Expand Down Expand Up @@ -1728,33 +1728,13 @@ static void ipv4_dst_destroy(struct dst_entry *dst)
{
struct rtable *rt = (struct rtable *) dst;
struct inet_peer *peer = rt->peer;
struct in_device *idev = rt->idev;

if (peer) {
rt->peer = NULL;
inet_putpeer(peer);
}

if (idev) {
rt->idev = NULL;
in_dev_put(idev);
}
}

static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
int how)
{
struct rtable *rt = (struct rtable *) dst;
struct in_device *idev = rt->idev;
if (dev != dev_net(dev)->loopback_dev && idev && idev->dev == dev) {
struct in_device *loopback_idev =
in_dev_get(dev_net(dev)->loopback_dev);
if (loopback_idev) {
rt->idev = loopback_idev;
in_dev_put(idev);
}
}
}

static void ipv4_link_failure(struct sk_buff *skb)
{
Expand Down Expand Up @@ -1910,7 +1890,6 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
rth->fl.iif = dev->ifindex;
rth->dst.dev = init_net.loopback_dev;
dev_hold(rth->dst.dev);
rth->idev = in_dev_get(rth->dst.dev);
rth->fl.oif = 0;
rth->rt_gateway = daddr;
rth->rt_spec_dst= spec_dst;
Expand Down Expand Up @@ -2050,7 +2029,6 @@ static int __mkroute_input(struct sk_buff *skb,
rth->fl.iif = in_dev->dev->ifindex;
rth->dst.dev = (out_dev)->dev;
dev_hold(rth->dst.dev);
rth->idev = in_dev_get(rth->dst.dev);
rth->fl.oif = 0;
rth->rt_spec_dst= spec_dst;

Expand Down Expand Up @@ -2231,7 +2209,6 @@ out: return err;
rth->fl.iif = dev->ifindex;
rth->dst.dev = net->loopback_dev;
dev_hold(rth->dst.dev);
rth->idev = in_dev_get(rth->dst.dev);
rth->rt_gateway = daddr;
rth->rt_spec_dst= spec_dst;
rth->dst.input= ip_local_deliver;
Expand Down Expand Up @@ -2417,9 +2394,6 @@ static int __mkroute_output(struct rtable **result,
if (!rth)
return -ENOBUFS;

in_dev_hold(in_dev);
rth->idev = in_dev;

atomic_set(&rth->dst.__refcnt, 1);
rth->dst.flags= DST_HOST;
if (IN_DEV_CONF_GET(in_dev, NOXFRM))
Expand Down Expand Up @@ -2759,9 +2733,6 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi

rt->fl = ort->fl;

rt->idev = ort->idev;
if (rt->idev)
in_dev_hold(rt->idev);
rt->rt_genid = rt_genid(net);
rt->rt_flags = ort->rt_flags;
rt->rt_type = ort->rt_type;
Expand Down
24 changes: 0 additions & 24 deletions net/ipv4/xfrm4_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
xdst->u.dst.dev = dev;
dev_hold(dev);

xdst->u.rt.idev = in_dev_get(dev);
if (!xdst->u.rt.idev)
return -ENODEV;

xdst->u.rt.peer = rt->peer;
if (rt->peer)
atomic_inc(&rt->peer->refcnt);
Expand Down Expand Up @@ -189,8 +185,6 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
{
struct xfrm_dst *xdst = (struct xfrm_dst *)dst;

if (likely(xdst->u.rt.idev))
in_dev_put(xdst->u.rt.idev);
if (likely(xdst->u.rt.peer))
inet_putpeer(xdst->u.rt.peer);
xfrm_dst_destroy(xdst);
Expand All @@ -199,27 +193,9 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
int unregister)
{
struct xfrm_dst *xdst;

if (!unregister)
return;

xdst = (struct xfrm_dst *)dst;
if (xdst->u.rt.idev->dev == dev) {
struct in_device *loopback_idev =
in_dev_get(dev_net(dev)->loopback_dev);
BUG_ON(!loopback_idev);

do {
in_dev_put(xdst->u.rt.idev);
xdst->u.rt.idev = loopback_idev;
in_dev_hold(loopback_idev);
xdst = (struct xfrm_dst *)xdst->u.dst.child;
} while (xdst->u.dst.xfrm);

__in_dev_put(loopback_idev);
}

xfrm_dst_ifdown(dst, dev);
}

Expand Down

0 comments on commit 72cdd1d

Please sign in to comment.