aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/fib6_rules.c
diff options
context:
space:
mode:
authorWei Wang <weiwan@google.com>2019-06-20 20:36:39 -0400
committerDavid S. Miller <davem@davemloft.net>2019-06-23 16:24:17 -0400
commitd64a1f574a2957b4bcb06452d36cc1c6bf16e9fc (patch)
treeb07474822bdef5a6e543daf192c8e23e3408e3fd /net/ipv6/fib6_rules.c
parent74109218b051c2431eec2569886627c7217e235a (diff)
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 <weiwan@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/fib6_rules.c')
-rw-r--r--net/ipv6/fib6_rules.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index bcfae13409b5..d22b6c140f23 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -113,14 +113,15 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
113 rt = lookup(net, net->ipv6.fib6_local_tbl, fl6, skb, flags); 113 rt = lookup(net, net->ipv6.fib6_local_tbl, fl6, skb, flags);
114 if (rt != net->ipv6.ip6_null_entry && rt->dst.error != -EAGAIN) 114 if (rt != net->ipv6.ip6_null_entry && rt->dst.error != -EAGAIN)
115 return &rt->dst; 115 return &rt->dst;
116 ip6_rt_put(rt); 116 ip6_rt_put_flags(rt, flags);
117 rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, skb, flags); 117 rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, skb, flags);
118 if (rt->dst.error != -EAGAIN) 118 if (rt->dst.error != -EAGAIN)
119 return &rt->dst; 119 return &rt->dst;
120 ip6_rt_put(rt); 120 ip6_rt_put_flags(rt, flags);
121 } 121 }
122 122
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);
124 return &net->ipv6.ip6_null_entry->dst; 125 return &net->ipv6.ip6_null_entry->dst;
125} 126}
126 127
@@ -237,13 +238,14 @@ static int __fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
237 goto out; 238 goto out;
238 } 239 }
239again: 240again:
240 ip6_rt_put(rt); 241 ip6_rt_put_flags(rt, flags);
241 err = -EAGAIN; 242 err = -EAGAIN;
242 rt = NULL; 243 rt = NULL;
243 goto out; 244 goto out;
244 245
245discard_pkt: 246discard_pkt:
246 dst_hold(&rt->dst); 247 if (!(flags & RT6_LOOKUP_F_DST_NOREF))
248 dst_hold(&rt->dst);
247out: 249out:
248 res->rt6 = rt; 250 res->rt6 = rt;
249 return err; 251 return err;