summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2019-06-23 13:24:17 -0700
committerDavid S. Miller <davem@davemloft.net>2019-06-23 13:24:17 -0700
commit7d30a7f6424e88c958c19a02f6f54ab8d25919cd (patch)
tree5649667efad829c536543d0feb5374ad42b93483 /include
parent8c25c0cb5bb4e63170bb7760179ec294a3827694 (diff)
parent7d9e5f422150ed00de744e02a80734d74cc9704d (diff)
Merge branch 'ipv6-avoid-taking-refcnt-on-dst-during-route-lookup'
Wei Wang says: ==================== ipv6: avoid taking refcnt on dst during route lookup Ipv6 route lookup code always grabs refcnt on the dst for the caller. But for certain cases, grabbing refcnt is not always necessary if the call path is rcu protected and the caller does not cache the dst. Another issue in the route lookup logic is: When there are multiple custom rules, we have to do the lookup into each table associated to each rule individually. And when we can't find the route in one table, we grab and release refcnt on net->ipv6.ip6_null_entry before going to the next table. This operation is completely redundant, and causes false issue because net->ipv6.ip6_null_entry is a shared object. This patch set introduces a new flag RT6_LOOKUP_F_DST_NOREF for route lookup callers to set, to avoid any manipulation on the dst refcnt. And it converts the major input and output path to use it. The performance gain is noticable. I ran synflood tests between 2 hosts under the same switch. Both hosts have 20G mlx NIC, and 8 tx/rx queues. Sender sends pure SYN flood with random src IPs and ports using trafgen. Receiver has a simple TCP listener on the target port. Both hosts have multiple custom rules: - For incoming packets, only local table is traversed. - For outgoing packets, 3 tables are traversed to find the route. The packet processing rate on the receiver is as follows: - Before the fix: 3.78Mpps - After the fix: 5.50Mpps v2->v3: - Handled fib6_rule_lookup() when CONFIG_IPV6_MULTIPLE_TABLES is not configured in patch 03 (suggested by David Ahern) - Removed the renaming of l3mdev_link_scope_lookup() in patch 05 (suggested by David Ahern) - Moved definition of ip6_route_output_flags() from an inline function in /net/ipv6/route.c to net/ipv6/route.c in order to address kbuild error in patch 05 v1->v2: - Added a helper ip6_rt_put_flags() in patch 3 suggested by David Miller ==================== Reviewed-by: David Ahern <dsahern@gmail.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/net/ip6_route.h15
1 files changed, 15 insertions, 0 deletions
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 7375a165fd98..89ad7917b98d 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -36,6 +36,7 @@ struct route_info {
#define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010
#define RT6_LOOKUP_F_SRCPREF_COA 0x00000020
#define RT6_LOOKUP_F_IGNORE_LINKSTATE 0x00000040
+#define RT6_LOOKUP_F_DST_NOREF 0x00000080
/* We do not (yet ?) support IPv6 jumbograms (RFC 2675)
* Unlike IPv4, hdr->seg_len doesn't include the IPv6 header
@@ -83,6 +84,10 @@ struct dst_entry *ip6_route_input_lookup(struct net *net,
struct flowi6 *fl6,
const struct sk_buff *skb, int flags);
+struct dst_entry *ip6_route_output_flags_noref(struct net *net,
+ const struct sock *sk,
+ struct flowi6 *fl6, int flags);
+
struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk,
struct flowi6 *fl6, int flags);
@@ -93,6 +98,16 @@ static inline struct dst_entry *ip6_route_output(struct net *net,
return ip6_route_output_flags(net, sk, fl6, 0);
}
+/* Only conditionally release dst if flags indicates
+ * !RT6_LOOKUP_F_DST_NOREF or dst is in uncached_list.
+ */
+static inline void ip6_rt_put_flags(struct rt6_info *rt, int flags)
+{
+ if (!(flags & RT6_LOOKUP_F_DST_NOREF) ||
+ !list_empty(&rt->rt6i_uncached))
+ ip6_rt_put(rt);
+}
+
struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
const struct sk_buff *skb, int flags);
struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,