]> git.proxmox.com Git - mirror_ovs.git/commitdiff
datapath: compat: Refactor egress tunnel info
authorPravin B Shelar <pshelar@ovn.org>
Fri, 8 Jul 2016 02:35:33 +0000 (19:35 -0700)
committerPravin B Shelar <pshelar@ovn.org>
Sat, 9 Jul 2016 02:27:48 +0000 (19:27 -0700)
upstream tunnel egress info is retrieved using ndo_fill_metadata_dst.
Since we do not have it on older kernel we need to keep vport operation
to do same on these kernels.
Following patch try to merge these to operations into one to avoid code
duplication.
This commit backports fc4099f1 ("openvswitch:
Fix egress tunnel info.")

Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
Acked-by: Jesse Gross <jesse@kernel.org>
26 files changed:
acinclude.m4
datapath/actions.c
datapath/datapath.c
datapath/datapath.h
datapath/flow_netlink.c
datapath/flow_netlink.h
datapath/linux/compat/dev-openvswitch.c
datapath/linux/compat/geneve.c
datapath/linux/compat/gso.h
datapath/linux/compat/include/linux/netdevice.h
datapath/linux/compat/include/net/geneve.h
datapath/linux/compat/include/net/gre.h
datapath/linux/compat/include/net/lisp.h
datapath/linux/compat/include/net/stt.h
datapath/linux/compat/include/net/vxlan.h
datapath/linux/compat/ip_gre.c
datapath/linux/compat/lisp.c
datapath/linux/compat/stt.c
datapath/linux/compat/vxlan.c
datapath/vport-geneve.c
datapath/vport-gre.c
datapath/vport-lisp.c
datapath/vport-stt.c
datapath/vport-vxlan.c
datapath/vport.c
datapath/vport.h

index 0de940b144a987780335d231223e9fd4efcb5d99..7f96be1f7452619f0f36c6d82a039e352a8b7101 100644 (file)
@@ -436,6 +436,7 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
 
   OVS_GREP_IFELSE([$KSRC/include/linux/net.h], [sock_create_kern.*net],
                   [OVS_DEFINE([HAVE_SOCK_CREATE_KERN_NET])])
+  OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [ndo_fill_metadata_dst])
   OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_disable_lro])
   OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_get_stats])
   OVS_GREP_IFELSE([$KSRC/include/linux/netdevice.h], [dev_get_by_index_rcu])
index 7ef1baeee42cf1e61870c1894d0bc7f313a4e6de..757a8f684cbdf1de67be97b1a37a17ef40f3522e 100644 (file)
@@ -775,20 +775,21 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
                kfree_skb(skb);
        }
 }
+
 static int output_userspace(struct datapath *dp, struct sk_buff *skb,
                            struct sw_flow_key *key, const struct nlattr *attr,
                            const struct nlattr *actions, int actions_len,
                            uint32_t cutlen)
 {
-       struct ip_tunnel_info info;
        struct dp_upcall_info upcall;
        const struct nlattr *a;
-       int rem;
+       int rem, err;
 
        memset(&upcall, 0, sizeof(upcall));
        upcall.cmd = OVS_PACKET_CMD_ACTION;
        upcall.mru = OVS_CB(skb)->mru;
 
+       SKB_INIT_FILL_METADATA_DST(skb);
        for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
                 a = nla_next(a, &rem)) {
                switch (nla_type(a)) {
@@ -808,11 +809,9 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
                        if (vport) {
                                int err;
 
-                               upcall.egress_tun_info = &info;
-                               err = ovs_vport_get_egress_tun_info(vport, skb,
-                                                                   &upcall);
-                               if (err)
-                                       upcall.egress_tun_info = NULL;
+                               err = dev_fill_metadata_dst(vport->dev, skb);
+                               if (!err)
+                                       upcall.egress_tun_info = skb_tunnel_info(skb);
                        }
 
                        break;
@@ -828,7 +827,9 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
                } /* End of switch. */
        }
 
-       return ovs_dp_upcall(dp, skb, key, &upcall, cutlen);
+       err = ovs_dp_upcall(dp, skb, key, &upcall, cutlen);
+       SKB_RESTORE_FILL_METADATA_DST(skb);
+       return err;
 }
 
 static int sample(struct datapath *dp, struct sk_buff *skb,
index b02807e714772996d3f7387acc723664f707c770..2540df1a5d0a245627cb8f3629385c92451e4493 100644 (file)
@@ -503,9 +503,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 
        if (upcall_info->egress_tun_info) {
                nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY);
-               err = ovs_nla_put_egress_tunnel_key(user_skb,
-                                                   upcall_info->egress_tun_info,
-                                                   upcall_info->egress_tun_opts);
+               err = ovs_nla_put_tunnel_info(user_skb,
+                                             upcall_info->egress_tun_info);
                BUG_ON(err);
                nla_nest_end(user_skb, nla);
        }
