summaryrefslogtreecommitdiff
path: root/datapath/linux/compat/include/net/dst_metadata.h
blob: 36f3f390dbe980e1535e6e2c89ab73b18a261666 (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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#ifndef __NET_DST_METADATA_WRAPPER_H
#define __NET_DST_METADATA_WRAPPER_H 1

#ifdef USE_UPSTREAM_TUNNEL
#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>

enum metadata_type {
	METADATA_IP_TUNNEL,
	METADATA_HW_PORT_MUX,
};

struct hw_port_info {
	struct net_device *lower_dev;
	u32 port_id;
};

struct metadata_dst {
	struct dst_entry 	dst;
	enum metadata_type	type;
	union {
		struct ip_tunnel_info	tun_info;
		struct hw_port_info	port_info;
	} u;
};

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

	dst = &md_dst->dst;

#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

static inline void ovs_tun_rx_dst(struct metadata_dst *md_dst, int optslen)
{
	/* 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
	__metadata_dst_init(md_dst, optslen);
}

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

	ovs_tun_rx_dst(md_dst, md_size);
	ip_tunnel_key_init(&md_dst->u.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 metadata_dst *md_dst,
				       struct sk_buff *skb,
				       __be16 flags,
				       __be64 tunnel_id,
				       int md_size)
{
	struct ip_tunnel_info *info = &md_dst->u.tun_info;
	const struct ipv6hdr *ip6h = ipv6_hdr(skb);

	ovs_tun_rx_dst(md_dst, 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);
}

#endif /* USE_UPSTREAM_TUNNEL */

void ovs_ip_tunnel_rcv(struct net_device *dev, struct sk_buff *skb,
		      struct metadata_dst *tun_dst);

static inline struct metadata_dst *
rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, gfp_t flags)
{
#if defined(HAVE_METADATA_DST_ALLOC_WITH_METADATA_TYPE) && defined(USE_UPSTREAM_TUNNEL)
	return metadata_dst_alloc(optslen, type, flags);
#else
	return metadata_dst_alloc(optslen, flags);
#endif
}
#define metadata_dst_alloc rpl_metadata_dst_alloc

#endif /* __NET_DST_METADATA_WRAPPER_H */