/* Keep error state on tunnel for 30 sec */
 #define IPTUNNEL_ERR_TIMEO     (30*HZ)
 
+/* Used to memset ip_tunnel padding. */
+#define IP_TUNNEL_KEY_SIZE                                     \
+       (offsetof(struct ip_tunnel_key, tp_dst) +               \
+        FIELD_SIZEOF(struct ip_tunnel_key, tp_dst))
+
+struct ip_tunnel_key {
+       __be64                  tun_id;
+       __be32                  ipv4_src;
+       __be32                  ipv4_dst;
+       __be16                  tun_flags;
+       __u8                    ipv4_tos;
+       __u8                    ipv4_ttl;
+       __be16                  tp_src;
+       __be16                  tp_dst;
+} __packed __aligned(4); /* Minimize padding. */
+
+struct ip_tunnel_info {
+       struct ip_tunnel_key    key;
+       const void              *options;
+       u8                      options_len;
+};
+
 /* 6rd prefix/relay information */
 #ifdef CONFIG_IPV6_SIT_6RD
 struct ip_tunnel_6rd_parm {
 int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *op,
                            unsigned int num);
 
+static inline void __ip_tunnel_info_init(struct ip_tunnel_info *tun_info,
+                                        __be32 saddr, __be32 daddr,
+                                        u8 tos, u8 ttl,
+                                        __be16 tp_src, __be16 tp_dst,
+                                        __be64 tun_id, __be16 tun_flags,
+                                        const void *opts, u8 opts_len)
+{
+       tun_info->key.tun_id = tun_id;
+       tun_info->key.ipv4_src = saddr;
+       tun_info->key.ipv4_dst = daddr;
+       tun_info->key.ipv4_tos = tos;
+       tun_info->key.ipv4_ttl = ttl;
+       tun_info->key.tun_flags = tun_flags;
+
+       /* For the tunnel types on the top of IPsec, the tp_src and tp_dst of
+        * the upper tunnel are used.
+        * E.g: GRE over IPSEC, the tp_src and tp_port are zero.
+        */
+       tun_info->key.tp_src = tp_src;
+       tun_info->key.tp_dst = tp_dst;
+
+       /* Clear struct padding. */
+       if (sizeof(tun_info->key) != IP_TUNNEL_KEY_SIZE)
+               memset((unsigned char *)&tun_info->key + IP_TUNNEL_KEY_SIZE,
+                      0, sizeof(tun_info->key) - IP_TUNNEL_KEY_SIZE);
+
+       tun_info->options = opts;
+       tun_info->options_len = opts_len;
+}
+
+static inline void ip_tunnel_info_init(struct ip_tunnel_info *tun_info,
+                                      const struct iphdr *iph,
+                                      __be16 tp_src, __be16 tp_dst,
+                                      __be64 tun_id, __be16 tun_flags,
+                                      const void *opts, u8 opts_len)
+{
+       __ip_tunnel_info_init(tun_info, iph->saddr, iph->daddr,
+                             iph->tos, iph->ttl, tp_src, tp_dst,
+                             tun_id, tun_flags, opts, opts_len);
+}
+
 #ifdef CONFIG_INET
 
 int ip_tunnel_init(struct net_device *dev);
 
                                 * the accepted length of the array. */
 
 #ifdef __KERNEL__
