+
+ /* 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,
+ IPPROTO_UDP,
+ OVS_CB(skb)->tun_key->ipv4_tos,
+ skb->mark);
+ if (IS_ERR(rt)) {
+ err = PTR_ERR(rt);
+ goto error;
+ }
+
+ min_headroom = LL_RESERVED_SPACE(rt_dst(rt).dev) + rt_dst(rt).header_len
+ + sizeof(struct iphdr) + LISP_HLEN;
+
+ if (skb_headroom(skb) < min_headroom || skb_header_cloned(skb)) {
+ int head_delta = SKB_DATA_ALIGN(min_headroom -
+ skb_headroom(skb) +
+ 16);
+
+ err = pskb_expand_head(skb, max_t(int, head_delta, 0),
+ 0, GFP_ATOMIC);
+ if (unlikely(err))
+ goto err_free_rt;
+ }
+
+ /* Reset l2 headers. */
+ skb_pull(skb, network_offset);
+ skb_reset_mac_header(skb);
+ vlan_set_tci(skb, 0);
+
+ skb_reset_inner_headers(skb);
+
+ __skb_push(skb, LISP_HLEN);
+ skb_reset_transport_header(skb);
+
+ lisp_build_header(vport, skb);
+
+ /* Offloading */
+ err = handle_offloads(skb);
+ if (err)
+ goto err_free_rt;
+
+ skb->local_df = 1;
+
+ df = OVS_CB(skb)->tun_key->tun_flags &
+ TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
+ sent_len = iptunnel_xmit(rt, skb,
+ saddr, OVS_CB(skb)->tun_key->ipv4_dst,
+ IPPROTO_UDP, OVS_CB(skb)->tun_key->ipv4_tos,
+ OVS_CB(skb)->tun_key->ipv4_ttl, df, false);
+
+ return sent_len > 0 ? sent_len + network_offset : sent_len;
+
+err_free_rt:
+ ip_rt_put(rt);
+error:
+ return err;