Commit a725e514 authored by Jiri Benc's avatar Jiri Benc Committed by David S. Miller

vxlan: metadata based tunneling for IPv6

Support metadata based (formerly flow based) tunneling also for IPv6.
This complements commit ee122c79 ("vxlan: Flow based tunneling").
Signed-off-by: default avatarJiri Benc <jbenc@redhat.com>
Acked-by: default avatarThomas Graf <tgraf@suug.ch>
Acked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6f264e47
...@@ -1269,17 +1269,27 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb) ...@@ -1269,17 +1269,27 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
} }
if (vxlan_collect_metadata(vs)) { if (vxlan_collect_metadata(vs)) {
const struct iphdr *iph = ip_hdr(skb);
tun_dst = metadata_dst_alloc(sizeof(*md), GFP_ATOMIC); tun_dst = metadata_dst_alloc(sizeof(*md), GFP_ATOMIC);
if (!tun_dst) if (!tun_dst)
goto drop; goto drop;
info = &tun_dst->u.tun_info; info = &tun_dst->u.tun_info;
if (vxlan_get_sk_family(vs) == AF_INET) {
const struct iphdr *iph = ip_hdr(skb);
info->key.u.ipv4.src = iph->saddr; info->key.u.ipv4.src = iph->saddr;
info->key.u.ipv4.dst = iph->daddr; info->key.u.ipv4.dst = iph->daddr;
info->key.tos = iph->tos; info->key.tos = iph->tos;
info->key.ttl = iph->ttl; info->key.ttl = iph->ttl;
} else {
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
info->key.u.ipv6.src = ip6h->saddr;
info->key.u.ipv6.dst = ip6h->daddr;
info->key.tos = ipv6_get_dsfield(ip6h);
info->key.ttl = ip6h->hop_limit;
}
info->key.tp_src = udp_hdr(skb)->source; info->key.tp_src = udp_hdr(skb)->source;
info->key.tp_dst = udp_hdr(skb)->dest; info->key.tp_dst = udp_hdr(skb)->dest;
...@@ -1894,6 +1904,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -1894,6 +1904,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
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 = vxlan->vn_sock->sock->sk; struct sock *sk = vxlan->vn_sock->sock->sk;
unsigned short family = vxlan_get_sk_family(vxlan->vn_sock);
struct rtable *rt = NULL; struct rtable *rt = NULL;
const struct iphdr *old_iph; const struct iphdr *old_iph;
struct flowi4 fl4; struct flowi4 fl4;
...@@ -1908,7 +1919,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -1908,7 +1919,6 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
int err; int err;
u32 flags = vxlan->flags; u32 flags = vxlan->flags;
/* FIXME: Support IPv6 */
info = skb_tunnel_info(skb); info = skb_tunnel_info(skb);
if (rdst) { if (rdst) {
...@@ -1924,8 +1934,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -1924,8 +1934,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port;
vni = be64_to_cpu(info->key.tun_id); vni = be64_to_cpu(info->key.tun_id);
remote_ip.sin.sin_family = AF_INET; remote_ip.sa.sa_family = family;
if (family == AF_INET)
remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst;
else
remote_ip.sin6.sin6_addr = info->key.u.ipv6.dst;
dst = &remote_ip; dst = &remote_ip;
} }
...@@ -1951,10 +1964,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -1951,10 +1964,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min, src_port = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
vxlan->cfg.port_max, true); vxlan->cfg.port_max, true);
if (dst->sa.sa_family == AF_INET) {
if (info) { if (info) {
if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT)
df = htons(IP_DF);
if (info->key.tun_flags & TUNNEL_CSUM) if (info->key.tun_flags & TUNNEL_CSUM)
flags |= VXLAN_F_UDP_CSUM; flags |= VXLAN_F_UDP_CSUM;
else else
...@@ -1969,6 +1979,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -1969,6 +1979,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
md->gbp = skb->mark; md->gbp = skb->mark;
} }
if (dst->sa.sa_family == AF_INET) {
if (info && (info->key.tun_flags & TUNNEL_DONT_FRAGMENT))
df = htons(IP_DF);
memset(&fl4, 0, sizeof(fl4)); memset(&fl4, 0, sizeof(fl4));
fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0; fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0;
fl4.flowi4_tos = RT_TOS(tos); fl4.flowi4_tos = RT_TOS(tos);
...@@ -2066,12 +2080,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, ...@@ -2066,12 +2080,10 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
} }
ttl = ttl ? : ip6_dst_hoplimit(ndst); ttl = ttl ? : ip6_dst_hoplimit(ndst);
md->gbp = skb->mark;
err = vxlan6_xmit_skb(ndst, sk, skb, dev, &fl6.saddr, &fl6.daddr, err = vxlan6_xmit_skb(ndst, sk, skb, dev, &fl6.saddr, &fl6.daddr,
0, ttl, src_port, dst_port, htonl(vni << 8), md, 0, ttl, src_port, dst_port, htonl(vni << 8), md,
!net_eq(vxlan->net, dev_net(vxlan->dev)), !net_eq(vxlan->net, dev_net(vxlan->dev)),
vxlan->flags); flags);
#endif #endif
} }
...@@ -2104,7 +2116,6 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2104,7 +2116,6 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
struct vxlan_rdst *rdst, *fdst = NULL; struct vxlan_rdst *rdst, *fdst = NULL;
struct vxlan_fdb *f; struct vxlan_fdb *f;
/* FIXME: Support IPv6 */
info = skb_tunnel_info(skb); info = skb_tunnel_info(skb);
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
......
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