net: add dst_cache to ovs vxlan lwtunnel
In case of UDP traffic with datagram length below MTU this give about 2% performance increase when tunneling over ipv4 and about 60% when tunneling over ipv6 Signed-off-by: Paolo Abeni <pabeni@redhat.com> Suggested-and-acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
0c1d70af92
Коммит
d71785ffc7
|
@ -1775,7 +1775,7 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
|
||||||
/* when the ip_tunnel_info is availble, the tos used for lookup is
|
/* when the ip_tunnel_info is availble, the tos used for lookup is
|
||||||
* packet independent, so we can use the cache
|
* packet independent, so we can use the cache
|
||||||
*/
|
*/
|
||||||
if (dst_cache && !skb->mark && (!tos || info)) {
|
if (!skb->mark && (!tos || info)) {
|
||||||
use_cache = true;
|
use_cache = true;
|
||||||
rt = dst_cache_get_ip4(dst_cache, saddr);
|
rt = dst_cache_get_ip4(dst_cache, saddr);
|
||||||
if (rt)
|
if (rt)
|
||||||
|
@ -1806,13 +1806,11 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
|
||||||
struct in6_addr *saddr,
|
struct in6_addr *saddr,
|
||||||
struct dst_cache *dst_cache)
|
struct dst_cache *dst_cache)
|
||||||
{
|
{
|
||||||
bool use_cache = false;
|
|
||||||
struct dst_entry *ndst;
|
struct dst_entry *ndst;
|
||||||
struct flowi6 fl6;
|
struct flowi6 fl6;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (dst_cache && !skb->mark) {
|
if (!skb->mark) {
|
||||||
use_cache = true;
|
|
||||||
ndst = dst_cache_get_ip6(dst_cache, saddr);
|
ndst = dst_cache_get_ip6(dst_cache, saddr);
|
||||||
if (ndst)
|
if (ndst)
|
||||||
return ndst;
|
return ndst;
|
||||||
|
@ -1832,7 +1830,7 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
*saddr = fl6.saddr;
|
*saddr = fl6.saddr;
|
||||||
if (use_cache)
|
if (!skb->mark)
|
||||||
dst_cache_set_ip6(dst_cache, ndst, saddr);
|
dst_cache_set_ip6(dst_cache, ndst, saddr);
|
||||||
return ndst;
|
return ndst;
|
||||||
}
|
}
|
||||||
|
@ -1886,6 +1884,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
|
||||||
static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||||
struct vxlan_rdst *rdst, bool did_rsc)
|
struct vxlan_rdst *rdst, bool did_rsc)
|
||||||
{
|
{
|
||||||
|
struct dst_cache *dst_cache;
|
||||||
struct ip_tunnel_info *info;
|
struct ip_tunnel_info *info;
|
||||||
struct vxlan_dev *vxlan = netdev_priv(dev);
|
struct vxlan_dev *vxlan = netdev_priv(dev);
|
||||||
struct sock *sk;
|
struct sock *sk;
|
||||||
|
@ -1910,6 +1909,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||||
dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
|
dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port;
|
||||||
vni = rdst->remote_vni;
|
vni = rdst->remote_vni;
|
||||||
dst = &rdst->remote_ip;
|
dst = &rdst->remote_ip;
|
||||||
|
dst_cache = &rdst->dst_cache;
|
||||||
} else {
|
} else {
|
||||||
if (!info) {
|
if (!info) {
|
||||||
WARN_ONCE(1, "%s: Missing encapsulation instructions\n",
|
WARN_ONCE(1, "%s: Missing encapsulation instructions\n",
|
||||||
|
@ -1924,6 +1924,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||||
else
|
else
|
||||||
remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst;
|
remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst;
|
||||||
dst = &remote_ip;
|
dst = &remote_ip;
|
||||||
|
dst_cache = &info->dst_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vxlan_addr_any(dst)) {
|
if (vxlan_addr_any(dst)) {
|
||||||
|
@ -1976,7 +1977,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||||
rt = vxlan_get_route(vxlan, skb,
|
rt = vxlan_get_route(vxlan, skb,
|
||||||
rdst ? rdst->remote_ifindex : 0, tos,
|
rdst ? rdst->remote_ifindex : 0, tos,
|
||||||
dst->sin.sin_addr.s_addr, &saddr,
|
dst->sin.sin_addr.s_addr, &saddr,
|
||||||
rdst ? &rdst->dst_cache : NULL, info);
|
dst_cache, info);
|
||||||
if (IS_ERR(rt)) {
|
if (IS_ERR(rt)) {
|
||||||
netdev_dbg(dev, "no route to %pI4\n",
|
netdev_dbg(dev, "no route to %pI4\n",
|
||||||
&dst->sin.sin_addr.s_addr);
|
&dst->sin.sin_addr.s_addr);
|
||||||
|
@ -2029,7 +2030,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
|
||||||
ndst = vxlan6_get_route(vxlan, skb,
|
ndst = vxlan6_get_route(vxlan, skb,
|
||||||
rdst ? rdst->remote_ifindex : 0,
|
rdst ? rdst->remote_ifindex : 0,
|
||||||
&dst->sin6.sin6_addr, &saddr,
|
&dst->sin6.sin6_addr, &saddr,
|
||||||
rdst ? &rdst->dst_cache : NULL);
|
dst_cache);
|
||||||
if (IS_ERR(ndst)) {
|
if (IS_ERR(ndst)) {
|
||||||
netdev_dbg(dev, "no route to %pI6\n",
|
netdev_dbg(dev, "no route to %pI6\n",
|
||||||
&dst->sin6.sin6_addr);
|
&dst->sin6.sin6_addr);
|
||||||
|
|
|
@ -62,6 +62,7 @@ static inline int skb_metadata_dst_cmp(const struct sk_buff *skb_a,
|
||||||
sizeof(a->u.tun_info) + a->u.tun_info.options_len);
|
sizeof(a->u.tun_info) + a->u.tun_info.options_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void metadata_dst_free(struct metadata_dst *);
|
||||||
struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags);
|
struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags);
|
||||||
struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags);
|
struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags);
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,9 @@ struct ip_tunnel_key {
|
||||||
|
|
||||||
struct ip_tunnel_info {
|
struct ip_tunnel_info {
|
||||||
struct ip_tunnel_key key;
|
struct ip_tunnel_key key;
|
||||||
|
#ifdef CONFIG_DST_CACHE
|
||||||
|
struct dst_cache dst_cache;
|
||||||
|
#endif
|
||||||
u8 options_len;
|
u8 options_len;
|
||||||
u8 mode;
|
u8 mode;
|
||||||
};
|
};
|
||||||
|
|
|
@ -265,7 +265,7 @@ again:
|
||||||
lwtstate_put(dst->lwtstate);
|
lwtstate_put(dst->lwtstate);
|
||||||
|
|
||||||
if (dst->flags & DST_METADATA)
|
if (dst->flags & DST_METADATA)
|
||||||
kfree(dst);
|
metadata_dst_free((struct metadata_dst *)dst);
|
||||||
else
|
else
|
||||||
kmem_cache_free(dst->ops->kmem_cachep, dst);
|
kmem_cache_free(dst->ops->kmem_cachep, dst);
|
||||||
|
|
||||||
|
@ -395,6 +395,14 @@ struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(metadata_dst_alloc);
|
EXPORT_SYMBOL_GPL(metadata_dst_alloc);
|
||||||
|
|
||||||
|
void metadata_dst_free(struct metadata_dst *md_dst)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_DST_CACHE
|
||||||
|
dst_cache_destroy(&md_dst->u.tun_info.dst_cache);
|
||||||
|
#endif
|
||||||
|
kfree(md_dst);
|
||||||
|
}
|
||||||
|
|
||||||
struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags)
|
struct metadata_dst __percpu *metadata_dst_alloc_percpu(u8 optslen, gfp_t flags)
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
|
@ -10,6 +10,7 @@ config OPENVSWITCH
|
||||||
select LIBCRC32C
|
select LIBCRC32C
|
||||||
select MPLS
|
select MPLS
|
||||||
select NET_MPLS_GSO
|
select NET_MPLS_GSO
|
||||||
|
select DST_CACHE
|
||||||
---help---
|
---help---
|
||||||
Open vSwitch is a multilayer Ethernet switch targeted at virtualized
|
Open vSwitch is a multilayer Ethernet switch targeted at virtualized
|
||||||
environments. In addition to supporting a variety of features
|
environments. In addition to supporting a variety of features
|
||||||
|
|
|
@ -1959,6 +1959,12 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
|
||||||
if (!tun_dst)
|
if (!tun_dst)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
err = dst_cache_init(&tun_dst->u.tun_info.dst_cache, GFP_KERNEL);
|
||||||
|
if (err) {
|
||||||
|
dst_release((struct dst_entry *)tun_dst);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
|
a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
|
||||||
sizeof(*ovs_tun), log);
|
sizeof(*ovs_tun), log);
|
||||||
if (IS_ERR(a)) {
|
if (IS_ERR(a)) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче