Commit 69d72587 authored by Beniamino Galvani's avatar Beniamino Galvani Committed by David S. Miller

geneve: use generic function for tunnel IPv6 route lookup

The route lookup can be done now via generic function
udp_tunnel6_dst_lookup() to replace the custom implementation in
geneve_get_v6_dst().

This is similar to what already done for IPv4 in commit daa2ba7e
("geneve: use generic function for tunnel IPv4 route lookup").
Suggested-by: default avatarGuillaume Nault <gnault@redhat.com>
Signed-off-by: default avatarBeniamino Galvani <b.galvani@gmail.com>
Reviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 946fcfdb
...@@ -800,57 +800,6 @@ static u8 geneve_get_dsfield(struct sk_buff *skb, struct net_device *dev, ...@@ -800,57 +800,6 @@ static u8 geneve_get_dsfield(struct sk_buff *skb, struct net_device *dev,
return dsfield; return dsfield;
} }
#if IS_ENABLED(CONFIG_IPV6)
static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
struct net_device *dev,
struct geneve_sock *gs6,
struct flowi6 *fl6,
const struct ip_tunnel_info *info,
__be16 dport, __be16 sport)
{
bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
struct geneve_dev *geneve = netdev_priv(dev);
struct dst_entry *dst = NULL;
struct dst_cache *dst_cache;
__u8 prio;
if (!gs6)
return ERR_PTR(-EIO);
memset(fl6, 0, sizeof(*fl6));
fl6->flowi6_mark = skb->mark;
fl6->flowi6_proto = IPPROTO_UDP;
fl6->daddr = info->key.u.ipv6.dst;
fl6->saddr = info->key.u.ipv6.src;
fl6->fl6_dport = dport;
fl6->fl6_sport = sport;
prio = geneve_get_dsfield(skb, dev, info, &use_cache);
fl6->flowlabel = ip6_make_flowinfo(prio, info->key.label);
dst_cache = (struct dst_cache *)&info->dst_cache;
if (use_cache) {
dst = dst_cache_get_ip6(dst_cache, &fl6->saddr);
if (dst)
return dst;
}
dst = ipv6_stub->ipv6_dst_lookup_flow(geneve->net, gs6->sock->sk, fl6,
NULL);
if (IS_ERR(dst)) {
netdev_dbg(dev, "no route to %pI6\n", &fl6->daddr);
return ERR_PTR(-ENETUNREACH);
}
if (dst->dev == dev) { /* is this necessary? */
netdev_dbg(dev, "circular route to %pI6\n", &fl6->daddr);
dst_release(dst);
return ERR_PTR(-ELOOP);
}
if (use_cache)
dst_cache_set_ip6(dst_cache, dst, &fl6->saddr);
return dst;
}
#endif
static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct geneve_dev *geneve, struct geneve_dev *geneve,
const struct ip_tunnel_info *info) const struct ip_tunnel_info *info)
...@@ -967,7 +916,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -967,7 +916,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct geneve_sock *gs6 = rcu_dereference(geneve->sock6); struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
const struct ip_tunnel_key *key = &info->key; const struct ip_tunnel_key *key = &info->key;
struct dst_entry *dst = NULL; struct dst_entry *dst = NULL;
struct flowi6 fl6; struct in6_addr saddr;
bool use_cache;
__u8 prio, ttl; __u8 prio, ttl;
__be16 sport; __be16 sport;
int err; int err;
...@@ -975,9 +925,18 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -975,9 +925,18 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
if (!pskb_inet_may_pull(skb)) if (!pskb_inet_may_pull(skb))
return -EINVAL; return -EINVAL;
if (!gs6)
return -EIO;
use_cache = ip_tunnel_dst_cache_usable(skb, info);
prio = geneve_get_dsfield(skb, dev, info, &use_cache);
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info,
geneve->cfg.info.key.tp_dst, sport); dst = udp_tunnel6_dst_lookup(skb, dev, geneve->net, gs6->sock, 0,
&saddr, key, sport,
geneve->cfg.info.key.tp_dst, prio,
use_cache ?
(struct dst_cache *)&info->dst_cache : NULL);
if (IS_ERR(dst)) if (IS_ERR(dst))
return PTR_ERR(dst); return PTR_ERR(dst);
...@@ -999,8 +958,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -999,8 +958,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
return -ENOMEM; return -ENOMEM;
} }
unclone->key.u.ipv6.dst = fl6.saddr; unclone->key.u.ipv6.dst = saddr;
unclone->key.u.ipv6.src = fl6.daddr; unclone->key.u.ipv6.src = info->key.u.ipv6.dst;
} }
if (!pskb_may_pull(skb, ETH_HLEN)) { if (!pskb_may_pull(skb, ETH_HLEN)) {
...@@ -1014,12 +973,10 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -1014,12 +973,10 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
return -EMSGSIZE; return -EMSGSIZE;
} }
prio = ip_tunnel_ecn_encap(prio, ip_hdr(skb), skb);
if (geneve->cfg.collect_md) { if (geneve->cfg.collect_md) {
prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
ttl = key->ttl; ttl = key->ttl;
} else { } else {
prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel),
ip_hdr(skb), skb);
if (geneve->cfg.ttl_inherit) if (geneve->cfg.ttl_inherit)
ttl = ip_tunnel_get_ttl(ip_hdr(skb), skb); ttl = ip_tunnel_get_ttl(ip_hdr(skb), skb);
else else
...@@ -1032,7 +989,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -1032,7 +989,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
return err; return err;
udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev, udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev,
&fl6.saddr, &fl6.daddr, prio, ttl, &saddr, &key->u.ipv6.dst, prio, ttl,
info->key.label, sport, geneve->cfg.info.key.tp_dst, info->key.label, sport, geneve->cfg.info.key.tp_dst,
!(info->key.tun_flags & TUNNEL_CSUM)); !(info->key.tun_flags & TUNNEL_CSUM));
return 0; return 0;
...@@ -1126,19 +1083,28 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) ...@@ -1126,19 +1083,28 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
} else if (ip_tunnel_info_af(info) == AF_INET6) { } else if (ip_tunnel_info_af(info) == AF_INET6) {
struct dst_entry *dst; struct dst_entry *dst;
struct flowi6 fl6;
struct geneve_sock *gs6 = rcu_dereference(geneve->sock6); struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
struct in6_addr saddr;
bool use_cache;
u8 prio;
if (!gs6)
return -EIO;
use_cache = ip_tunnel_dst_cache_usable(skb, info);
prio = geneve_get_dsfield(skb, dev, info, &use_cache);
sport = udp_flow_src_port(geneve->net, skb, sport = udp_flow_src_port(geneve->net, skb,
1, USHRT_MAX, true); 1, USHRT_MAX, true);
dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info, dst = udp_tunnel6_dst_lookup(skb, dev, geneve->net, gs6->sock, 0,
geneve->cfg.info.key.tp_dst, sport); &saddr, &info->key, sport,
geneve->cfg.info.key.tp_dst, prio,
use_cache ? &info->dst_cache : NULL);
if (IS_ERR(dst)) if (IS_ERR(dst))
return PTR_ERR(dst); return PTR_ERR(dst);
dst_release(dst); dst_release(dst);
info->key.u.ipv6.src = fl6.saddr; info->key.u.ipv6.src = saddr;
#endif #endif
} else { } else {
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment