Skip to content

Commit

Permalink
geneve: use generic function for tunnel IPv6 route lookup
Browse files Browse the repository at this point in the history
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 daa2ba7
("geneve: use generic function for tunnel IPv4 route lookup").

Suggested-by: Guillaume Nault <gnault@redhat.com>
Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Beniamino Galvani authored and David S. Miller committed Oct 23, 2023
1 parent 946fcfd commit 69d7258
Showing 1 changed file with 31 additions and 65 deletions.
96 changes: 31 additions & 65 deletions drivers/net/geneve.c
Original file line number Diff line number Diff line change
Expand Up @@ -800,57 +800,6 @@ static u8 geneve_get_dsfield(struct sk_buff *skb, struct net_device *dev,
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,
struct geneve_dev *geneve,
const struct ip_tunnel_info *info)
Expand Down Expand Up @@ -967,17 +916,27 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
const struct ip_tunnel_key *key = &info->key;
struct dst_entry *dst = NULL;
struct flowi6 fl6;
struct in6_addr saddr;
bool use_cache;
__u8 prio, ttl;
__be16 sport;
int err;

if (!pskb_inet_may_pull(skb))
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);
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))
return PTR_ERR(dst);

Expand All @@ -999,8 +958,8 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
return -ENOMEM;
}

unclone->key.u.ipv6.dst = fl6.saddr;
unclone->key.u.ipv6.src = fl6.daddr;
unclone->key.u.ipv6.dst = saddr;
unclone->key.u.ipv6.src = info->key.u.ipv6.dst;
}

if (!pskb_may_pull(skb, ETH_HLEN)) {
Expand All @@ -1014,12 +973,10 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
return -EMSGSIZE;
}

prio = ip_tunnel_ecn_encap(prio, ip_hdr(skb), skb);
if (geneve->cfg.collect_md) {
prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
ttl = key->ttl;
} else {
prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel),
ip_hdr(skb), skb);
if (geneve->cfg.ttl_inherit)
ttl = ip_tunnel_get_ttl(ip_hdr(skb), skb);
else
Expand All @@ -1032,7 +989,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
return err;

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.tun_flags & TUNNEL_CSUM));
return 0;
Expand Down Expand Up @@ -1126,19 +1083,28 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
#if IS_ENABLED(CONFIG_IPV6)
} else if (ip_tunnel_info_af(info) == AF_INET6) {
struct dst_entry *dst;
struct flowi6 fl6;

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,
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, &info->key, sport,
geneve->cfg.info.key.tp_dst, prio,
use_cache ? &info->dst_cache : NULL);
if (IS_ERR(dst))
return PTR_ERR(dst);

dst_release(dst);
info->key.u.ipv6.src = fl6.saddr;
info->key.u.ipv6.src = saddr;
#endif
} else {
return -EINVAL;
Expand Down

0 comments on commit 69d7258

Please sign in to comment.