index a70123c1a87bbcd10e5105aaba3df608dc65012e..f1607ab22fdc9600755bf7c14057897fac8ea8e4 100644 (file)
@@ -120,7 +120,6 @@ struct ovs_skb_cb {
  */
 struct dp_upcall_info {
        struct ip_tunnel_info *egress_tun_info;
-       const void *egress_tun_opts;
        const struct nlattr *userdata;
        const struct nlattr *actions;
        int actions_len;
index 1defb112775cbe642896ac8044e619779c41ca48..a6e1f3207665c970334b6aa26ec7012529ea02c0 100644 (file)
@@ -719,7 +719,7 @@ static int __ipv4_tun_to_nlattr(struct sk_buff *skb,
        if ((output->tun_flags & TUNNEL_OAM) &&
            nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
                return -EMSGSIZE;
-       if (tun_opts) {
+       if (swkey_tun_opts_len) {
                if (output->tun_flags & TUNNEL_GENEVE_OPT &&
                    nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
                            swkey_tun_opts_len, tun_opts))
@@ -751,13 +751,12 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
        return 0;
 }
 
-int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb,
-                                 const struct ip_tunnel_info *egress_tun_info,
-                                 const void *egress_tun_opts)
+int ovs_nla_put_tunnel_info(struct sk_buff *skb,
+                           struct ip_tunnel_info *tun_info)
 {
-       return __ipv4_tun_to_nlattr(skb, &egress_tun_info->key,
-                                   egress_tun_opts,
-                                   egress_tun_info->options_len);
+       return __ipv4_tun_to_nlattr(skb, &tun_info->key,
+                                   ip_tunnel_info_opts(tun_info),
+                                   tun_info->options_len);
 }
 
 static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
@@ -2399,10 +2398,7 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
                if (!start)
                        return -EMSGSIZE;
 
-               err = ipv4_tun_to_nlattr(skb, &tun_info->key,
-                                        tun_info->options_len ?
-                                            ip_tunnel_info_opts(tun_info) : NULL,
-                                        tun_info->options_len);
+               err = ovs_nla_put_tunnel_info(skb, tun_info);
                if (err)
                        return err;
                nla_nest_end(skb, start);
index 1c01755e799f948d8433f25c5a7f8b4e3302f1e1..1c4208bcb9d4b6e8e5ae276611fe98a44395f0ac 100644 (file)
@@ -55,9 +55,8 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb);
 int ovs_nla_get_match(struct net *, struct sw_flow_match *,
                      const struct nlattr *key, const struct nlattr *mask,
                      bool log);
-int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb,
-                                 const struct ip_tunnel_info *egress_tun_info,
-                                 const void *egress_tun_opts);
+int ovs_nla_put_tunnel_info(struct sk_buff *skb,
+                           struct ip_tunnel_info *tun_info);
 
 bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log);
 int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid,
index 0d2088b38f3adf85e0ac926e31d94f8298dbd975..1e870431f683ec12599b72d7fc90dbeeeb680711 100644 (file)
@@ -3,6 +3,11 @@
 #include <linux/version.h>
 #include <net/rtnetlink.h>
 
+#include "gso.h"
+#include "vport.h"
+#include "vport-internal_dev.h"
+#include "vport-netdev.h"
+
 #ifndef HAVE_DEV_DISABLE_LRO
 
 #ifdef NETIF_F_LRO
@@ -54,3 +59,30 @@ int rpl_rtnl_delete_link(struct net_device *dev)
 #endif
        return 0;
 }
