dataoath: compat: Do not use upstream fill-meta-data function for compat tunnel
[cascardo/ovs.git] / datapath / linux / compat / lisp.c
index f1f50ae..dd23059 100644 (file)
@@ -207,11 +207,12 @@ static void lisp_build_header(struct sk_buff *skb,
 /* Called with rcu_read_lock and BH disabled. */
 static int lisp_rcv(struct sock *sk, struct sk_buff *skb)
 {
+       struct lisp_dev *lisp_dev;
        struct net_device *dev;
        struct lisphdr *lisph;
        struct iphdr *inner_iph;
        struct metadata_dst *tun_dst;
-#ifndef HAVE_METADATA_DST
+#ifndef USE_UPSTREAM_TUNNEL
        struct metadata_dst temp;
 #endif
        __be64 key;
@@ -222,7 +223,9 @@ static int lisp_rcv(struct sock *sk, struct sk_buff *skb)
        if (unlikely(!dev))
                goto error;
 
-       if (iptunnel_pull_header(skb, LISP_HLEN, 0))
+       lisp_dev = netdev_priv(dev);
+       if (iptunnel_pull_header(skb, LISP_HLEN, 0,
+                                !net_eq(lisp_dev->net, dev_net(lisp_dev->dev))))
                goto error;
 
        lisph = lisp_hdr(skb);
@@ -233,9 +236,9 @@ static int lisp_rcv(struct sock *sk, struct sk_buff *skb)
                key = instance_id_to_tunnel_id(&lisph->u2.word2.instance_id[0]);
 
        /* Save outer tunnel values */
-#ifndef HAVE_METADATA_DST
+#ifndef USE_UPSTREAM_TUNNEL
        tun_dst = &temp;
-       ovs_udp_tun_rx_dst(&tun_dst->u.tun_info, skb, AF_INET, TUNNEL_KEY, key, 0);
+       ovs_udp_tun_rx_dst(tun_dst, skb, AF_INET, TUNNEL_KEY, key, 0);
 #else
        tun_dst = udp_tun_rx_dst(skb, AF_INET, TUNNEL_KEY, key, 0);
 #endif
@@ -269,6 +272,24 @@ out:
        return 0;
 }
 
+static struct rtable *lisp_get_rt(struct sk_buff *skb,
+                                struct net_device *dev,
+                                struct flowi4 *fl,
+                                const struct ip_tunnel_key *key)
+{
+       struct net *net = dev_net(dev);
+
+       /* Route lookup */
+       memset(fl, 0, sizeof(*fl));
+       fl->daddr = key->u.ipv4.dst;
+       fl->saddr = key->u.ipv4.src;
+       fl->flowi4_tos = RT_TOS(key->tos);
+       fl->flowi4_mark = skb->mark;
+       fl->flowi4_proto = IPPROTO_UDP;
+
+       return ip_route_output_key(net, fl);
+}
+
 netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
@@ -298,14 +319,7 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb)
 
        tun_key = &info->key;
 
-       /* Route lookup */
-       memset(&fl, 0, sizeof(fl));
-       fl.daddr = tun_key->u.ipv4.dst;
-       fl.saddr = tun_key->u.ipv4.src;
-       fl.flowi4_tos = RT_TOS(tun_key->tos);
-       fl.flowi4_mark = skb->mark;
-       fl.flowi4_proto = IPPROTO_UDP;
-       rt = ip_route_output_key(net, &fl);
+       rt = lisp_get_rt(skb, dev, &fl, tun_key);
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
                goto error;
@@ -330,12 +344,9 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb)
        skb_reset_mac_header(skb);
        skb->vlan_tci = 0;
 
-       skb = udp_tunnel_handle_offloads(skb, false, 0, false);
-       if (IS_ERR(skb)) {
-               err = PTR_ERR(skb);
-               skb = NULL;
+       err = udp_tunnel_handle_offloads(skb, false, false);
+       if (err)
                goto err_free_rt;
-       }
 
        src_port = htons(get_src_port(net, skb));
        dst_port = lisp_dev->dst_port;
@@ -347,12 +358,11 @@ netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb)
        ovs_skb_set_inner_protocol(skb, skb->protocol);
 
        df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
-       err = udp_tunnel_xmit_skb(rt, lisp_dev->sock->sk, skb,
-                       fl.saddr, tun_key->u.ipv4.dst,
-                       tun_key->tos, tun_key->ttl,
-                       df, src_port, dst_port, false, true);
+       udp_tunnel_xmit_skb(rt, lisp_dev->sock->sk, skb,
+                           fl.saddr, tun_key->u.ipv4.dst,
+                           tun_key->tos, tun_key->ttl,
+                           df, src_port, dst_port, false, true);
 
-       iptunnel_xmit_stats(err, &dev->stats, (struct pcpu_sw_netstats __percpu *)dev->tstats);
        return NETDEV_TX_OK;
 
 err_free_rt:
@@ -434,7 +444,7 @@ static int lisp_stop(struct net_device *dev)
 
 static netdev_tx_t lisp_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-#ifdef HAVE_METADATA_DST
+#ifdef USE_UPSTREAM_TUNNEL
        return rpl_lisp_xmit(skb);
 #else
        /* Drop All packets coming from networking stack. OVS-CB is
@@ -456,6 +466,40 @@ static int lisp_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
+static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
+                               struct ip_tunnel_info *info,
+                               __be16 sport, __be16 dport)
+{
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       rt = lisp_get_rt(skb, dev, &fl4, &info->key);
+       if (IS_ERR(rt))
+               return PTR_ERR(rt);
+       ip_rt_put(rt);
+
+       info->key.u.ipv4.src = fl4.saddr;
+       info->key.tp_src = sport;
+       info->key.tp_dst = dport;
+       return 0;
+}
+
+int ovs_lisp_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct lisp_dev *lisp = netdev_priv(dev);
+       struct net *net = lisp->net;
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       __be16 sport, dport;
+
+       sport = htons(get_src_port(net, skb));
+       dport = lisp->dst_port;
+
+       if (ip_tunnel_info_af(info) == AF_INET)
+               return egress_ipv4_tun_info(dev, skb, info, sport, dport);
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(ovs_lisp_fill_metadata_dst);
+
 static const struct net_device_ops lisp_netdev_ops = {
        .ndo_init               = lisp_init,
        .ndo_uninit             = lisp_uninit,
@@ -466,6 +510,11 @@ static const struct net_device_ops lisp_netdev_ops = {
        .ndo_change_mtu         = lisp_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
+#ifdef USE_UPSTREAM_TUNNEL
+#ifdef HAVE_NDO_FILL_METADATA_DST
+       .ndo_fill_metadata_dst  = lisp_fill_metadata_dst,
+#endif
+#endif
 };
 
 static void lisp_get_drvinfo(struct net_device *dev,
@@ -505,7 +554,7 @@ static void lisp_setup(struct net_device *dev)
        dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
        dev->hw_features |= NETIF_F_GSO_SOFTWARE;
 #endif
-#ifdef HAVE_METADATA_DST
+#ifdef USE_UPSTREAM_TUNNEL
        netif_keep_dst(dev);
 #endif
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;