#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>
/* 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;
- __be32 ipv4_src;
- __be32 ipv4_dst;
+ union {
+ struct {
+ __be32 src;
+ __be32 dst;
+ } ipv4;
+ struct {
+ struct in6_addr src;
+ struct in6_addr dst;
+ } ipv6;
+ } u;
__be16 tun_flags;
- u8 ipv4_tos;
- u8 ipv4_ttl;
+ u8 tos; /* TOS for IPv4, TC for IPv6 */
+ u8 ttl; /* TTL for IPv4, HL for IPv6 */
__be16 tp_src;
__be16 tp_dst;
};
-/* Indicates whether the tunnel info structure represents receive
- * or transmit tunnel parameters.
- */
-enum {
- IP_TUNNEL_INFO_RX,
- IP_TUNNEL_INFO_TX,
-};
+/* 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;
- const void *options;
u8 options_len;
u8 mode;
};
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)
+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)
{
- 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;
+ 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.
*/
- tun_info->key.tp_src = tp_src;
- tun_info->key.tp_dst = tp_dst;
+ key->tp_src = tp_src;
+ 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;
+ if (sizeof(*key) != IP_TUNNEL_KEY_SIZE)
+ memset((unsigned char *)key + IP_TUNNEL_KEY_SIZE,
+ 0, sizeof(*key) - IP_TUNNEL_KEY_SIZE);
}
-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)
+static inline unsigned short ip_tunnel_info_af(const struct ip_tunnel_info
+ *tun_info)
{
- __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);
+ return tun_info->mode & IP_TUNNEL_INFO_IPV6 ? AF_INET6 : AF_INET;
}
#ifdef CONFIG_INET
}
}
-static inline void *ip_tunnel_info_opts(struct ip_tunnel_info *info, size_t n)
+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;