+
+#ifndef HAVE_NDO_FILL_METADATA_DST
+int ovs_dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info;
+       struct vport *vport;
+
+       if (!SKB_SETUP_FILL_METADATA_DST(skb))
+               return -ENOMEM;
+
+       vport = ovs_netdev_get_vport(dev);
+       if (!vport)
+               return -EINVAL;
+
+       if (!vport->ops->fill_metadata_dst)
+               return -EINVAL;
+
+       info = skb_tunnel_info(skb);
+       if (!info)
+               return -ENOMEM;
+       if (unlikely(!(info->mode & IP_TUNNEL_INFO_TX)))
+               return -EINVAL;
+
+       return vport->ops->fill_metadata_dst(dev, skb);
+}
+EXPORT_SYMBOL_GPL(ovs_dev_fill_metadata_dst);
+#endif
index 0399de7066370cbcc94bfa54f8a9ac136ee4341e..05404948524aa76efe34344e1c5bc7721a6170e7 100644 (file)
@@ -615,14 +615,12 @@ static struct rtable *geneve_get_rt(struct sk_buff *skb,
        rt = ip_route_output_key(geneve->net, fl4);
        if (IS_ERR(rt)) {
                netdev_dbg(dev, "no route to %pI4\n", &fl4->daddr);
-               dev->stats.tx_carrier_errors++;
-               return rt;
+               return ERR_PTR(-ENETUNREACH);
        }
        if (rt->dst.dev == dev) { /* is this necessary? */
                netdev_dbg(dev, "circular route to %pI4\n", &fl4->daddr);
-               dev->stats.collisions++;
                ip_rt_put(rt);
-               return ERR_PTR(-EINVAL);
+               return ERR_PTR(-ELOOP);
        }
        return rt;
 }
@@ -649,12 +647,12 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb)
        struct ip_tunnel_info *info = NULL;
        struct rtable *rt = NULL;
        const struct iphdr *iip; /* interior IP header */
+       int err = -EINVAL;
        struct flowi4 fl4;
        __u8 tos, ttl;
        __be16 sport;
        bool udp_csum;
        __be16 df;
-       int err;
 
        if (geneve->collect_md) {
                info = skb_tunnel_info(skb);
@@ -669,7 +667,7 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb)
        rt = geneve_get_rt(skb, dev, &fl4, info);
        if (IS_ERR(rt)) {
                netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr);
-               dev->stats.tx_carrier_errors++;
+               err = PTR_ERR(rt);
                goto tx_error;
        }
 
@@ -721,7 +719,12 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb)
 tx_error:
        dev_kfree_skb(skb);
 err:
-       dev->stats.tx_errors++;
+       if (err == -ELOOP)
+               dev->stats.collisions++;
+       else if (err == -ENETUNREACH)
+               dev->stats.tx_carrier_errors++;
+       else
+               dev->stats.tx_errors++;
        return NETDEV_TX_OK;
 }
 EXPORT_SYMBOL(rpl_geneve_xmit);
@@ -765,6 +768,29 @@ static int geneve_change_mtu(struct net_device *dev, int new_mtu)
        return __geneve_change_mtu(dev, new_mtu, true);
 }
 
