Use the tun_key, which is the basis of flow-based tunnelling, on transmit.

Cc: Kyle Mestery <kmest...@cisco.com>
Signed-off-by: Simon Horman <ho...@verge.net.au>
---
 datapath/tunnel.c |   44 +++++++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 2c1c210..bb545c2 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -1002,12 +1002,13 @@ unlock:
 }
 
 static struct rtable *__find_route(const struct tnl_mutable_config *mutable,
-                                  u8 ipproto, u8 tos)
+                                  u8 ipproto, __be32 daddr, __be32 saddr,
+                                  u8 tos)
 {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)
        struct flowi fl = { .nl_u = { .ip4_u = {
-                                       .daddr = mutable->key.daddr,
-                                       .saddr = mutable->key.saddr,
+                                       .daddr = daddr,
+                                       .saddr = saddr,
                                        .tos = tos } },
                            .proto = ipproto };
        struct rtable *rt;
@@ -1017,8 +1018,8 @@ static struct rtable *__find_route(const struct 
tnl_mutable_config *mutable,
 
        return rt;
 #else
-       struct flowi4 fl = { .daddr = mutable->key.daddr,
-                            .saddr = mutable->key.saddr,
+       struct flowi4 fl = { .daddr = daddr,
+                            .saddr = saddr,
                             .flowi4_tos = tos,
                             .flowi4_proto = ipproto };
 
@@ -1028,7 +1029,8 @@ static struct rtable *__find_route(const struct 
tnl_mutable_config *mutable,
 
 static struct rtable *find_route(struct vport *vport,
                                 const struct tnl_mutable_config *mutable,
-                                u8 tos, struct tnl_cache **cache)
+                                u8 tos, __be32 daddr, __be32 saddr,
+                                struct tnl_cache **cache)
 {
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
        struct tnl_cache *cur_cache = rcu_dereference(tnl_vport->cache);
@@ -1036,14 +1038,15 @@ static struct rtable *find_route(struct vport *vport,
        *cache = NULL;
        tos = RT_TOS(tos);
 
-       if (likely(tos == mutable->tos &&
-           check_cache_valid(cur_cache, mutable))) {
+       if (daddr == mutable->key.daddr && saddr == mutable->key.saddr &&
+           tos == mutable->tos && check_cache_valid(cur_cache, mutable)) {
                *cache = cur_cache;
                return cur_cache->rt;
        } else {
                struct rtable *rt;
 
-               rt = __find_route(mutable, tnl_vport->tnl_ops->ipproto, tos);
+               rt = __find_route(mutable, tnl_vport->tnl_ops->ipproto,
+                                 daddr, saddr, tos);
                if (IS_ERR(rt))
                        return NULL;
 
@@ -1179,6 +1182,8 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
        struct tnl_cache *cache;
        int sent_len = 0;
        __be16 frag_off = 0;
+       __be32 daddr;
+       __be32 saddr;
        u8 ttl;
        u8 inner_tos;
        u8 tos;
@@ -1218,13 +1223,23 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff 
*skb)
 
        if (mutable->flags & TNL_F_TOS_INHERIT)
                tos = inner_tos;
+       else if (OVS_CB(skb)->tun_key)
+               tos = OVS_CB(skb)->tun_key->ipv4_tos;
        else
                tos = mutable->tos;
 
        tos = INET_ECN_encapsulate(tos, inner_tos);
 
+       if (OVS_CB(skb)->tun_key) {
+               daddr = OVS_CB(skb)->tun_key->ipv4_dst;
+               saddr = OVS_CB(skb)->tun_key->ipv4_src;
+       } else {
+               daddr = mutable->key.daddr;
+               saddr = mutable->key.saddr;
+       }
+
        /* Route lookup */
-       rt = find_route(vport, mutable, tos, &cache);
+       rt = find_route(vport, mutable, tos, daddr, saddr, &cache);
        if (unlikely(!rt))
                goto error_free;
        if (unlikely(!cache))
@@ -1259,10 +1274,12 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff 
*skb)
        }
 
        /* TTL */
-       ttl = mutable->ttl;
+       if (OVS_CB(skb)->tun_key)
+               ttl = OVS_CB(skb)->tun_key->ipv4_ttl;
+       else
+               ttl = mutable->ttl;
        if (!ttl)
                ttl = ip4_dst_hoplimit(&rt_dst(rt));
-
        if (mutable->flags & TNL_F_TTL_INHERIT) {
                if (skb->protocol == htons(ETH_P_IP))
                        ttl = ip_hdr(skb)->ttl;
@@ -1440,7 +1457,8 @@ static int tnl_set_config(struct net *net, struct nlattr 
*options,
                struct net_device *dev;
                struct rtable *rt;
 
-               rt = __find_route(mutable, tnl_ops->ipproto, mutable->tos);
+               rt = __find_route(mutable, tnl_ops->ipproto, mutable->tos,
+                                 mutable->key.daddr, mutable->key.saddr);
                if (IS_ERR(rt))
                        return -EADDRNOTAVAIL;
                dev = rt_dst(rt).dev;
-- 
1.7.10

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to