summaryrefslogtreecommitdiffstats
path: root/net/l3mdev
diff options
context:
space:
mode:
authorWei Wang <weiwan@google.com>2019-06-20 20:36:41 -0400
committerDavid S. Miller <davem@davemloft.net>2019-06-23 16:24:17 -0400
commit7d9e5f422150ed00de744e02a80734d74cc9704d (patch)
tree5649667efad829c536543d0feb5374ad42b93483 /net/l3mdev
parent67f415dd29063a5906c560051c00e42dcf01a4dd (diff)
ipv6: convert major tx path to use RT6_LOOKUP_F_DST_NOREF
For tx path, in most cases, we still have to take refcnt on the dst cause the caller is caching the dst somewhere. But it still is beneficial to make use of RT6_LOOKUP_F_DST_NOREF flag while doing the route lookup. It is cause this flag prevents manipulating refcnt on net->ipv6.ip6_null_entry when doing fib6_rule_lookup() to traverse each routing table. The null_entry is a shared object and constant updates on it cause false sharing. We converted the current major lookup function ip6_route_output_flags() to make use of RT6_LOOKUP_F_DST_NOREF. Together with the change in the rx path, we see noticable performance boost: 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 Signed-off-by: Wei Wang <weiwan@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l3mdev')
-rw-r--r--net/l3mdev/l3mdev.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/net/l3mdev/l3mdev.c b/net/l3mdev/l3mdev.c
index cfc9fcb97465..f35899d45a9a 100644
--- a/net/l3mdev/l3mdev.c
+++ b/net/l3mdev/l3mdev.c
@@ -118,6 +118,8 @@ EXPORT_SYMBOL_GPL(l3mdev_fib_table_by_index);
118 * local and multicast addresses 118 * local and multicast addresses
119 * @net: network namespace for device index lookup 119 * @net: network namespace for device index lookup
120 * @fl6: IPv6 flow struct for lookup 120 * @fl6: IPv6 flow struct for lookup
121 * This function does not hold refcnt on the returned dst.
122 * Caller must hold rcu_read_lock().
121 */ 123 */
122 124
123struct dst_entry *l3mdev_link_scope_lookup(struct net *net, 125struct dst_entry *l3mdev_link_scope_lookup(struct net *net,
@@ -126,9 +128,8 @@ struct dst_entry *l3mdev_link_scope_lookup(struct net *net,
126 struct dst_entry *dst = NULL; 128 struct dst_entry *dst = NULL;
127 struct net_device *dev; 129 struct net_device *dev;
128 130
131 WARN_ON_ONCE(!rcu_read_lock_held());
129 if (fl6->flowi6_oif) { 132 if (fl6->flowi6_oif) {
130 rcu_read_lock();
131
132 dev = dev_get_by_index_rcu(net, fl6->flowi6_oif); 133 dev = dev_get_by_index_rcu(net, fl6->flowi6_oif);
133 if (dev && netif_is_l3_slave(dev)) 134 if (dev && netif_is_l3_slave(dev))
134 dev = netdev_master_upper_dev_get_rcu(dev); 135 dev = netdev_master_upper_dev_get_rcu(dev);
@@ -136,8 +137,6 @@ struct dst_entry *l3mdev_link_scope_lookup(struct net *net,
136 if (dev && netif_is_l3_master(dev) && 137 if (dev && netif_is_l3_master(dev) &&
137 dev->l3mdev_ops->l3mdev_link_scope_lookup) 138 dev->l3mdev_ops->l3mdev_link_scope_lookup)
138 dst = dev->l3mdev_ops->l3mdev_link_scope_lookup(dev, fl6); 139 dst = dev->l3mdev_ops->l3mdev_link_scope_lookup(dev, fl6);
139
140 rcu_read_unlock();
141 } 140 }
142 141
143 return dst; 142 return dst;