+int ovs_geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       struct geneve_dev *geneve = netdev_priv(dev);
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       if (ip_tunnel_info_af(info) != AF_INET)
+               return -EINVAL;
+
+       rt = geneve_get_rt(skb, dev, &fl4, info);
+       if (IS_ERR(rt))
+               return PTR_ERR(rt);
+
+       ip_rt_put(rt);
+       info->key.u.ipv4.src = fl4.saddr;
+       info->key.tp_src = udp_flow_src_port(geneve->net, skb,
+                                            1, USHRT_MAX, true);
+       info->key.tp_dst = geneve->dst_port;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ovs_geneve_fill_metadata_dst);
+
 static const struct net_device_ops geneve_netdev_ops = {
        .ndo_init               = geneve_init,
        .ndo_uninit             = geneve_uninit,
@@ -775,6 +801,9 @@ static const struct net_device_ops geneve_netdev_ops = {
        .ndo_change_mtu         = geneve_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
+#ifdef HAVE_NDO_FILL_METADATA_DST
+       .ndo_fill_metadata_dst  = geneve_fill_metadata_dst,
+#endif
 };
 
 static void geneve_get_drvinfo(struct net_device *dev,
index 0f2b09a9ace95e86314369a151192257b61eea75..7a20942a50550bbe3a37c210e7990f63741625bf 100644 (file)
@@ -23,6 +23,11 @@ struct ovs_gso_cb {
 #ifndef HAVE_INNER_NETWORK_HEADER
        unsigned int    inner_network_header;
 #endif
+#ifndef HAVE_NDO_FILL_METADATA_DST
+       /* Keep original tunnel info during userspace action execution. */
+       struct metadata_dst *fill_md_dst;
+#endif
+
 };
 #define OVS_GSO_CB(skb) ((struct ovs_gso_cb *)(skb)->cb)
 
@@ -197,4 +202,44 @@ static inline void ovs_dst_release(struct dst_entry *dst)
 #define ovs_dst_release dst_release
 #endif
 
+#ifndef HAVE_NDO_FILL_METADATA_DST
+#define SKB_INIT_FILL_METADATA_DST(skb)        OVS_GSO_CB(skb)->fill_md_dst = NULL;
+
+#define SKB_RESTORE_FILL_METADATA_DST(skb)     do {                    \
+       if (OVS_GSO_CB(skb)->fill_md_dst) {                                     \
+               kfree(OVS_GSO_CB(skb)->tun_dst);                        \
+               OVS_GSO_CB(skb)->tun_dst = OVS_GSO_CB(skb)->fill_md_dst;        \
+       }                                                               \
+} while (0)
+
+
+#define SKB_SETUP_FILL_METADATA_DST(skb) ({                    \
+       struct metadata_dst *new_md_dst;                        \
+       struct metadata_dst *md_dst;                            \
+       int md_size;                                            \
+       int ret = 1;                                            \
+                                                               \
+       SKB_RESTORE_FILL_METADATA_DST(skb);                     \
+       new_md_dst = kmalloc(sizeof(struct metadata_dst) + 256, GFP_ATOMIC); \
+       if (new_md_dst) {                                               \
+               md_dst = OVS_GSO_CB(skb)->tun_dst;                      \
+               md_size = new_md_dst->u.tun_info.options_len;           \
+               memcpy(&new_md_dst->u.tun_info, &md_dst->u.tun_info,    \
+                       sizeof(struct ip_tunnel_info) + md_size);       \
+                                                                       \
+               OVS_GSO_CB(skb)->fill_md_dst = md_dst;                          \
+               OVS_GSO_CB(skb)->tun_dst = new_md_dst;                  \
+               ret = 1;                                                \
+       } else {                                                        \
+               ret = 0;                                                \
+       }                                                               \
+       ret;                                                            \
+})
+
+#else
+#define SKB_INIT_FILL_METADATA_DST(skb)                do {} while(0)
+#define SKB_SETUP_FILL_METADATA_DST(skb)       (true)
+#define SKB_RESTORE_FILL_METADATA_DST(skb)     do {} while(0)
+#endif
+
 #endif
index e9fa9957906a7a70bb64af6b17f5ace2914a7c95..ac612efee4edd319f4f0e271d8984995ce952335 100644 (file)
@@ -249,4 +249,8 @@ do {                                                                \
 
 #endif
 
+#ifndef HAVE_NDO_FILL_METADATA_DST
+#define dev_fill_metadata_dst ovs_dev_fill_metadata_dst
+int ovs_dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
+#endif
 #endif /* __LINUX_NETDEVICE_WRAPPER_H */
index 550f4a77eb78b3c9b13110b5da0f8d8f22c91541..a7f22526e355ad910c20e168ce7bd10c81851dfc 100644 (file)
@@ -91,4 +91,7 @@ netdev_tx_t rpl_geneve_xmit(struct sk_buff *skb);
 #define geneve_init_module rpl_geneve_init_module
 #define geneve_cleanup_module rpl_geneve_cleanup_module
 
+#define geneve_fill_metadata_dst ovs_geneve_fill_metadata_dst
+int ovs_geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
+
 #endif /*ifdef__NET_GENEVE_H */
index 60618df9ed704591796b2e122af7586fba0fdb3d..8082a98538f07aa1797d9be3ed2c65a093507f45 100644 (file)
@@ -66,4 +66,7 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb);
 #define ipgre_init rpl_ipgre_init
 #define ipgre_fini rpl_ipgre_fini
 
+#define gre_fill_metadata_dst ovs_gre_fill_metadata_dst
+int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
+
 #endif
index b8af17dbb9ee8b8b2473cb16ed6e5592836ebd88..6b43c77e2ab6a298648a2d66ee2712c50474f4cb 100644 (file)
@@ -21,4 +21,7 @@ void rpl_lisp_cleanup_module(void);
 #define lisp_xmit rpl_lisp_xmit
 netdev_tx_t rpl_lisp_xmit(struct sk_buff *skb);
 
+#define lisp_fill_metadata_dst ovs_lisp_fill_metadata_dst
+int ovs_lisp_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
+
 #endif /*ifdef__NET_LISP_H */
