Skip to content

Commit

Permalink
Merge branch 'consolidate-udp-ipv6-route-lookups'
Browse files Browse the repository at this point in the history
Beniamino Galvani says:

====================
net: consolidate IPv6 route lookup for UDP tunnels

At the moment different UDP tunnels rely on different functions for
IPv6 route lookup, and those functions all implement the same
logic.

Extend the generic lookup function so that it is suitable for all UDP
tunnel implementations, and then adapt bareudp, geneve and vxlan to
use it.

This is similar to what already done for IPv4.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 23, 2023
2 parents 92fc97a + 2aceb89 commit 35c1b27
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 250 deletions.
13 changes: 8 additions & 5 deletions drivers/net/bareudp.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,10 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
if (!sock)
return -ESHUTDOWN;

dst = ip6_dst_lookup_tunnel(skb, dev, bareudp->net, sock, &saddr, info,
IPPROTO_UDP, use_cache);
dst = udp_tunnel6_dst_lookup(skb, dev, bareudp->net, sock, 0, &saddr,
key, 0, 0, key->tos,
use_cache ?
(struct dst_cache *) &info->dst_cache : NULL);
if (IS_ERR(dst))
return PTR_ERR(dst);

Expand Down Expand Up @@ -498,9 +500,10 @@ static int bareudp_fill_metadata_dst(struct net_device *dev,
struct in6_addr saddr;
struct socket *sock = rcu_dereference(bareudp->sock);

dst = ip6_dst_lookup_tunnel(skb, dev, bareudp->net, sock,
&saddr, info, IPPROTO_UDP,
use_cache);
dst = udp_tunnel6_dst_lookup(skb, dev, bareudp->net, sock,
0, &saddr, &info->key,
0, 0, info->key.tos,
use_cache ? &info->dst_cache : NULL);
if (IS_ERR(dst))
return PTR_ERR(dst);

Expand Down
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
Loading

0 comments on commit 35c1b27

Please sign in to comment.