datapath: Fix IP ID setting.
authorJarno Rajahalme <jarno.rajahalme@nsn.com>
Mon, 25 Mar 2013 19:03:38 +0000 (21:03 +0200)
committerJesse Gross <jesse@nicira.com>
Wed, 27 Mar 2013 00:21:25 +0000 (17:21 -0700)
Eliminate the extra call to ip_select_ident(), and place the
__ip_select_ident() call where the ip_select_ident() call was.
This fixes two problems: Before, the call to ip_select_ident() did
always zero out the value set earlier by __ip_select_ident().  Also,
when __ip_select_ident() was called before setting the iph->daddr,
ident calculation was possibly based on uninitialized data (but as
the result was masked by the later call to ip_select_ident() it was
not visible).

Signed-off-by: Jarno Rajahalme <jarno.rajahalme@nsn.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
datapath/tunnel.c

index 8d5a6d4..fca016c 100644 (file)
@@ -280,15 +280,6 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
                /* Push Tunnel header. */
                tnl_vport->tnl_ops->build_header(vport, skb, tunnel_hlen);
 
-               /*
-                * Allow our local IP stack to fragment the outer packet even
-                * if the DF bit is set as a last resort.  We also need to
-                * force selection of an IP ID here because Linux will
-                * otherwise leave it at 0 if the packet originally had DF set.
-                */
-               skb->local_df = 1;
-               __ip_select_ident(ip_hdr(skb), skb_dst(skb), 0);
-
                /* Push IP header. */
                iph = ip_hdr(skb);
                iph->version    = 4;
@@ -300,7 +291,15 @@ int ovs_tnl_send(struct vport *vport, struct sk_buff *skb)
                iph->ttl        = OVS_CB(skb)->tun_key->ipv4_ttl;
                iph->frag_off   = OVS_CB(skb)->tun_key->tun_flags &
                                  OVS_TNL_F_DONT_FRAGMENT ?  htons(IP_DF) : 0;
-               ip_select_ident(iph, &rt_dst(rt), NULL);
+               /*
+                * Allow our local IP stack to fragment the outer packet even
+                * if the DF bit is set as a last resort.  We also need to
+                * force selection of an IP ID here with __ip_select_ident(),
+                * as ip_select_ident() assumes a proper ID is not needed when
+                * when the DF bit is set.
+                */
+               skb->local_df = 1;
+               __ip_select_ident(iph, skb_dst(skb), 0);
 
                memset(IPCB(skb), 0, sizeof(*IPCB(skb)));