These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / include / net / ip_tunnels.h
index d8214cb..62a750a 100644 (file)
@@ -4,14 +4,15 @@
 #include <linux/if_tunnel.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
+#include <linux/socket.h>
 #include <linux/types.h>
 #include <linux/u64_stats_sync.h>
 #include <net/dsfield.h>
 #include <net/gro_cells.h>
 #include <net/inet_ecn.h>
-#include <net/ip.h>
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
+#include <net/lwtunnel.h>
 
 #if IS_ENABLED(CONFIG_IPV6)
 #include <net/ipv6.h>
 /* 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     offsetofend(struct ip_tunnel_key, tp_dst)
+
+/* Used to memset ipv4 address padding. */
+#define IP_TUNNEL_KEY_IPV4_PAD offsetofend(struct ip_tunnel_key, u.ipv4.dst)
+#define IP_TUNNEL_KEY_IPV4_PAD_LEN                             \
+       (FIELD_SIZEOF(struct ip_tunnel_key, u) -                \
+        FIELD_SIZEOF(struct ip_tunnel_key, u.ipv4))
+
+struct ip_tunnel_key {
+       __be64                  tun_id;
+       union {
+               struct {
+                       __be32  src;
+                       __be32  dst;
+               } ipv4;
+               struct {
+                       struct in6_addr src;
+                       struct in6_addr dst;
+               } ipv6;
+       } u;
+       __be16                  tun_flags;
+       u8                      tos;            /* TOS for IPv4, TC for IPv6 */
+       u8                      ttl;            /* TTL for IPv4, HL for IPv6 */
+       __be16                  tp_src;
+       __be16                  tp_dst;
+};
+
+/* Flags for ip_tunnel_info mode. */
+#define IP_TUNNEL_INFO_TX      0x01    /* represents tx tunnel parameters */
+#define IP_TUNNEL_INFO_IPV6    0x02    /* key contains IPv6 addresses */
+
+struct ip_tunnel_info {
+       struct ip_tunnel_key    key;
+       u8                      options_len;
+       u8                      mode;
+};
+
 /* 6rd prefix/relay information */
 #ifdef CONFIG_IPV6_SIT_6RD
 struct ip_tunnel_6rd_parm {
@@ -33,8 +72,8 @@ struct ip_tunnel_6rd_parm {
 #endif
 
 struct ip_tunnel_encap {
-       __u16                   type;
-       __u16                   flags;
+       u16                     type;
+       u16                     flags;
        __be16                  sport;
        __be16                  dport;
 };
@@ -51,6 +90,8 @@ struct ip_tunnel_dst {
        __be32                           saddr;
 };
 
+struct metadata_dst;
+
 struct ip_tunnel {
        struct ip_tunnel __rcu  *next;
        struct hlist_node hash_node;
@@ -62,8 +103,8 @@ struct ip_tunnel {
                                         * arrived */
 
        /* These four fields used only by GRE */
-       __u32           i_seqno;        /* The last seen seqno  */
-       __u32           o_seqno;        /* The last output seqno */
+       u32             i_seqno;        /* The last seen seqno  */
+       u32             o_seqno;        /* The last output seqno */
        int             tun_hlen;       /* Precalculated header length */
        int             mlink;
 
@@ -84,6 +125,7 @@ struct ip_tunnel {
        unsigned int            prl_count;      /* # of entries in PRL */
        int                     ip_tnl_net_id;
        struct gro_cells        gro_cells;
+       bool                    collect_md;
 };
 
 #define TUNNEL_CSUM            __cpu_to_be16(0x01)
@@ -118,6 +160,7 @@ struct tnl_ptk_info {
 struct ip_tunnel_net {
        struct net_device *fb_tunnel_dev;
        struct hlist_head tunnels[IP_TNL_HASH_SIZE];
+       struct ip_tunnel __rcu *collect_md_tun;
 };
 
 struct ip_tunnel_encap_ops {
@@ -136,6 +179,40 @@ int ip_tunnel_encap_add_ops(const struct ip_tunnel_encap_ops *op,
 int ip_tunnel_encap_del_ops(const struct ip_tunnel_encap_ops *op,
                            unsigned int num);
 
+static inline void ip_tunnel_key_init(struct ip_tunnel_key *key,
+                                     __be32 saddr, __be32 daddr,
+                                     u8 tos, u8 ttl,
+                                     __be16 tp_src, __be16 tp_dst,
+                                     __be64 tun_id, __be16 tun_flags)
+{
+       key->tun_id = tun_id;
+       key->u.ipv4.src = saddr;
+       key->u.ipv4.dst = daddr;
+       memset((unsigned char *)key + IP_TUNNEL_KEY_IPV4_PAD,
+              0, IP_TUNNEL_KEY_IPV4_PAD_LEN);
+       key->tos = tos;
+       key->ttl = ttl;
+       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.
+        */
+       key->tp_src = tp_src;
+       key->tp_dst = tp_dst;
+
+       /* Clear struct padding. */
+       if (sizeof(*key) != IP_TUNNEL_KEY_SIZE)
+               memset((unsigned char *)key + IP_TUNNEL_KEY_SIZE,
+                      0, sizeof(*key) - IP_TUNNEL_KEY_SIZE);
+}
+
+static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info
+                                              *tun_info)
+{
+       return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET;
+}
+
 #ifdef CONFIG_INET
 
 int ip_tunnel_init(struct net_device *dev);
@@ -163,7 +240,8 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn,
                                   __be32 key);
 
 int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
-                 const struct tnl_ptk_info *tpi, bool log_ecn_error);
+                 const struct tnl_ptk_info *tpi, struct metadata_dst *tun_dst,
+                 bool log_ecn_error);
 int ip_tunnel_changelink(struct net_device *dev, struct nlattr *tb[],
                         struct ip_tunnel_parm *p);
 int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[],
@@ -196,8 +274,10 @@ static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,
 
 int iptunnel_pull_header(struct sk_buff *skb, int hdr_len, __be16 inner_proto);
 int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
-                 __be32 src, __be32 dst, __u8 proto,
-                 __u8 tos, __u8 ttl, __be16 df, bool xnet);
+                 __be32 src, __be32 dst, u8 proto,
+                 u8 tos, u8 ttl, __be16 df, bool xnet);
+struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
+                                            gfp_t flags);
 
 struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb, bool gre_csum,
                                         int gso_type_mask);
