summaryrefslogtreecommitdiff
path: root/datapath/linux/compat/include/net/dst_metadata.h
blob: 310cfa6573308a623e19bd4840e9a4f164f606d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#ifndef __NET_DST_METADATA_WRAPPER_H
#define __NET_DST_METADATA_WRAPPER_H 1

#ifdef HAVE_METADATA_DST
#include_next <net/dst_metadata.h>
#else
#include <linux/skbuff.h>

#include <net/dsfield.h>
#include <net/dst.h>
#include <net/ipv6.h>
#include <net/ip_tunnels.h>

struct metadata_dst {
	unsigned long dst;
	union {
		struct ip_tunnel_info	tun_info;
	} u;
};

static void __metadata_dst_init(struct metadata_dst *md_dst, u8 optslen)
{
	unsigned long *dst;

	dst = &md_dst->dst;
	*dst = 0;
#if 0
	dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE,
			DST_METADATA | DST_NOCACHE | DST_NOCOUNT);

	dst->input = dst_md_discard;
	dst->output = dst_md_discard_out;
#endif

	memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst));
}

static inline struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags)
{
	struct metadata_dst *md_dst;

	md_dst = kmalloc(sizeof(*md_dst) + optslen, flags);
	if (!md_dst)
		return NULL;

	__metadata_dst_init(md_dst, optslen);
	return md_dst;
}

#define skb_tunnel_info ovs_skb_tunnel_info
#endif

static inline void ovs_tun_rx_dst(struct ip_tunnel_info *info, int md_size)
{
	/* No need to allocate for OVS backport case. */
#if 0
	struct metadata_dst *tun_dst;
	struct ip_tunnel_info *info;

	tun_dst = metadata_dst_alloc(md_size, GFP_ATOMIC);
	if (!tun_dst)
		return NULL;
#endif
	info->mode = 0;
	info->options_len = 0;
}

static inline void ovs_ip_tun_rx_dst(struct ip_tunnel_info *tun_info,
				 struct sk_buff *skb, __be16 flags,
				 __be64 tunnel_id, int md_size)
{
	const struct iphdr *iph = ip_hdr(skb);

	ovs_tun_rx_dst(tun_info, md_size);
	ip_tunnel_key_init(&tun_info->key,
			   iph->saddr, iph->daddr, iph->tos, iph->ttl, 0,
			   0, 0, tunnel_id, flags);
}

static inline void ovs_ipv6_tun_rx_dst(struct ip_tunnel_info *info,
				       struct sk_buff *skb,
				       __be16 flags,
				       __be64 tunnel_id,
				       int md_size)
{
	const struct ipv6hdr *ip6h = ipv6_hdr(skb);

	ovs_tun_rx_dst(info, md_size);
	info->mode = IP_TUNNEL_INFO_IPV6;
	info->key.tun_flags = flags;
	info->key.tun_id = tunnel_id;
	info->key.tp_src = 0;
	info->key.tp_dst = 0;

	info->key.u.ipv6.src = ip6h->saddr;
	info->key.u.ipv6.dst = ip6h->daddr;

	info->key.tos = ipv6_get_dsfield(ip6h);
	info->key.ttl = ip6h->hop_limit;
	info->key.label = ip6_flowlabel(ip6h);
}

void ovs_ip_tunnel_rcv(struct net_device *dev, struct sk_buff *skb,
		      struct metadata_dst *tun_dst);
#endif /* __NET_DST_METADATA_WRAPPER_H */