LISP can also take advantage of setup_udp_tunnel_sock() and
udp_tunnel_xmit_skb() to increase code reuse.

Signed-off-by: Jesse Gross <je...@nicira.com>
---
 datapath/vport-lisp.c | 101 +++++++++++++-------------------------------------
 1 file changed, 26 insertions(+), 75 deletions(-)

diff --git a/datapath/vport-lisp.c b/datapath/vport-lisp.c
index 10369dc..29a1afc 100644
--- a/datapath/vport-lisp.c
+++ b/datapath/vport-lisp.c
@@ -176,12 +176,12 @@ static u16 get_src_port(struct net *net, struct sk_buff 
*skb)
                        struct iphdr *iph;
                        int size = (sizeof(iph->saddr) * 2) / sizeof(u32);
 
-                       iph = (struct iphdr *) skb_inner_network_header(skb);
+                       iph = (struct iphdr *) skb_network_header(skb);
                        hash = jhash2((const u32 *)&iph->saddr, size, 0);
                } else if (skb->protocol == htons(ETH_P_IPV6)) {
                        struct ipv6hdr *ipv6hdr;
 
-                       ipv6hdr = (struct ipv6hdr *) 
skb_inner_network_header(skb);
+                       ipv6hdr = (struct ipv6hdr *) skb_network_header(skb);
                        hash = jhash2((const u32 *)&ipv6hdr->saddr,
                                      (sizeof(struct in6_addr) * 2) / 
sizeof(u32), 0);
                } else {
@@ -195,21 +195,14 @@ static u16 get_src_port(struct net *net, struct sk_buff 
*skb)
        return (((u64) hash * range) >> 32) + low;
 }
 
-static void lisp_build_header(const struct vport *vport,
-                             struct sk_buff *skb)
+static void lisp_build_header(struct sk_buff *skb)
 {
-       struct net *net = ovs_dp_get_net(vport->dp);
-       struct lisp_port *lisp_port = lisp_vport(vport);
-       struct udphdr *udph = udp_hdr(skb);
-       struct lisphdr *lisph = (struct lisphdr *)(udph + 1);
+       struct lisphdr *lisph;
        const struct ovs_key_ipv4_tunnel *tun_key;
 
        tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
-       udph->dest = lisp_port->dst_port;
-       udph->source = htons(get_src_port(net, skb));
-       udph->check = 0;
-       udph->len = htons(skb->len - skb_transport_offset(skb));
 
+       lisph = (struct lisphdr *)__skb_push(skb, sizeof(struct lisphdr));
        lisph->nonce_present = 0;       /* We don't support echo nonce 
algorithm */
        lisph->locator_status_bits_present = 1; /* Set LSB */
        lisph->solicit_echo_nonce = 0;  /* No echo noncing */
@@ -236,7 +229,7 @@ static int lisp_rcv(struct sock *sk, struct sk_buff *skb)
        struct ethhdr *ethh;
        __be16 protocol;
 
-       lisp_port = lisp_find_port(dev_net(skb->dev), udp_hdr(skb)->dest);
+       lisp_port = rcu_dereference_sk_user_data(sk);
        if (unlikely(!lisp_port))
                goto error;
 
@@ -288,11 +281,10 @@ out:
        return 0;
 }
 
-/* Arbitrary value.  Irrelevant as long as it's not 0 since we set the 
handler. */
-#define UDP_ENCAP_LISP 1
 static int lisp_socket_init(struct lisp_port *lisp_port, struct net *net)
 {
        struct udp_port_cfg udp_conf;
+       struct udp_tunnel_sock_cfg tunnel_cfg;
        int err;
 
        memset(&udp_conf, 0, sizeof(udp_conf));
@@ -307,10 +299,12 @@ static int lisp_socket_init(struct lisp_port *lisp_port, 
struct net *net)
                 return err;
        }
 