@@ -207,12 +287,13 @@ static inline void iptunnel_xmit_stats(int err,
                                       struct pcpu_sw_netstats __percpu *stats)
 {
        if (err > 0) {
-               struct pcpu_sw_netstats *tstats = this_cpu_ptr(stats);
+               struct pcpu_sw_netstats *tstats = get_cpu_ptr(stats);
 
                u64_stats_update_begin(&tstats->syncp);
                tstats->tx_bytes += err;
                tstats->tx_packets++;
                u64_stats_update_end(&tstats->syncp);
+               put_cpu_ptr(tstats);
        } else if (err < 0) {
                err_stats->tx_errors++;
                err_stats->tx_aborted_errors++;
@@ -221,6 +302,57 @@ static inline void iptunnel_xmit_stats(int err,
        }
 }
 
+static inline void *ip_tunnel_info_opts(struct ip_tunnel_info *info)
+{
+       return info + 1;
+}
+
+static inline void ip_tunnel_info_opts_get(void *to,
+                                          const struct ip_tunnel_info *info)
+{
+       memcpy(to, info + 1, info->options_len);
+}
+
+static inline void ip_tunnel_info_opts_set(struct ip_tunnel_info *info,
+                                          const void *from, int len)
+{
+       memcpy(ip_tunnel_info_opts(info), from, len);
+       info->options_len = len;
+}
+
+static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate)
+{
+       return (struct ip_tunnel_info *)lwtstate->data;
+}
+
+extern struct static_key ip_tunnel_metadata_cnt;
+
+/* Returns > 0 if metadata should be collected */
+static inline int ip_tunnel_collect_metadata(void)
+{
+       return static_key_false(&ip_tunnel_metadata_cnt);
+}
+
+void __init ip_tunnel_core_init(void);
+
+void ip_tunnel_need_metadata(void);
+void ip_tunnel_unneed_metadata(void);
+
+#else /* CONFIG_INET */
+
+static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate)
+{
+       return NULL;
+}
+
+static inline void ip_tunnel_need_metadata(void)
+{
+}
+
+static inline void ip_tunnel_unneed_metadata(void)
+{
+}
+
 #endif /* CONFIG_INET */
 
 #endif /* __NET_IP_TUNNELS_H */