diff options
author | YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> | 2006-03-20 17:00:05 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 17:00:05 -0800 |
commit | 519fbd8715ce6413ec8e122bf02f09b0e49d3ca5 (patch) | |
tree | fc5d83e8beb12dc74b9f83897ec227b4837dca96 | |
parent | e40cf3533c712b941d4c8ebb3eca892d55c32c34 (diff) |
[IPV6]: ROUTE: Clean-up cow'ing in ip6_route_{intput,output}().
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/route.c | 113 |
1 files changed, 60 insertions, 53 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 061a7bba163..6a4019a4ca8 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -72,6 +72,7 @@ #define RT6_TRACE(x...) do { ; } while (0) #endif +#define CLONE_OFFLINK_ROUTE 0 static int ip6_rt_max_size = 4096; static int ip6_rt_gc_min_interval = HZ / 2; @@ -465,9 +466,10 @@ if (rt == &ip6_null_entry && strict) { \ void ip6_route_input(struct sk_buff *skb) { struct fib6_node *fn; - struct rt6_info *rt; + struct rt6_info *rt, *nrt; int strict; int attempts = 3; + int err; strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); @@ -492,51 +494,53 @@ restart: dst_hold(&rt->u.dst); read_unlock_bh(&rt6_lock); - if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { - struct rt6_info *nrt; - int err; - - nrt = rt6_alloc_cow(rt, &skb->nh.ipv6h->daddr, - &skb->nh.ipv6h->saddr); - - dst_release(&rt->u.dst); - rt = nrt ? : &ip6_null_entry; + if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) + nrt = rt6_alloc_cow(rt, &skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr); + else { +#if CLONE_OFFLINK_ROUTE + nrt = rt6_alloc_clone(rt, &skb->nh.ipv6h->daddr); +#else + goto out2; +#endif + } - dst_hold(&rt->u.dst); - if (nrt) { - err = ip6_ins_rt(nrt, NULL, NULL, - &NETLINK_CB(skb)); - if (!err) - goto out2; - } + dst_release(&rt->u.dst); + rt = nrt ? : &ip6_null_entry; - if (--attempts <= 0) + dst_hold(&rt->u.dst); + if (nrt) { + err = ip6_ins_rt(nrt, NULL, NULL, &NETLINK_CB(skb)); + if (!err) goto out2; - - /* Race condition! In the gap, when rt6_lock was - released someone could insert this route. Relookup. - */ - dst_release(&rt->u.dst); - goto relookup; } + if (--attempts <= 0) + goto out2; + + /* + * Race condition! In the gap, when rt6_lock was + * released someone could insert this route. Relookup. + */ + dst_release(&rt->u.dst); + goto relookup; + +out: + dst_hold(&rt->u.dst); + read_unlock_bh(&rt6_lock); out2: rt->u.dst.lastuse = jiffies; rt->u.dst.__use++; skb->dst = (struct dst_entry *) rt; return; -out: - dst_hold(&rt->u.dst); - read_unlock_bh(&rt6_lock); - goto out2; } struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) { struct fib6_node *fn; - struct rt6_info *rt; + struct rt6_info *rt, *nrt; int strict; int attempts = 3; + int err; strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); @@ -564,40 +568,43 @@ restart: dst_hold(&rt->u.dst); read_unlock_bh(&rt6_lock); - if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { - struct rt6_info *nrt; - int err; - + if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); + else { +#if CLONE_OFFLINK_ROUTE + nrt = rt6_alloc_clone(rt, &fl->fl6_dst); +#else + goto out2; +#endif + } - dst_release(&rt->u.dst); - rt = nrt ? : &ip6_null_entry; - - dst_hold(&rt->u.dst); - if (nrt) { - err = ip6_ins_rt(nrt, NULL, NULL, NULL); - if (!err) - goto out2; - } + dst_release(&rt->u.dst); + rt = nrt ? : &ip6_null_entry; - if (--attempts <= 0) + dst_hold(&rt->u.dst); + if (nrt) { + err = ip6_ins_rt(nrt, NULL, NULL, NULL); + if (!err) goto out2; - - /* Race condition! In the gap, when rt6_lock was - released someone could insert this route. Relookup. - */ - dst_release(&rt->u.dst); - goto relookup; } + if (--attempts <= 0) + goto out2; + + /* + * Race condition! In the gap, when rt6_lock was + * released someone could insert this route. Relookup. + */ + dst_release(&rt->u.dst); + goto relookup; + +out: + dst_hold(&rt->u.dst); + read_unlock_bh(&rt6_lock); out2: rt->u.dst.lastuse = jiffies; rt->u.dst.__use++; return &rt->u.dst; -out: - dst_hold(&rt->u.dst); - read_unlock_bh(&rt6_lock); - goto out2; } |