]> git.proxmox.com Git - ovs.git/blob - datapath/linux/compat/include/net/dst_metadata.h
compat: Remove duplicate metadata destination code
[ovs.git] / datapath / linux / compat / include / net / dst_metadata.h
1 #ifndef __NET_DST_METADATA_WRAPPER_H
2 #define __NET_DST_METADATA_WRAPPER_H 1
3
4 #ifdef USE_UPSTREAM_TUNNEL
5 #include_next <net/dst_metadata.h>
6 #else
7 #include <linux/skbuff.h>
8
9 #include <net/dsfield.h>
10 #include <net/dst.h>
11 #include <net/ipv6.h>
12 #include <net/ip_tunnels.h>
13
14 enum metadata_type {
15 METADATA_IP_TUNNEL,
16 METADATA_HW_PORT_MUX,
17 };
18
19 struct hw_port_info {
20 struct net_device *lower_dev;
21 u32 port_id;
22 };
23
24 struct metadata_dst {
25 struct dst_entry dst;
26 enum metadata_type type;
27 union {
28 struct ip_tunnel_info tun_info;
29 struct hw_port_info port_info;
30 } u;
31 };
32
33 #ifndef DST_METADATA
34 #define DST_METADATA 0x0080
35 #endif
36
37 extern struct dst_ops md_dst_ops;
38
39 static void rpl__metadata_dst_init(struct metadata_dst *md_dst,
40 enum metadata_type type, u8 optslen)
41
42 {
43 struct dst_entry *dst;
44
45 dst = &md_dst->dst;
46 dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE,
47 DST_METADATA | DST_NOCOUNT);
48
49 #if 0
50 /* unused in OVS */
51 dst->input = dst_md_discard;
52 dst->output = dst_md_discard_out;
53 #endif
54 memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst));
55 md_dst->type = type;
56 }
57
58 static struct
59 metadata_dst *__rpl_metadata_dst_alloc(u8 optslen,
60 enum metadata_type type,
61 gfp_t flags)
62 {
63 struct metadata_dst *md_dst;
64
65 md_dst = kmalloc(sizeof(*md_dst) + optslen, flags);
66 if (!md_dst)
67 return NULL;
68
69 rpl__metadata_dst_init(md_dst, type, optslen);
70
71 return md_dst;
72 }
73 static inline struct metadata_dst *rpl_tun_rx_dst(int md_size)
74 {
75 struct metadata_dst *tun_dst;
76
77 tun_dst = __rpl_metadata_dst_alloc(md_size, METADATA_IP_TUNNEL,
78 GFP_ATOMIC);
79 if (!tun_dst)
80 return NULL;
81
82 tun_dst->u.tun_info.options_len = 0;
83 tun_dst->u.tun_info.mode = 0;
84 return tun_dst;
85 }
86 static inline struct metadata_dst *rpl__ip_tun_set_dst(__be32 saddr,
87 __be32 daddr,
88 __u8 tos, __u8 ttl,
89 __be16 tp_dst,
90 __be16 flags,
91 __be64 tunnel_id,
92 int md_size)
93 {
94 struct metadata_dst *tun_dst;
95
96 tun_dst = rpl_tun_rx_dst(md_size);
97 if (!tun_dst)
98 return NULL;
99
100 ip_tunnel_key_init(&tun_dst->u.tun_info.key,
101 saddr, daddr, tos, ttl,
102 0, 0, tp_dst, tunnel_id, flags);
103 return tun_dst;
104 }
105
106 static inline struct metadata_dst *rpl_ip_tun_rx_dst(struct sk_buff *skb,
107 __be16 flags,
108 __be64 tunnel_id,
109 int md_size)
110 {
111 const struct iphdr *iph = ip_hdr(skb);
112
113 return rpl__ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl,
114 0, flags, tunnel_id, md_size);
115 }
116
117 static inline
118 struct metadata_dst *rpl__ipv6_tun_set_dst(const struct in6_addr *saddr,
119 const struct in6_addr *daddr,
120 __u8 tos, __u8 ttl,
121 __be16 tp_dst,
122 __be32 label,
123 __be16 flags,
124 __be64 tunnel_id,
125 int md_size)
126 {
127 struct metadata_dst *tun_dst;
128 struct ip_tunnel_info *info;
129
130 tun_dst = rpl_tun_rx_dst(md_size);
131 if (!tun_dst)
132 return NULL;
133
134 info = &tun_dst->u.tun_info;
135 info->mode = IP_TUNNEL_INFO_IPV6;
136 info->key.tun_flags = flags;
137 info->key.tun_id = tunnel_id;
138 info->key.tp_src = 0;
139 info->key.tp_dst = tp_dst;
140
141 info->key.u.ipv6.src = *saddr;
142 info->key.u.ipv6.dst = *daddr;
143
144 info->key.tos = tos;
145 info->key.ttl = ttl;
146 info->key.label = label;
147
148 return tun_dst;
149 }
150
151 static inline struct metadata_dst *rpl_ipv6_tun_rx_dst(struct sk_buff *skb,
152 __be16 flags,
153 __be64 tunnel_id,
154 int md_size)
155 {
156 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
157
158 return rpl__ipv6_tun_set_dst(&ip6h->saddr, &ip6h->daddr,
159 ipv6_get_dsfield(ip6h), ip6h->hop_limit,
160 0, ip6_flowlabel(ip6h), flags, tunnel_id,
161 md_size);
162 }
163
164 static void __metadata_dst_init(struct metadata_dst *md_dst, u8 optslen)
165 {
166 struct dst_entry *dst;
167
168 dst = &md_dst->dst;
169
170 #if 0
171 dst_init(dst, &md_dst_ops, NULL, 1, DST_OBSOLETE_NONE,
172 DST_METADATA | DST_NOCACHE | DST_NOCOUNT);
173
174 dst->input = dst_md_discard;
175 dst->output = dst_md_discard_out;
176 #endif
177
178 memset(dst + 1, 0, sizeof(*md_dst) + optslen - sizeof(*dst));
179 }
180
181 static inline struct metadata_dst *metadata_dst_alloc(u8 optslen, gfp_t flags)
182 {
183 struct metadata_dst *md_dst;
184
185 md_dst = kmalloc(sizeof(*md_dst) + optslen, flags);
186 if (!md_dst)
187 return NULL;
188
189 __metadata_dst_init(md_dst, optslen);
190 return md_dst;
191 }
192
193 #define skb_tunnel_info ovs_skb_tunnel_info
194
195 static inline void ovs_tun_rx_dst(struct metadata_dst *md_dst, int optslen)
196 {
197 /* No need to allocate for OVS backport case. */
198 #if 0
199 struct metadata_dst *tun_dst;
200 struct ip_tunnel_info *info;
201
202 tun_dst = metadata_dst_alloc(md_size, GFP_ATOMIC);
203 if (!tun_dst)
204 return NULL;
205 #endif
206 __metadata_dst_init(md_dst, optslen);
207 }
208
209 static inline void ovs_ip_tun_rx_dst(struct metadata_dst *md_dst,
210 struct sk_buff *skb, __be16 flags,
211 __be64 tunnel_id, int md_size)
212 {
213 const struct iphdr *iph = ip_hdr(skb);
214
215 ovs_tun_rx_dst(md_dst, md_size);
216 ip_tunnel_key_init(&md_dst->u.tun_info.key,
217 iph->saddr, iph->daddr, iph->tos, iph->ttl, 0,
218 0, 0, tunnel_id, flags);
219 }
220
221 static inline void ovs_ipv6_tun_rx_dst(struct metadata_dst *md_dst,
222 struct sk_buff *skb,
223 __be16 flags,
224 __be64 tunnel_id,
225 int md_size)
226 {
227 struct ip_tunnel_info *info = &md_dst->u.tun_info;
228 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
229
230 ovs_tun_rx_dst(md_dst, md_size);
231 info->mode = IP_TUNNEL_INFO_IPV6;
232 info->key.tun_flags = flags;
233 info->key.tun_id = tunnel_id;
234 info->key.tp_src = 0;
235 info->key.tp_dst = 0;
236
237 info->key.u.ipv6.src = ip6h->saddr;
238 info->key.u.ipv6.dst = ip6h->daddr;
239
240 info->key.tos = ipv6_get_dsfield(ip6h);
241 info->key.ttl = ip6h->hop_limit;
242 info->key.label = ip6_flowlabel(ip6h);
243 }
244
245 #endif /* USE_UPSTREAM_TUNNEL */
246
247 void ovs_ip_tunnel_rcv(struct net_device *dev, struct sk_buff *skb,
248 struct metadata_dst *tun_dst);
249
250 static inline struct metadata_dst *
251 rpl_metadata_dst_alloc(u8 optslen, enum metadata_type type, gfp_t flags)
252 {
253 #if defined(HAVE_METADATA_DST_ALLOC_WITH_METADATA_TYPE) && defined(USE_UPSTREAM_TUNNEL)
254 return metadata_dst_alloc(optslen, type, flags);
255 #else
256 return metadata_dst_alloc(optslen, flags);
257 #endif
258 }
259 #define metadata_dst_alloc rpl_metadata_dst_alloc
260
261 static inline bool rpl_skb_valid_dst(const struct sk_buff *skb)
262 {
263 struct dst_entry *dst = skb_dst(skb);
264
265 return dst && !(dst->flags & DST_METADATA);
266 }
267 #define skb_valid_dst rpl_skb_valid_dst
268
269 #endif /* __NET_DST_METADATA_WRAPPER_H */