index 28d4dc53c06158d33bfd191dd8fbc0ac9d44747b..d2e63d16307a65a4c60924cb6552dda02e075e0e 100644 (file)
@@ -64,4 +64,7 @@ static inline netdev_tx_t ovs_stt_xmit(struct sk_buff *skb)
 #define stt_init_module ovs_stt_init_module
 #define stt_cleanup_module ovs_stt_cleanup_module
 
+#define stt_fill_metadata_dst ovs_stt_fill_metadata_dst
+int ovs_stt_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
+
 #endif /*ifdef__NET_STT_H */
index 75a5a7acdf8dc16cb5f80ec62bfd349f34154c9f..589e6f2590efe8e243e92ee81ae50cff2be59f45 100644 (file)
@@ -274,4 +274,6 @@ netdev_tx_t rpl_vxlan_xmit(struct sk_buff *skb);
 #define vxlan_init_module rpl_vxlan_init_module
 #define vxlan_cleanup_module rpl_vxlan_cleanup_module
 
+#define vxlan_fill_metadata_dst ovs_vxlan_fill_metadata_dst
+int ovs_vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
 #endif
index 2e1384348718ac1a424089377efd733a6acb7e50..67db9af731c0655dd9c047e9941a7cc4b2ecb6b3 100644 (file)
@@ -256,11 +256,26 @@ static void build_header(struct sk_buff *skb, int hdr_len, __be16 flags,
        ovs_skb_set_inner_protocol(skb, proto);
 }
 
+static struct rtable *gre_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);
+
+       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_GRE;
+
+       return ip_route_output_key(net, fl);
+}
 
 netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
-       struct net *net = dev_net(dev);
        struct ip_tunnel_info *tun_info;
        const struct ip_tunnel_key *key;
        struct flowi4 fl;
@@ -276,14 +291,8 @@ netdev_tx_t rpl_gre_fb_xmit(struct sk_buff *skb)
                goto err_free_skb;
 
        key = &tun_info->key;
-       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_GRE;
-
-       rt = ip_route_output_key(net, &fl);
+
+       rt = gre_get_rt(skb, dev, &fl, key);
        if (IS_ERR(rt))
                goto err_free_skb;
 
@@ -459,6 +468,25 @@ static netdev_tx_t gre_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
+int ovs_gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       if (ip_tunnel_info_af(info) != AF_INET)
+               return -EINVAL;
+
+       rt = gre_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;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ovs_gre_fill_metadata_dst);
+
 static const struct net_device_ops gre_tap_netdev_ops = {
        .ndo_init               = gre_tap_init,
        .ndo_uninit             = ip_tunnel_uninit,
@@ -472,6 +500,9 @@ static const struct net_device_ops gre_tap_netdev_ops = {
 #ifdef HAVE_NDO_GET_IFLINK
        .ndo_get_iflink         = ip_tunnel_get_iflink,
 #endif
+#ifdef HAVE_NDO_FILL_METADATA_DST
+       .ndo_fill_metadata_dst  = gre_fill_metadata_dst,
+#endif
 };
 
 static void ipgre_tap_setup(struct net_device *dev)
index f1f50aea58127213be4ebf84e905f5008c773e45..ae3e5f37b4c6017fb2a01c86490fddd237dce60d 100644 (file)
@@ -269,6 +269,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 +316,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;
@@ -456,6 +467,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 +511,9 @@ 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 HAVE_NDO_FILL_METADATA_DST
+       .ndo_fill_metadata_dst  = lisp_fill_metadata_dst,
+#endif
 };
 
 static void lisp_get_drvinfo(struct net_device *dev,
index 86d225e868f932e72e2b6278f6b90d963d836598..0bdd4db49a8bdc3b6de28ef75095b2f6ac5d9017 100644 (file)
@@ -980,6 +980,24 @@ err_free_rt:
        return ret;
 }
 
+static struct rtable *stt_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_TCP;
+
+       return ip_route_output_key(net, fl);
+}
+
 netdev_tx_t ovs_stt_xmit(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
@@ -1002,14 +1020,7 @@ netdev_tx_t ovs_stt_xmit(struct sk_buff *skb)
 
        tun_key = &tun_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_TCP;
-       rt = ip_route_output_key(net, &fl);
+       rt = stt_get_rt(skb, dev, &fl, tun_key);
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
                goto error;
@@ -1802,6 +1813,31 @@ static int stt_change_mtu(struct net_device *dev, int new_mtu)
        return __stt_change_mtu(dev, new_mtu, true);
 }
 
+int ovs_stt_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       struct stt_dev *stt_dev = netdev_priv(dev);
+       struct net *net = stt_dev->net;
+       __be16 dport = stt_dev->dst_port;
+       struct flowi4 fl4;
+       struct rtable *rt;
+
+       if (ip_tunnel_info_af(info) != AF_INET)
+               return -EINVAL;
+
+       rt = stt_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 = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
+       info->key.tp_dst = dport;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ovs_stt_fill_metadata_dst);
+
 static const struct net_device_ops stt_netdev_ops = {
        .ndo_init               = stt_init,
        .ndo_uninit             = stt_uninit,
@@ -1812,6 +1848,9 @@ static const struct net_device_ops stt_netdev_ops = {
        .ndo_change_mtu         = stt_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
+#ifdef HAVE_NDO_FILL_METADATA_DST
+       .ndo_fill_metadata_dst  = stt_fill_metadata_dst,
+#endif
 };
 
 static void stt_get_drvinfo(struct net_device *dev,
index 4faa18f3ee8e07ba45e918c18e44b4e304ee5ecc..b92a9025927ecc88d4374c67c24dbd8ee7a67e8a 100644 (file)
@@ -1648,6 +1648,47 @@ static netdev_tx_t vxlan_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        return NETDEV_TX_OK;
 }
 
+static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
+               struct ip_tunnel_info *info,
+               __be16 sport, __be16 dport)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       memset(&fl4, 0, sizeof(fl4));
+       fl4.flowi4_tos = RT_TOS(info->key.tos);
+       fl4.flowi4_mark = skb->mark;
+       fl4.flowi4_proto = IPPROTO_UDP;
+       fl4.daddr = info->key.u.ipv4.dst;
+
+       rt = ip_route_output_key(vxlan->net, &fl4);
+       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_vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       __be16 sport, dport;
+
+       sport = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
+                       vxlan->cfg.port_max, true);
+       dport = info->key.tp_dst ? : vxlan->cfg.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_vxlan_fill_metadata_dst);
+
 static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_init               = vxlan_init,
        .ndo_uninit             = vxlan_uninit,
@@ -1659,6 +1700,9 @@ static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_change_mtu         = vxlan_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
+#ifdef HAVE_NDO_FILL_METADATA_DST
+       .ndo_fill_metadata_dst  = vxlan_fill_metadata_dst,
+#endif
 };
 
 /* Info for udev, that this is a virtual tunnel endpoint */
index e65e43dd9c7abc02a80511c8a9110e3a0b7c4642..718b077d5bb9a2ae017174e6e1bfad64207aeba3 100644 (file)
@@ -52,18 +52,6 @@ static int geneve_get_options(const struct vport *vport,
        return 0;
 }
 
-static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                     struct dp_upcall_info *upcall)
-{
-       struct geneve_port *geneve_port = geneve_vport(vport);
-       struct net *net = ovs_dp_get_net(vport->dp);
-       __be16 dport = htons(geneve_port->dst_port);
-       __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
-
-       return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
-                                         skb, IPPROTO_UDP, sport, dport);
-}
-
 static struct vport *geneve_tnl_create(const struct vport_parms *parms)
 {
        struct net *net = ovs_dp_get_net(parms->dp);
@@ -128,8 +116,8 @@ static struct vport_ops ovs_geneve_vport_ops = {
        .create         = geneve_create,
        .destroy        = ovs_netdev_tunnel_destroy,
        .get_options    = geneve_get_options,
+       .fill_metadata_dst = geneve_fill_metadata_dst,
        .send           = geneve_xmit,
-       .get_egress_tun_info    = geneve_get_egress_tun_info,
 };
 
 static int __init ovs_geneve_tnl_init(void)
index 50aaba5931405d7f5a7742e8b3d89bb1a3da55e0..ffe0079caa712d9edf0521ef6dd6c327d68c85d9 100644 (file)
@@ -84,18 +84,11 @@ static struct vport *gre_create(const struct vport_parms *parms)
        return ovs_netdev_link(vport, parms->name);
 }
 
-static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                  struct dp_upcall_info *upcall)
-{
-       return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
-                                         skb, IPPROTO_GRE, 0, 0);
-}
-
 static struct vport_ops ovs_gre_vport_ops = {
        .type           = OVS_VPORT_TYPE_GRE,
        .create         = gre_create,
        .send           = gre_fb_xmit,
-       .get_egress_tun_info    = gre_get_egress_tun_info,
+       .fill_metadata_dst = gre_fill_metadata_dst,
        .destroy        = ovs_netdev_tunnel_destroy,
 };
 