-       udp_sk(lisp_port->lisp_rcv_socket->sk)->encap_type = UDP_ENCAP_LISP;
-       udp_sk(lisp_port->lisp_rcv_socket->sk)->encap_rcv = lisp_rcv;
+       tunnel_cfg.sk_user_data = lisp_port;
+       tunnel_cfg.encap_type = 1;
+       tunnel_cfg.encap_rcv = lisp_rcv;
+       tunnel_cfg.encap_destroy = NULL;
 
-       udp_encap_enable();
+       setup_udp_tunnel_sock(net, lisp_port->lisp_rcv_socket, &tunnel_cfg);
 
        return 0;
 }
@@ -329,9 +323,7 @@ static void lisp_tnl_destroy(struct vport *vport)
        struct lisp_port *lisp_port = lisp_vport(vport);
 
        list_del_rcu(&lisp_port->list);
-       /* Release socket */
-       sk_release_kernel(lisp_port->lisp_rcv_socket->sk);
-
+       udp_tunnel_sock_release(lisp_port->lisp_rcv_socket);
        ovs_vport_deferred_free(vport);
 }
 
@@ -387,54 +379,16 @@ error:
        return ERR_PTR(err);
 }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,12,0)
-
-static void lisp_fix_segment(struct sk_buff *skb)
-{
-       struct udphdr *udph = udp_hdr(skb);
-
-       udph->len = htons(skb->len - skb_transport_offset(skb));
-}
-
-static struct sk_buff *handle_offloads(struct sk_buff *skb)
-{
-       return ovs_iptunnel_handle_offloads(skb, false, lisp_fix_segment);
-}
-#else
-static struct sk_buff *handle_offloads(struct sk_buff *skb)
-{
-       int err = 0;
-
-       if (skb_is_gso(skb)) {
-
-               if (skb_is_encapsulated(skb)) {
-                       err = -ENOSYS;
-                       goto error;
-               }
-
-               err = skb_unclone(skb, GFP_ATOMIC);
-               if (unlikely(err))
-                       goto error;
-
-               skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL;
-       } else if (skb->ip_summed != CHECKSUM_PARTIAL)
-               skb->ip_summed = CHECKSUM_NONE;
-
-       skb->encapsulation = 1;
-       return skb;
-error:
-       kfree_skb(skb);
-       return ERR_PTR(err);
-}
-#endif
-
 static int lisp_send(struct vport *vport, struct sk_buff *skb)
 {
        struct ovs_key_ipv4_tunnel *tun_key;
+       struct lisp_port *lisp_port = lisp_vport(vport);
+       struct net *net = ovs_dp_get_net(vport->dp);
        int network_offset = skb_network_offset(skb);
        struct rtable *rt;
        int min_headroom;
        __be32 saddr;
+       __be16 src_port, dst_port;
        __be16 df;
        int sent_len;
        int err;
@@ -482,30 +436,27 @@ static int lisp_send(struct vport *vport, struct sk_buff 
*skb)
        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 */
-       skb = handle_offloads(skb);
+       skb = udp_tunnel_handle_offloads(skb, false, false);
        if (IS_ERR(skb)) {
                err = PTR_ERR(skb);
                skb = NULL;
                goto err_free_rt;
        }
 
+       src_port = htons(get_src_port(net, skb));
+       dst_port = lisp_port->dst_port;
+
+       lisp_build_header(skb);
+
        skb->ignore_df = 1;
 
        ovs_skb_set_inner_protocol(skb, skb->protocol);
 
        df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
-       sent_len = iptunnel_xmit(skb->sk, rt, skb,
-                            saddr, tun_key->ipv4_dst,
-                            IPPROTO_UDP, tun_key->ipv4_tos,
-                            tun_key->ipv4_ttl, df, false);
+       sent_len = udp_tunnel_xmit_skb(lisp_port->lisp_rcv_socket, rt, skb,
+                                      saddr, tun_key->ipv4_dst,
+                                      tun_key->ipv4_tos, tun_key->ipv4_ttl,
+                                      df, src_port, dst_port, false);
 
        return sent_len > 0 ? sent_len + network_offset : sent_len;
 
-- 
1.9.1

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

Reply via email to