While sending packet over tunnel it can get segmented or reallocated.
In that case we loose OVS_CB(). But some tunneling protocol
implementation needs OVS_CB(), e.g. vxlan needs OVS_CB()->flow which
leads to kernel panic.
Following patch set flow before calling tnl_ops->build_header() and fixes
OVS_CB(skb)->tun_key access.

Signed-off-by: Pravin B Shelar <pshe...@nicira.com>
---
 datapath/tunnel.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/datapath/tunnel.c b/datapath/tunnel.c
index 83d2c41..2ca3e9a 100644
--- a/datapath/tunnel.c
+++ b/datapath/tunnel.c
@@ -221,27 +221,29 @@ u16 ovs_tnl_get_src_port(struct sk_buff *skb)
 int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
 {
        struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
+       struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
+       struct sw_flow *flow = OVS_CB(skb)->flow;
        struct rtable *rt;
        __be32 saddr;
        int sent_len = 0;
        int tunnel_hlen;
 
-       if (unlikely(!OVS_CB(skb)->tun_key))
+       if (unlikely(!tun_key))
                goto error_free;
 
        /* Route lookup */
        saddr = OVS_CB(skb)->tun_key->ipv4_src;
        rt = find_route(ovs_dp_get_net(vport->dp),
                        &saddr,
-                       OVS_CB(skb)->tun_key->ipv4_dst,
+                       tun_key->ipv4_dst,
                        tnl_vport->tnl_ops->ipproto,
-                       OVS_CB(skb)->tun_key->ipv4_tos,
+                       tun_key->ipv4_tos,
                        skb_get_mark(skb));
        if (IS_ERR(rt))
                goto error_free;
 
        /* Offloading */
-       tunnel_hlen = tnl_vport->tnl_ops->hdr_len(OVS_CB(skb)->tun_key);
+       tunnel_hlen = tnl_vport->tnl_ops->hdr_len(tun_key);
        tunnel_hlen += sizeof(struct iphdr);
 
        skb = handle_offloads(skb, rt, tunnel_hlen);
@@ -263,6 +265,7 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
                int err;
 
                skb->next = NULL;
+               OVS_CB(skb)->flow = flow;
 
                if (unlikely(vlan_deaccel_tag(skb)))
                        goto next;
@@ -285,11 +288,11 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
                iph->version    = 4;
                iph->ihl        = sizeof(struct iphdr) >> 2;
                iph->protocol   = tnl_vport->tnl_ops->ipproto;
-               iph->daddr      = OVS_CB(skb)->tun_key->ipv4_dst;
+               iph->daddr      = tun_key->ipv4_dst;
                iph->saddr      = saddr;
-               iph->tos        = OVS_CB(skb)->tun_key->ipv4_tos;
-               iph->ttl        = OVS_CB(skb)->tun_key->ipv4_ttl;
-               iph->frag_off   = OVS_CB(skb)->tun_key->tun_flags &
+               iph->tos        = tun_key->ipv4_tos;
+               iph->ttl        = tun_key->ipv4_ttl;
+               iph->frag_off   = tun_key->tun_flags &
                                  OVS_TNL_F_DONT_FRAGMENT ?  htons(IP_DF) : 0;
                ip_select_ident(iph, &rt_dst(rt), NULL);
 
-- 
1.7.1

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

Reply via email to