index 3ce8613aef1f0f36eb1a3593207ca4c152280526..25f6932d135bccf8b3ae0a22c00267c543f92378 100644 (file)
@@ -52,18 +52,6 @@ static int lisp_get_options(const struct vport *vport,
        return 0;
 }
 
-static int lisp_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                     struct dp_upcall_info *upcall)
-{
-       struct lisp_port *lisp_port = lisp_vport(vport);
-       struct net *net = ovs_dp_get_net(vport->dp);
-       __be16 dport = htons(lisp_port->port_no);
-       __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
-
-       return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
-                                         skb, IPPROTO_UDP, sport, dport);
-}
-
 static struct vport *lisp_tnl_create(const struct vport_parms *parms)
 {
        struct net *net = ovs_dp_get_net(parms->dp);
@@ -128,8 +116,8 @@ static struct vport_ops ovs_lisp_vport_ops = {
        .create         = lisp_create,
        .destroy        = ovs_netdev_tunnel_destroy,
        .get_options    = lisp_get_options,
+       .fill_metadata_dst = lisp_fill_metadata_dst,
        .send           = lisp_xmit,
-       .get_egress_tun_info    = lisp_get_egress_tun_info,
 };
 
 static int __init ovs_lisp_tnl_init(void)
index b8e0c883920f2c455abf8d96476cf44a14e62db6..e46bec15d42005dae9b58d8b54181426921cf7ec 100644 (file)
@@ -54,18 +54,6 @@ static int stt_get_options(const struct vport *vport,
        return 0;
 }
 
-static int stt_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                     struct dp_upcall_info *upcall)
-{
-       struct stt_port *stt_port = stt_vport(vport);
-       struct net *net = ovs_dp_get_net(vport->dp);
-       __be16 dport = htons(stt_port->port_no);
-       __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
-
-       return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
-                                         skb, IPPROTO_UDP, sport, dport);
-}
-
 static struct vport *stt_tnl_create(const struct vport_parms *parms)
 {
        struct net *net = ovs_dp_get_net(parms->dp);
@@ -130,8 +118,8 @@ static struct vport_ops ovs_stt_vport_ops = {
        .create         = stt_create,
        .destroy        = ovs_netdev_tunnel_destroy,
        .get_options    = stt_get_options,
+       .fill_metadata_dst = stt_fill_metadata_dst,
        .send           = ovs_stt_xmit,
-       .get_egress_tun_info    = stt_get_egress_tun_info,
 };
 
 static int __init ovs_stt_tnl_init(void)
index c05f5d447e089e5668aa8c070d70b76bbbff5a9f..37e6da1f7355e36b4a4ca4cddc228b743dd4798f 100644 (file)
@@ -148,31 +148,13 @@ static struct vport *vxlan_create(const struct vport_parms *parms)
        return ovs_netdev_link(vport, parms->name);
 }
 
-static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                    struct dp_upcall_info *upcall)
-{
-       struct vxlan_dev *vxlan = netdev_priv(vport->dev);
-       struct net *net = ovs_dp_get_net(vport->dp);
-       __be16 dst_port = vxlan_dev_dst_port(vxlan);
-       __be16 src_port;
-       int port_min;
-       int port_max;
-
-       inet_get_local_port_range(net, &port_min, &port_max);
-       src_port = udp_flow_src_port(net, skb, 0, 0, true);
-
-       return ovs_tunnel_get_egress_info(upcall, net,
-                                         skb, IPPROTO_UDP,
-                                         src_port, dst_port);
-}
-
 static struct vport_ops ovs_vxlan_netdev_vport_ops = {
        .type                   = OVS_VPORT_TYPE_VXLAN,
        .create                 = vxlan_create,
        .destroy                = ovs_netdev_tunnel_destroy,
        .get_options            = vxlan_get_options,
+       .fill_metadata_dst      = vxlan_fill_metadata_dst,
        .send                   = vxlan_xmit,
-       .get_egress_tun_info    = vxlan_get_egress_tun_info,
 };
 
 static int __init ovs_vxlan_tnl_init(void)