-       OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ovs_tunnel_info */
+       OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
 #endif
        __OVS_KEY_ATTR_MAX
 };
 
                            struct sw_flow_key *key, const struct nlattr *attr,
                            const struct nlattr *actions, int actions_len)
 {
-       struct ovs_tunnel_info info;
+       struct ip_tunnel_info info;
        struct dp_upcall_info upcall;
        const struct nlattr *a;
        int rem;
 
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <linux/u64_stats_sync.h>
+#include <net/ip_tunnels.h>
 
 #include "flow.h"
 #include "flow_table.h"
  * when a packet is received by OVS.
  */
 struct ovs_skb_cb {
-       struct ovs_tunnel_info  *egress_tun_info;
+       struct ip_tunnel_info  *egress_tun_info;
        struct vport            *input_vport;
 };
 #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
  * @egress_tun_info: If nonnull, becomes %OVS_PACKET_ATTR_EGRESS_TUN_KEY.
  */
 struct dp_upcall_info {
-       const struct ovs_tunnel_info *egress_tun_info;
+       const struct ip_tunnel_info *egress_tun_info;
        const struct nlattr *userdata;
        const struct nlattr *actions;
        int actions_len;
 
        return key_extract(skb, key);
 }
 
-int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,
+int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
                         struct sk_buff *skb, struct sw_flow_key *key)
 {
        /* Extract metadata from packet. */
        if (tun_info) {
-               memcpy(&key->tun_key, &tun_info->tunnel, sizeof(key->tun_key));
+               memcpy(&key->tun_key, &tun_info->key, sizeof(key->tun_key));
 
                if (tun_info->options) {
                        BUILD_BUG_ON((1 << (sizeof(tun_info->options_len) *
 
 #include <linux/time.h>
 #include <linux/flex_array.h>
 #include <net/inet_ecn.h>
+#include <net/ip_tunnels.h>
 
 struct sk_buff;
 
-/* Used to memset ovs_key_ipv4_tunnel padding. */
-#define OVS_TUNNEL_KEY_SIZE                                    \
-       (offsetof(struct ovs_key_ipv4_tunnel, tp_dst) +         \
-        FIELD_SIZEOF(struct ovs_key_ipv4_tunnel, tp_dst))
-
-struct ovs_key_ipv4_tunnel {
-       __be64 tun_id;
-       __be32 ipv4_src;
-       __be32 ipv4_dst;
-       __be16 tun_flags;
-       u8   ipv4_tos;
-       u8   ipv4_ttl;
-       __be16 tp_src;
-       __be16 tp_dst;
-} __packed __aligned(4); /* Minimize padding. */
-
-struct ovs_tunnel_info {
-       struct ovs_key_ipv4_tunnel tunnel;
-       const void *options;
-       u8 options_len;
-};
-
 /* Store options at the end of the array if they are less than the
  * maximum size. This allows us to get the benefits of variable length
  * matching for small options.
 #define TUN_METADATA_OPTS(flow_key, opt_len) \
        ((void *)((flow_key)->tun_opts + TUN_METADATA_OFFSET(opt_len)))
 
-static inline void __ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
-                                           __be32 saddr, __be32 daddr,
-                                           u8 tos, u8 ttl,
-                                           __be16 tp_src,
-                                           __be16 tp_dst,
-                                           __be64 tun_id,
-                                           __be16 tun_flags,
-                                           const void *opts,
-                                           u8 opts_len)
-{
-       tun_info->tunnel.tun_id = tun_id;
-       tun_info->tunnel.ipv4_src = saddr;
-       tun_info->tunnel.ipv4_dst = daddr;
-       tun_info->tunnel.ipv4_tos = tos;
-       tun_info->tunnel.ipv4_ttl = ttl;
-       tun_info->tunnel.tun_flags = tun_flags;
-
-       /* For the tunnel types on the top of IPsec, the tp_src and tp_dst of
-        * the upper tunnel are used.
-        * E.g: GRE over IPSEC, the tp_src and tp_port are zero.
-        */
-       tun_info->tunnel.tp_src = tp_src;
-       tun_info->tunnel.tp_dst = tp_dst;
-
-       /* Clear struct padding. */
-       if (sizeof(tun_info->tunnel) != OVS_TUNNEL_KEY_SIZE)
-               memset((unsigned char *)&tun_info->tunnel + OVS_TUNNEL_KEY_SIZE,
-                      0, sizeof(tun_info->tunnel) - OVS_TUNNEL_KEY_SIZE);
-
-       tun_info->options = opts;
-       tun_info->options_len = opts_len;
-}
-
-static inline void ovs_flow_tun_info_init(struct ovs_tunnel_info *tun_info,
-                                         const struct iphdr *iph,
-                                         __be16 tp_src,
-                                         __be16 tp_dst,
-                                         __be64 tun_id,
-                                         __be16 tun_flags,
-                                         const void *opts,
-                                         u8 opts_len)
-{
-       __ovs_flow_tun_info_init(tun_info, iph->saddr, iph->daddr,
-                                iph->tos, iph->ttl,
-                                tp_src, tp_dst,
-                                tun_id, tun_flags,
-                                opts, opts_len);
-}
-
 #define OVS_SW_FLOW_KEY_METADATA_SIZE                  \
        (offsetof(struct sw_flow_key, recirc_id) +      \
        FIELD_SIZEOF(struct sw_flow_key, recirc_id))
 struct sw_flow_key {
        u8 tun_opts[255];
        u8 tun_opts_len;
-       struct ovs_key_ipv4_tunnel tun_key;  /* Encapsulating tunnel key. */
+       struct ip_tunnel_key tun_key;   /* Encapsulating tunnel key. */
        struct {
                u32     priority;       /* Packet QoS priority. */
                u32     skb_mark;       /* SKB mark. */
 u64 ovs_flow_used_time(unsigned long flow_jiffies);
 
 int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
-int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,
+int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
                         struct sk_buff *skb,
                         struct sw_flow_key *key);
 /* Extract key from packet coming from userspace. */
 
 }
 
 static int __ipv4_tun_to_nlattr(struct sk_buff *skb,
-                               const struct ovs_key_ipv4_tunnel *output,
+                               const struct ip_tunnel_key *output,
                                const void *tun_opts, int swkey_tun_opts_len)
 {
        if (output->tun_flags & TUNNEL_KEY &&
 }
 
 static int ipv4_tun_to_nlattr(struct sk_buff *skb,
-                             const struct ovs_key_ipv4_tunnel *output,
+                             const struct ip_tunnel_key *output,
                              const void *tun_opts, int swkey_tun_opts_len)
 {
        struct nlattr *nla;
 }
 
 int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb,
-                                 const struct ovs_tunnel_info *egress_tun_info)
+                                 const struct ip_tunnel_info *egress_tun_info)
 {
-       return __ipv4_tun_to_nlattr(skb, &egress_tun_info->tunnel,
+       return __ipv4_tun_to_nlattr(skb, &egress_tun_info->key,
                                    egress_tun_info->options,
                                    egress_tun_info->options_len);
 }
 {
        struct sw_flow_match match;
        struct sw_flow_key key;
-       struct ovs_tunnel_info *tun_info;
+       struct ip_tunnel_info *tun_info;
        struct nlattr *a;
        int err = 0, start, opts_type;
 
                return PTR_ERR(a);
 
        tun_info = nla_data(a);
-       tun_info->tunnel = key.tun_key;
+       tun_info->key = key.tun_key;
        tun_info->options_len = key.tun_opts_len;
 
        if (tun_info->options_len) {
 
        switch (key_type) {
        case OVS_KEY_ATTR_TUNNEL_INFO: {
-               struct ovs_tunnel_info *tun_info = nla_data(ovs_key);
+               struct ip_tunnel_info *tun_info = nla_data(ovs_key);
 
                start = nla_nest_start(skb, OVS_ACTION_ATTR_SET);
                if (!start)
                        return -EMSGSIZE;
 
-               err = ipv4_tun_to_nlattr(skb, &tun_info->tunnel,
+               err = ipv4_tun_to_nlattr(skb, &tun_info->key,
                                         tun_info->options_len ?
                                                tun_info->options : NULL,
                                         tun_info->options_len);
 
 int ovs_nla_get_match(struct sw_flow_match *, const struct nlattr *key,
                      const struct nlattr *mask, bool log);
 int ovs_nla_put_egress_tunnel_key(struct sk_buff *,
-                                 const struct ovs_tunnel_info *);
+                                 const struct ip_tunnel_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,
 
        struct vport *vport = gs->rcv_data;
        struct genevehdr *geneveh = geneve_hdr(skb);
        int opts_len;
-       struct ovs_tunnel_info tun_info;
+       struct ip_tunnel_info tun_info;
        __be64 key;
        __be16 flags;
 
 
        key = vni_to_tunnel_id(geneveh->vni);
 
-       ovs_flow_tun_info_init(&tun_info, ip_hdr(skb),
-                              udp_hdr(skb)->source, udp_hdr(skb)->dest,
-                              key, flags,
-                              geneveh->options, opts_len);
+       ip_tunnel_info_init(&tun_info, ip_hdr(skb),
+                           udp_hdr(skb)->source, udp_hdr(skb)->dest,
+                           key, flags, geneveh->options, opts_len);
 
        ovs_vport_receive(vport, skb, &tun_info);
 }
 
 static int geneve_tnl_send(struct vport *vport, struct sk_buff *skb)
 {
-       const struct ovs_key_ipv4_tunnel *tun_key;
-       struct ovs_tunnel_info *tun_info;
+       const struct ip_tunnel_key *tun_key;
+       struct ip_tunnel_info *tun_info;
        struct net *net = ovs_dp_get_net(vport->dp);
        struct geneve_port *geneve_port = geneve_vport(vport);
        __be16 dport = inet_sk(geneve_port->gs->sock->sk)->inet_sport;
                goto error;
        }
 
-       tun_key = &tun_info->tunnel;
+       tun_key = &tun_info->key;
        rt = ovs_tunnel_route_lookup(net, tun_key, skb->mark, &fl, IPPROTO_UDP);
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
 }
 
 static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                     struct ovs_tunnel_info *egress_tun_info)
+                                     struct ip_tunnel_info *egress_tun_info)
 {
        struct geneve_port *geneve_port = geneve_vport(vport);
        struct net *net = ovs_dp_get_net(vport->dp);
 
                                      int tunnel_hlen)
 {
        struct tnl_ptk_info tpi;
-       const struct ovs_key_ipv4_tunnel *tun_key;
+       const struct ip_tunnel_key *tun_key;
 
-       tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
+       tun_key = &OVS_CB(skb)->egress_tun_info->key;
 
        skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM));
        if (IS_ERR(skb))
 static int gre_rcv(struct sk_buff *skb,
                   const struct tnl_ptk_info *tpi)
 {
-       struct ovs_tunnel_info tun_info;
+       struct ip_tunnel_info tun_info;
        struct ovs_net *ovs_net;
        struct vport *vport;
        __be64 key;
                return PACKET_REJECT;
 
        key = key_to_tunnel_id(tpi->key, tpi->seq);
-       ovs_flow_tun_info_init(&tun_info, ip_hdr(skb), 0, 0, key,
-                              filter_tnl_flags(tpi->flags), NULL, 0);
+       ip_tunnel_info_init(&tun_info, ip_hdr(skb), 0, 0, key,
+                           filter_tnl_flags(tpi->flags), NULL, 0);
 
        ovs_vport_receive(vport, skb, &tun_info);
        return PACKET_RCVD;
 static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
 {
        struct net *net = ovs_dp_get_net(vport->dp);
-       const struct ovs_key_ipv4_tunnel *tun_key;
+       const struct ip_tunnel_key *tun_key;
        struct flowi4 fl;
        struct rtable *rt;
        int min_headroom;
                goto err_free_skb;
        }
 
-       tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
+       tun_key = &OVS_CB(skb)->egress_tun_info->key;
        rt = ovs_tunnel_route_lookup(net, tun_key, skb->mark, &fl, IPPROTO_GRE);
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
 }
 
 static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                  struct ovs_tunnel_info *egress_tun_info)
+                                  struct ip_tunnel_info *egress_tun_info)
 {
        return ovs_tunnel_get_egress_info(egress_tun_info,
                                          ovs_dp_get_net(vport->dp),
 
 static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb,
                      struct vxlan_metadata *md)
 {
-       struct ovs_tunnel_info tun_info;
+       struct ip_tunnel_info tun_info;
        struct vxlan_port *vxlan_port;
        struct vport *vport = vs->data;
        struct iphdr *iph;
        /* Save outer tunnel values */
        iph = ip_hdr(skb);
        key = cpu_to_be64(ntohl(md->vni) >> 8);
-       ovs_flow_tun_info_init(&tun_info, iph,
-                              udp_hdr(skb)->source, udp_hdr(skb)->dest,
-                              key, flags, &opts, sizeof(opts));
+       ip_tunnel_info_init(&tun_info, iph,
+                           udp_hdr(skb)->source, udp_hdr(skb)->dest,
+                           key, flags, &opts, sizeof(opts));
 
        ovs_vport_receive(vport, skb, &tun_info);
 }
 
 static int vxlan_ext_gbp(struct sk_buff *skb)
 {
-       const struct ovs_tunnel_info *tun_info;
+       const struct ip_tunnel_info *tun_info;
        const struct ovs_vxlan_opts *opts;
 
        tun_info = OVS_CB(skb)->egress_tun_info;
        opts = tun_info->options;
 
-       if (tun_info->tunnel.tun_flags & TUNNEL_VXLAN_OPT &&
+       if (tun_info->key.tun_flags & TUNNEL_VXLAN_OPT &&
            tun_info->options_len >= sizeof(*opts))
                return opts->gbp;
        else
        struct vxlan_port *vxlan_port = vxlan_vport(vport);
        struct sock *sk = vxlan_port->vs->sock->sk;
        __be16 dst_port = inet_sk(sk)->inet_sport;
-       const struct ovs_key_ipv4_tunnel *tun_key;
+       const struct ip_tunnel_key *tun_key;
        struct vxlan_metadata md = {0};
        struct rtable *rt;
        struct flowi4 fl;
                goto error;
        }
 
-       tun_key = &OVS_CB(skb)->egress_tun_info->tunnel;
+       tun_key = &OVS_CB(skb)->egress_tun_info->key;
        rt = ovs_tunnel_route_lookup(net, tun_key, skb->mark, &fl, IPPROTO_UDP);
        if (IS_ERR(rt)) {
                err = PTR_ERR(rt);
 }
 
 static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                    struct ovs_tunnel_info *egress_tun_info)
+                                    struct ip_tunnel_info *egress_tun_info)
 {
        struct net *net = ovs_dp_get_net(vport->dp);
        struct vxlan_port *vxlan_port = vxlan_vport(vport);
 
  * skb->data should point to the Ethernet header.
  */
 void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
-                      const struct ovs_tunnel_info *tun_info)
+                      const struct ip_tunnel_info *tun_info)
 {
        struct pcpu_sw_netstats *stats;
        struct sw_flow_key key;
 }
 EXPORT_SYMBOL_GPL(ovs_vport_deferred_free);
 
-int ovs_tunnel_get_egress_info(struct ovs_tunnel_info *egress_tun_info,
+int ovs_tunnel_get_egress_info(struct ip_tunnel_info *egress_tun_info,
                               struct net *net,
-                              const struct ovs_tunnel_info *tun_info,
+                              const struct ip_tunnel_info *tun_info,
                               u8 ipproto,
                               u32 skb_mark,
                               __be16 tp_src,
                               __be16 tp_dst)
 {
-       const struct ovs_key_ipv4_tunnel *tun_key;
+       const struct ip_tunnel_key *tun_key;
        struct rtable *rt;
        struct flowi4 fl;
 
        if (unlikely(!tun_info))
                return -EINVAL;
 
-       tun_key = &tun_info->tunnel;
+       tun_key = &tun_info->key;
 
        /* Route lookup to get srouce IP address.
         * The process may need to be changed if the corresponding process
        /* Generate egress_tun_info based on tun_info,
         * saddr, tp_src and tp_dst
         */
-       __ovs_flow_tun_info_init(egress_tun_info,
-                                fl.saddr, tun_key->ipv4_dst,
-                                tun_key->ipv4_tos,
-                                tun_key->ipv4_ttl,
-                                tp_src, tp_dst,
-                                tun_key->tun_id,
-                                tun_key->tun_flags,
-                                tun_info->options,
-                                tun_info->options_len);
+       __ip_tunnel_info_init(egress_tun_info,
+                             fl.saddr, tun_key->ipv4_dst,
+                             tun_key->ipv4_tos,
+                             tun_key->ipv4_ttl,
+                             tp_src, tp_dst,
+                             tun_key->tun_id,
+                             tun_key->tun_flags,
+                             tun_info->options,
+                             tun_info->options_len);
 
        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 ovs_tunnel_info *info)
+                                 struct ip_tunnel_info *info)
 {
        /* get_egress_tun_info() is only implemented on tunnel ports. */
        if (unlikely(!vport->ops->get_egress_tun_info))
 
 
 int ovs_vport_send(struct vport *, struct sk_buff *);
 
-int ovs_tunnel_get_egress_info(struct ovs_tunnel_info *egress_tun_info,
+int ovs_tunnel_get_egress_info(struct ip_tunnel_info *egress_tun_info,
                               struct net *net,
-                              const struct ovs_tunnel_info *tun_info,
+                              const struct ip_tunnel_info *tun_info,
                               u8 ipproto,
                               u32 skb_mark,
                               __be16 tp_src,
                               __be16 tp_dst);
 int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                 struct ovs_tunnel_info *info);
+                                 struct ip_tunnel_info *info);
 
 /* The following definitions are for implementers of vport devices: */
 
 
        int (*send)(struct vport *, struct sk_buff *);
        int (*get_egress_tun_info)(struct vport *, struct sk_buff *,
-                                  struct ovs_tunnel_info *);
+                                  struct ip_tunnel_info *);
 
        struct module *owner;
        struct list_head list;
 }
 
 void ovs_vport_receive(struct vport *, struct sk_buff *,
-                      const struct ovs_tunnel_info *);
+                      const struct ip_tunnel_info *);
 
 static inline void ovs_skb_postpush_rcsum(struct sk_buff *skb,
                                      const void *start, unsigned int len)
 void ovs_vport_ops_unregister(struct vport_ops *ops);
 
 static inline struct rtable *ovs_tunnel_route_lookup(struct net *net,
-                                                    const struct ovs_key_ipv4_tunnel *key,
+                                                    const struct ip_tunnel_key *key,
                                                     u32 mark,
                                                     struct flowi4 *fl,
                                                     u8 protocol)