vxlan: allow setting ipv6 traffic class
authorDaniel Borkmann <daniel@iogearbox.net>
Fri, 4 Mar 2016 14:15:08 +0000 (15:15 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 8 Mar 2016 18:58:47 +0000 (13:58 -0500)
We can already do that for IPv4, but IPv6 support was missing. Add
it for vxlan, so it can be used with collect metadata frontends.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/vxlan.c

index 7294a45..2399099 100644 (file)
@@ -1789,7 +1789,7 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan,
 
 #if IS_ENABLED(CONFIG_IPV6)
 static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
-                                         struct sk_buff *skb, int oif,
+                                         struct sk_buff *skb, int oif, u8 tos,
                                          const struct in6_addr *daddr,
                                          struct in6_addr *saddr,
                                          struct dst_cache *dst_cache,
@@ -1800,6 +1800,8 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
        struct flowi6 fl6;
        int err;
 
+       if (tos && !info)
+               use_cache = false;
        if (use_cache) {
                ndst = dst_cache_get_ip6(dst_cache, saddr);
                if (ndst)
@@ -1808,6 +1810,7 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
 
        memset(&fl6, 0, sizeof(fl6));
        fl6.flowi6_oif = oif;
+       fl6.flowi6_tos = RT_TOS(tos);
        fl6.daddr = *daddr;
        fl6.saddr = vxlan->cfg.saddr.sin6.sin6_addr;
        fl6.flowi6_mark = skb->mark;
@@ -2016,7 +2019,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                sk = vxlan->vn6_sock->sock->sk;
 
                ndst = vxlan6_get_route(vxlan, skb,
-                                       rdst ? rdst->remote_ifindex : 0,
+                                       rdst ? rdst->remote_ifindex : 0, tos,
                                        &dst->sin6.sin6_addr, &saddr,
                                        dst_cache, info);
                if (IS_ERR(ndst)) {
@@ -2053,6 +2056,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                if (!info)
                        udp_sum = !(flags & VXLAN_F_UDP_ZERO_CSUM6_TX);
 
+               tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
                ttl = ttl ? : ip6_dst_hoplimit(ndst);
                skb_scrub_packet(skb, xnet);
                err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
@@ -2062,8 +2066,8 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                        return;
                }
                udp_tunnel6_xmit_skb(ndst, sk, skb, dev,
-                                    &saddr, &dst->sin6.sin6_addr,
-                                    0, ttl, src_port, dst_port, !udp_sum);
+                                    &saddr, &dst->sin6.sin6_addr, tos, ttl,
+                                    src_port, dst_port, !udp_sum);
 #endif
        }
 
@@ -2385,7 +2389,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 
                if (!vxlan->vn6_sock)
                        return -EINVAL;
-               ndst = vxlan6_get_route(vxlan, skb, 0,
+               ndst = vxlan6_get_route(vxlan, skb, 0, info->key.tos,
                                        &info->key.u.ipv6.dst,
                                        &info->key.u.ipv6.src, NULL, info);
                if (IS_ERR(ndst))