index 3ba4c01a7774b26eab418c0e8729d2ef131a25d7..c29f0b0e5914b08c73ed32fc8acb69152b64f18a 100644 (file)
@@ -33,7 +33,6 @@
 #include <net/lisp.h>
 #include <net/gre.h>
 #include <net/geneve.h>
-#include <net/route.h>
 #include <net/stt.h>
 #include <net/vxlan.h>
 
@@ -526,83 +525,6 @@ void ovs_vport_deferred_free(struct vport *vport)
 }
 EXPORT_SYMBOL_GPL(ovs_vport_deferred_free);
 
-static struct rtable *ovs_tunnel_route_lookup(struct net *net,
-                                             const struct ip_tunnel_key *key,
-                                             u32 mark,
-                                             struct flowi4 *fl,
-                                             u8 protocol)
-{
-       struct rtable *rt;
-
-       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 = mark;
-       fl->flowi4_proto = protocol;
-
-       rt = ip_route_output_key(net, fl);
-       return rt;
-}
-
-int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
-                              struct net *net,
-                              struct sk_buff *skb,
-                              u8 ipproto,
-                              __be16 tp_src,
-                              __be16 tp_dst)
-{
-       struct ip_tunnel_info *egress_tun_info = upcall->egress_tun_info;
-       struct ip_tunnel_info *tun_info = skb_tunnel_info(skb);
-       const struct ip_tunnel_key *tun_key;
-       u32 skb_mark = skb->mark;
-       struct rtable *rt;
-       struct flowi4 fl;
-
-       if (unlikely(!tun_info))
-               return -EINVAL;
-       if (ip_tunnel_info_af(tun_info) != AF_INET)
-               return -EINVAL;
-
-       tun_key = &tun_info->key;
-
-       /* Route lookup to get srouce IP address.
-        * The process may need to be changed if the corresponding process
-        * in vports ops changed.
-        */
-       rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto);
-       if (IS_ERR(rt))
-               return PTR_ERR(rt);
-
-       ip_rt_put(rt);
-
-       /* Generate egress_tun_info based on tun_info,
-        * saddr, tp_src and tp_dst
-        */
-       ip_tunnel_key_init(&egress_tun_info->key,
-                          fl.saddr, tun_key->u.ipv4.dst,
-                          tun_key->tos,
-                          tun_key->ttl,
-                          tp_src, tp_dst,
-                          tun_key->tun_id,
-                          tun_key->tun_flags);
-       egress_tun_info->options_len = tun_info->options_len;
-       egress_tun_info->mode = tun_info->mode;
-       upcall->egress_tun_opts = ip_tunnel_info_opts(tun_info);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ovs_tunnel_get_egress_info);
-
-int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                 struct dp_upcall_info *upcall)
-{
-       /* get_egress_tun_info() is only implemented on tunnel ports. */
-       if (unlikely(!vport->ops->get_egress_tun_info))
-               return -EINVAL;
-
-       return vport->ops->get_egress_tun_info(vport, skb, upcall);
-}
-
 static unsigned int packet_length(const struct sk_buff *skb)
 {
        unsigned int length = skb->len - ETH_HLEN;
index 6e804933bb5af43468b71b8708a5e626157e3897..96a5b2be84f68a76fed112faa58df40673fde81b 100644 (file)
@@ -52,16 +52,6 @@ int ovs_vport_set_upcall_portids(struct vport *, const struct nlattr *pids);
 int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *);
 u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *);
 
-int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
-                              struct net *net,
-                              struct sk_buff *,
-                              u8 ipproto,
-                              __be16 tp_src,
-                              __be16 tp_dst);
-
-int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                 struct dp_upcall_info *upcall);
-
 /**
  * struct vport_portids - array of netlink portids of a vport.
  *                        must be protected by rcu.
@@ -140,8 +130,6 @@ struct vport_parms {
  * have any configuration.
  * @send: Send a packet on the device.
  * zero for dropped packets or negative for error.
- * @get_egress_tun_info: Get the egress tunnel 5-tuple and other info for
- * a packet.
  */
 struct vport_ops {
        enum ovs_vport_type type;
@@ -154,8 +142,7 @@ struct vport_ops {
        int (*get_options)(const struct vport *, struct sk_buff *);
 
        netdev_tx_t (*send)(struct sk_buff *skb);
-       int (*get_egress_tun_info)(struct vport *, struct sk_buff *,
-                                  struct dp_upcall_info *upcall);
+       int  (*fill_metadata_dst)(struct net_device *dev, struct sk_buff *skb);
 
        struct module *owner;
        struct list_head list;