- return NULL;
-}
-
-static inline struct vxlanhdr *vxlan_hdr(const struct sk_buff *skb)
-{
- return (struct vxlanhdr *)(udp_hdr(skb) + 1);
-}
-
-static void vxlan_build_header(const struct vport *vport,
- struct sk_buff *skb,
- int tunnel_hlen)
-{
- struct tnl_vport *tnl_vport = tnl_vport_priv(vport);
- struct udphdr *udph = udp_hdr(skb);
- struct vxlanhdr *vxh = (struct vxlanhdr *)(udph + 1);
- const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
-
- udph->dest = tnl_vport->dst_port;
- udph->source = htons(ovs_tnl_get_src_port(skb));
- udph->check = 0;
- udph->len = htons(skb->len - skb_transport_offset(skb));
-
- vxh->vx_flags = htonl(VXLAN_FLAGS);
- vxh->vx_vni = htonl(be64_to_cpu(tun_key->tun_id) << 8);
-
- /*
- * 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);
-}
-
-/* Called with rcu_read_lock and BH disabled. */
-static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
-{
- struct vxlan_port *vxlan_vport;
- struct vxlanhdr *vxh;
- struct iphdr *iph;
- struct ovs_key_ipv4_tunnel tun_key;
- __be64 key;
-
- vxlan_vport = vxlan_find_port(dev_net(skb->dev), udp_hdr(skb)->dest);
- if (unlikely(!vxlan_vport))
- goto error;
-
- if (unlikely(!pskb_may_pull(skb, VXLAN_HLEN + ETH_HLEN)))
- goto error;
-
- vxh = vxlan_hdr(skb);
- if (unlikely(vxh->vx_flags != htonl(VXLAN_FLAGS) ||
- vxh->vx_vni & htonl(0xff)))
- goto error;
-
- __skb_pull(skb, VXLAN_HLEN);
- skb_postpull_rcsum(skb, skb_transport_header(skb), VXLAN_HLEN + ETH_HLEN);
-
- key = cpu_to_be64(ntohl(vxh->vx_vni) >> 8);
-
- /* Save outer tunnel values */
- iph = ip_hdr(skb);
- tnl_tun_key_init(&tun_key, iph, key, OVS_TNL_F_KEY);
- OVS_CB(skb)->tun_key = &tun_key;
-
- ovs_tnl_rcv(vxlan_vport->vport, skb);
- goto out;
-
-error:
- kfree_skb(skb);
-out: