Skip to content

Commit d64a1f5

Browse files
tracywwnjdavem330
authored andcommitted
ipv6: honor RT6_LOOKUP_F_DST_NOREF in rule lookup logic
This patch specifically converts the rule lookup logic to honor this flag and not release refcnt when traversing each rule and calling lookup() on each routing table. Similar to previous patch, we also need some special handling of dst entries in uncached list because there is always 1 refcnt taken for them even if RT6_LOOKUP_F_DST_NOREF flag is set. Signed-off-by: Wei Wang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7410921 commit d64a1f5

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

include/net/ip6_route.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ static inline struct dst_entry *ip6_route_output(struct net *net,
9494
return ip6_route_output_flags(net, sk, fl6, 0);
9595
}
9696

97+
/* Only conditionally release dst if flags indicates
98+
* !RT6_LOOKUP_F_DST_NOREF or dst is in uncached_list.
99+
*/
100+
static inline void ip6_rt_put_flags(struct rt6_info *rt, int flags)
101+
{
102+
if (!(flags & RT6_LOOKUP_F_DST_NOREF) ||
103+
!list_empty(&rt->rt6i_uncached))
104+
ip6_rt_put(rt);
105+
}
106+
97107
struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
98108
const struct sk_buff *skb, int flags);
99109
struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,

net/ipv6/fib6_rules.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,15 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
113113
rt = lookup(net, net->ipv6.fib6_local_tbl, fl6, skb, flags);
114114
if (rt != net->ipv6.ip6_null_entry && rt->dst.error != -EAGAIN)
115115
return &rt->dst;
116-
ip6_rt_put(rt);
116+
ip6_rt_put_flags(rt, flags);
117117
rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, skb, flags);
118118
if (rt->dst.error != -EAGAIN)
119119
return &rt->dst;
120-
ip6_rt_put(rt);
120+
ip6_rt_put_flags(rt, flags);
121121
}
122122

123-
dst_hold(&net->ipv6.ip6_null_entry->dst);
123+
if (!(flags & RT6_LOOKUP_F_DST_NOREF))
124+
dst_hold(&net->ipv6.ip6_null_entry->dst);
124125
return &net->ipv6.ip6_null_entry->dst;
125126
}
126127

@@ -237,13 +238,14 @@ static int __fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
237238
goto out;
238239
}
239240
again:
240-
ip6_rt_put(rt);
241+
ip6_rt_put_flags(rt, flags);
241242
err = -EAGAIN;
242243
rt = NULL;
243244
goto out;
244245

245246
discard_pkt:
246-
dst_hold(&rt->dst);
247+
if (!(flags & RT6_LOOKUP_F_DST_NOREF))
248+
dst_hold(&rt->dst);
247249
out:
248250
res->rt6 = rt;
249251
return err;

net/ipv6/ip6_fib.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,10 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
316316

317317
rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, skb, flags);
318318
if (rt->dst.error == -EAGAIN) {
319-
ip6_rt_put(rt);
319+
ip6_rt_put_flags(rt, flags);
320320
rt = net->ipv6.ip6_null_entry;
321-
dst_hold(&rt->dst);
321+
if (!(flags | RT6_LOOKUP_F_DST_NOREF))
322+
dst_hold(&rt->dst);
322323
}
323324

324325
return &rt->dst;

0 commit comments

Comments
 (0)