Blame view

net/ipv4/ip_tunnel_core.c 11.9 KB
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
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
  /*
   * Copyright (c) 2013 Nicira, Inc.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of version 2 of the GNU General Public
   * License as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   * 02110-1301, USA
   */
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/skbuff.h>
  #include <linux/netdevice.h>
  #include <linux/in.h>
  #include <linux/if_arp.h>
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
27
28
29
30
31
32
33
  #include <linux/init.h>
  #include <linux/in6.h>
  #include <linux/inetdevice.h>
  #include <linux/netfilter_ipv4.h>
  #include <linux/etherdevice.h>
  #include <linux/if_ether.h>
  #include <linux/if_vlan.h>
e7030878f   Thomas Graf   fib: Add fib rule...
34
  #include <linux/static_key.h>
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
35
36
37
38
39
  
  #include <net/ip.h>
  #include <net/icmp.h>
  #include <net/protocol.h>
  #include <net/ip_tunnels.h>
058214a4d   Tom Herbert   ip6_tun: Add infr...
40
  #include <net/ip6_tunnel.h>
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
41
42
43
44
45
46
47
48
  #include <net/arp.h>
  #include <net/checksum.h>
  #include <net/dsfield.h>
  #include <net/inet_ecn.h>
  #include <net/xfrm.h>
  #include <net/net_namespace.h>
  #include <net/netns/generic.h>
  #include <net/rtnetlink.h>
63d008a4e   Jiri Benc   ipv4: send arp re...
49
  #include <net/dst_metadata.h>
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
50

55c2bc143   Tom Herbert   net: Cleanup enca...
51
52
53
  const struct ip_tunnel_encap_ops __rcu *
  		iptun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly;
  EXPORT_SYMBOL(iptun_encaps);
058214a4d   Tom Herbert   ip6_tun: Add infr...
54
55
56
  const struct ip6_tnl_encap_ops __rcu *
  		ip6tun_encaps[MAX_IPTUN_ENCAP_OPS] __read_mostly;
  EXPORT_SYMBOL(ip6tun_encaps);
039f50629   Pravin B Shelar   ip_tunnel: Move s...
57
58
59
  void 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)
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
60
  {
bc22a0e2e   Nicolas Dichtel   iptunnel: make rx...
61
  	int pkt_len = skb->len - skb_inner_network_offset(skb);
f859b0f66   Eric W. Biederman   ipv4: Cache net i...
62
  	struct net *net = dev_net(rt->dst.dev);
039f50629   Pravin B Shelar   ip_tunnel: Move s...
63
  	struct net_device *dev = skb->dev;
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
64
65
  	struct iphdr *iph;
  	int err;
963a88b31   Nicolas Dichtel   tunnels: harmoniz...
66
  	skb_scrub_packet(skb, xnet);
bf8d85d4f   Eric Dumazet   ip_tunnel: do not...
67
  	skb_clear_hash_if_not_l4(skb);
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
68
69
70
71
  	skb_dst_set(skb, &rt->dst);
  	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
  
  	/* Push down and install the IP header. */
78a3694d4   Steffen Klassert   ip_tunnel_core: C...
72
  	skb_push(skb, sizeof(struct iphdr));
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
73
74
75
76
77
78
79
80
81
82
83
84
  	skb_reset_network_header(skb);
  
  	iph = ip_hdr(skb);
  
  	iph->version	=	4;
  	iph->ihl	=	sizeof(struct iphdr) >> 2;
  	iph->frag_off	=	df;
  	iph->protocol	=	proto;
  	iph->tos	=	tos;
  	iph->daddr	=	dst;
  	iph->saddr	=	src;
  	iph->ttl	=	ttl;
f859b0f66   Eric W. Biederman   ipv4: Cache net i...
85
  	__ip_select_ident(net, iph, skb_shinfo(skb)->gso_segs ?: 1);
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
86

33224b16f   Eric W. Biederman   ipv4, ipv6: Pass ...
87
  	err = ip_local_out(net, sk, skb);
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
88
89
  	if (unlikely(net_xmit_eval(err)))
  		pkt_len = 0;
039f50629   Pravin B Shelar   ip_tunnel: Move s...
90
  	iptunnel_xmit_stats(dev, pkt_len);
0e6fbc5b6   Pravin B Shelar   ip_tunnels: exten...
91
92
  }
  EXPORT_SYMBOL_GPL(iptunnel_xmit);
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
93

a6d5bbf34   Jiri Benc   ip_tunnel: implem...
94
95
  int __iptunnel_pull_header(struct sk_buff *skb, int hdr_len,
  			   __be16 inner_proto, bool raw_proto, bool xnet)
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
96
97
98
99
100
  {
  	if (unlikely(!pskb_may_pull(skb, hdr_len)))
  		return -ENOMEM;
  
  	skb_pull_rcsum(skb, hdr_len);
a6d5bbf34   Jiri Benc   ip_tunnel: implem...
101
  	if (!raw_proto && inner_proto == htons(ETH_P_TEB)) {
1245dfc8c   Li RongQing   ipv4: fix a poten...
102
  		struct ethhdr *eh;
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
103
104
105
  
  		if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
  			return -ENOMEM;
1245dfc8c   Li RongQing   ipv4: fix a poten...
106
  		eh = (struct ethhdr *)skb->data;
d181ddca8   Alexander Duyck   ipv4/ip_tunnel_co...
107
  		if (likely(eth_proto_is_802_3(eh->h_proto)))
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
108
109
110
111
112
113
114
  			skb->protocol = eh->h_proto;
  		else
  			skb->protocol = htons(ETH_P_802_2);
  
  	} else {
  		skb->protocol = inner_proto;
  	}
7539fadcb   Tom Herbert   net: Add utility ...
115
  	skb_clear_hash_if_not_l4(skb);
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
116
117
  	skb->vlan_tci = 0;
  	skb_set_queue_mapping(skb, 0);
7f290c943   Jiri Benc   iptunnel: scrub p...
118
  	skb_scrub_packet(skb, xnet);
a09a4c8dd   Jesse Gross   tunnels: Remove e...
119
120
  
  	return iptunnel_pull_offloads(skb);
3d7b46cd2   Pravin B Shelar   ip_tunnel: push g...
121
  }
a6d5bbf34   Jiri Benc   ip_tunnel: implem...
122
  EXPORT_SYMBOL_GPL(__iptunnel_pull_header);
2d26f0a3c   Eric Dumazet   ipv4: generalize ...
123

63d008a4e   Jiri Benc   ipv4: send arp re...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
  					     gfp_t flags)
  {
  	struct metadata_dst *res;
  	struct ip_tunnel_info *dst, *src;
  
  	if (!md || md->u.tun_info.mode & IP_TUNNEL_INFO_TX)
  		return NULL;
  
  	res = metadata_dst_alloc(0, flags);
  	if (!res)
  		return NULL;
  
  	dst = &res->u.tun_info;
  	src = &md->u.tun_info;
  	dst->key.tun_id = src->key.tun_id;
  	if (src->mode & IP_TUNNEL_INFO_IPV6)
  		memcpy(&dst->key.u.ipv6.dst, &src->key.u.ipv6.src,
  		       sizeof(struct in6_addr));
  	else
  		dst->key.u.ipv4.dst = src->key.u.ipv4.src;
  	dst->mode = src->mode | IP_TUNNEL_INFO_TX;
  
  	return res;
  }
  EXPORT_SYMBOL_GPL(iptunnel_metadata_reply);
aed069df0   Alexander Duyck   ip_tunnel_core: i...
150
151
  int iptunnel_handle_offloads(struct sk_buff *skb,
  			     int gso_type_mask)
2d26f0a3c   Eric Dumazet   ipv4: generalize ...
152
153
154
155
156
157
158
159
160
  {
  	int err;
  
  	if (likely(!skb->encapsulation)) {
  		skb_reset_inner_headers(skb);
  		skb->encapsulation = 1;
  	}
  
  	if (skb_is_gso(skb)) {
9580bf2ed   Eric Dumazet   net: relax expens...
161
  		err = skb_header_unclone(skb, GFP_ATOMIC);
2d26f0a3c   Eric Dumazet   ipv4: generalize ...
162
  		if (unlikely(err))
aed069df0   Alexander Duyck   ip_tunnel_core: i...
163
  			return err;
2d26f0a3c   Eric Dumazet   ipv4: generalize ...
164
  		skb_shinfo(skb)->gso_type |= gso_type_mask;
aed069df0   Alexander Duyck   ip_tunnel_core: i...
165
  		return 0;
2d26f0a3c   Eric Dumazet   ipv4: generalize ...
166
  	}
6fa79666e   Edward Cree   net: ip_tunnel: r...
167
  	if (skb->ip_summed != CHECKSUM_PARTIAL) {
2d26f0a3c   Eric Dumazet   ipv4: generalize ...
168
  		skb->ip_summed = CHECKSUM_NONE;
6fa79666e   Edward Cree   net: ip_tunnel: r...
169
170
171
172
173
  		/* We clear encapsulation here to prevent badly-written
  		 * drivers potentially deciding to offload an inner checksum
  		 * if we set CHECKSUM_PARTIAL on the outer header.
  		 * This should go away when the drivers are all fixed.
  		 */
179bc67f6   Edward Cree   net: local checks...
174
175
  		skb->encapsulation = 0;
  	}
2d26f0a3c   Eric Dumazet   ipv4: generalize ...
176

aed069df0   Alexander Duyck   ip_tunnel_core: i...
177
  	return 0;
2d26f0a3c   Eric Dumazet   ipv4: generalize ...
178
179
  }
  EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
ebe44f350   David S. Miller   ip_tunnel: Move i...
180
181
182
183
184
185
  
  /* Often modified stats are per cpu, other are shared (netdev->stats) */
  struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
  						struct rtnl_link_stats64 *tot)
  {
  	int i;
c24a59649   Alexander Duyck   ip_tunnel: Report...
186
  	netdev_stats_to_stats64(tot, &dev->stats);
ebe44f350   David S. Miller   ip_tunnel: Move i...
187
188
189
190
191
192
193
  	for_each_possible_cpu(i) {
  		const struct pcpu_sw_netstats *tstats =
  						   per_cpu_ptr(dev->tstats, i);
  		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
  		unsigned int start;
  
  		do {
57a7744e0   Eric W. Biederman   net: Replace u64_...
194
  			start = u64_stats_fetch_begin_irq(&tstats->syncp);
ebe44f350   David S. Miller   ip_tunnel: Move i...
195
196
197
198
  			rx_packets = tstats->rx_packets;
  			tx_packets = tstats->tx_packets;
  			rx_bytes = tstats->rx_bytes;
  			tx_bytes = tstats->tx_bytes;
57a7744e0   Eric W. Biederman   net: Replace u64_...
199
  		} while (u64_stats_fetch_retry_irq(&tstats->syncp, start));
ebe44f350   David S. Miller   ip_tunnel: Move i...
200
201
202
203
204
205
  
  		tot->rx_packets += rx_packets;
  		tot->tx_packets += tx_packets;
  		tot->rx_bytes   += rx_bytes;
  		tot->tx_bytes   += tx_bytes;
  	}
ebe44f350   David S. Miller   ip_tunnel: Move i...
206
207
208
  	return tot;
  }
  EXPORT_SYMBOL_GPL(ip_tunnel_get_stats64);
3093fbe7f   Thomas Graf   route: Per route ...
209

a1c234f95   Jiri Benc   lwtunnel: rename ...
210
211
212
213
214
215
  static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = {
  	[LWTUNNEL_IP_ID]	= { .type = NLA_U64 },
  	[LWTUNNEL_IP_DST]	= { .type = NLA_U32 },
  	[LWTUNNEL_IP_SRC]	= { .type = NLA_U32 },
  	[LWTUNNEL_IP_TTL]	= { .type = NLA_U8 },
  	[LWTUNNEL_IP_TOS]	= { .type = NLA_U8 },
a1c234f95   Jiri Benc   lwtunnel: rename ...
216
  	[LWTUNNEL_IP_FLAGS]	= { .type = NLA_U16 },
3093fbe7f   Thomas Graf   route: Per route ...
217
218
219
  };
  
  static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr,
127eb7cd3   Tom Herbert   lwt: Add cfg argu...
220
  			      unsigned int family, const void *cfg,
3093fbe7f   Thomas Graf   route: Per route ...
221
222
223
224
  			      struct lwtunnel_state **ts)
  {
  	struct ip_tunnel_info *tun_info;
  	struct lwtunnel_state *new_state;
a1c234f95   Jiri Benc   lwtunnel: rename ...
225
  	struct nlattr *tb[LWTUNNEL_IP_MAX + 1];
3093fbe7f   Thomas Graf   route: Per route ...
226
  	int err;
a1c234f95   Jiri Benc   lwtunnel: rename ...
227
  	err = nla_parse_nested(tb, LWTUNNEL_IP_MAX, attr, ip_tun_policy);
3093fbe7f   Thomas Graf   route: Per route ...
228
229
230
231
232
233
234
235
236
237
  	if (err < 0)
  		return err;
  
  	new_state = lwtunnel_state_alloc(sizeof(*tun_info));
  	if (!new_state)
  		return -ENOMEM;
  
  	new_state->type = LWTUNNEL_ENCAP_IP;
  
  	tun_info = lwt_tun_info(new_state);
a1c234f95   Jiri Benc   lwtunnel: rename ...
238
  	if (tb[LWTUNNEL_IP_ID])
30d3d83a7   Lance Richardson   ipv4: fix endiann...
239
  		tun_info->key.tun_id = nla_get_be64(tb[LWTUNNEL_IP_ID]);
3093fbe7f   Thomas Graf   route: Per route ...
240

a1c234f95   Jiri Benc   lwtunnel: rename ...
241
  	if (tb[LWTUNNEL_IP_DST])
7822ce73e   Haishuang Yan   netlink: use nla_...
242
  		tun_info->key.u.ipv4.dst = nla_get_in_addr(tb[LWTUNNEL_IP_DST]);
3093fbe7f   Thomas Graf   route: Per route ...
243

a1c234f95   Jiri Benc   lwtunnel: rename ...
244
  	if (tb[LWTUNNEL_IP_SRC])
7822ce73e   Haishuang Yan   netlink: use nla_...
245
  		tun_info->key.u.ipv4.src = nla_get_in_addr(tb[LWTUNNEL_IP_SRC]);
3093fbe7f   Thomas Graf   route: Per route ...
246

a1c234f95   Jiri Benc   lwtunnel: rename ...
247
  	if (tb[LWTUNNEL_IP_TTL])
7c383fb22   Jiri Benc   ip_tunnels: use t...
248
  		tun_info->key.ttl = nla_get_u8(tb[LWTUNNEL_IP_TTL]);
3093fbe7f   Thomas Graf   route: Per route ...
249

a1c234f95   Jiri Benc   lwtunnel: rename ...
250
  	if (tb[LWTUNNEL_IP_TOS])
7c383fb22   Jiri Benc   ip_tunnels: use t...
251
  		tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP_TOS]);
3093fbe7f   Thomas Graf   route: Per route ...
252

a1c234f95   Jiri Benc   lwtunnel: rename ...
253
  	if (tb[LWTUNNEL_IP_FLAGS])
30d3d83a7   Lance Richardson   ipv4: fix endiann...
254
  		tun_info->key.tun_flags = nla_get_be16(tb[LWTUNNEL_IP_FLAGS]);
3093fbe7f   Thomas Graf   route: Per route ...
255
256
  
  	tun_info->mode = IP_TUNNEL_INFO_TX;
3093fbe7f   Thomas Graf   route: Per route ...
257
258
259
260
261
262
263
264
265
266
267
  	tun_info->options_len = 0;
  
  	*ts = new_state;
  
  	return 0;
  }
  
  static int ip_tun_fill_encap_info(struct sk_buff *skb,
  				  struct lwtunnel_state *lwtstate)
  {
  	struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate);
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
268
269
  	if (nla_put_be64(skb, LWTUNNEL_IP_ID, tun_info->key.tun_id,
  			 LWTUNNEL_IP_PAD) ||
7822ce73e   Haishuang Yan   netlink: use nla_...
270
271
  	    nla_put_in_addr(skb, LWTUNNEL_IP_DST, tun_info->key.u.ipv4.dst) ||
  	    nla_put_in_addr(skb, LWTUNNEL_IP_SRC, tun_info->key.u.ipv4.src) ||
7c383fb22   Jiri Benc   ip_tunnels: use t...
272
273
  	    nla_put_u8(skb, LWTUNNEL_IP_TOS, tun_info->key.tos) ||
  	    nla_put_u8(skb, LWTUNNEL_IP_TTL, tun_info->key.ttl) ||
30d3d83a7   Lance Richardson   ipv4: fix endiann...
274
  	    nla_put_be16(skb, LWTUNNEL_IP_FLAGS, tun_info->key.tun_flags))
3093fbe7f   Thomas Graf   route: Per route ...
275
276
277
278
279
280
281
  		return -ENOMEM;
  
  	return 0;
  }
  
  static int ip_tun_encap_nlsize(struct lwtunnel_state *lwtstate)
  {
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
282
  	return nla_total_size_64bit(8)	/* LWTUNNEL_IP_ID */
a1c234f95   Jiri Benc   lwtunnel: rename ...
283
284
285
286
  		+ nla_total_size(4)	/* LWTUNNEL_IP_DST */
  		+ nla_total_size(4)	/* LWTUNNEL_IP_SRC */
  		+ nla_total_size(1)	/* LWTUNNEL_IP_TOS */
  		+ nla_total_size(1)	/* LWTUNNEL_IP_TTL */
a1c234f95   Jiri Benc   lwtunnel: rename ...
287
  		+ nla_total_size(2);	/* LWTUNNEL_IP_FLAGS */
3093fbe7f   Thomas Graf   route: Per route ...
288
  }
2d7984990   Jiri Benc   lwtunnel: ip tunn...
289
290
291
292
293
  static int ip_tun_cmp_encap(struct lwtunnel_state *a, struct lwtunnel_state *b)
  {
  	return memcmp(lwt_tun_info(a), lwt_tun_info(b),
  		      sizeof(struct ip_tunnel_info));
  }
3093fbe7f   Thomas Graf   route: Per route ...
294
295
296
297
  static const struct lwtunnel_encap_ops ip_tun_lwt_ops = {
  	.build_state = ip_tun_build_state,
  	.fill_encap = ip_tun_fill_encap_info,
  	.get_encap_size = ip_tun_encap_nlsize,
2d7984990   Jiri Benc   lwtunnel: ip tunn...
298
  	.cmp_encap = ip_tun_cmp_encap,
89c258862   Robert Shearman   net: Specify the ...
299
  	.owner = THIS_MODULE,
3093fbe7f   Thomas Graf   route: Per route ...
300
  };
32a2b002c   Jiri Benc   ipv6: route: per ...
301
302
303
304
305
306
  static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = {
  	[LWTUNNEL_IP6_ID]		= { .type = NLA_U64 },
  	[LWTUNNEL_IP6_DST]		= { .len = sizeof(struct in6_addr) },
  	[LWTUNNEL_IP6_SRC]		= { .len = sizeof(struct in6_addr) },
  	[LWTUNNEL_IP6_HOPLIMIT]		= { .type = NLA_U8 },
  	[LWTUNNEL_IP6_TC]		= { .type = NLA_U8 },
32a2b002c   Jiri Benc   ipv6: route: per ...
307
308
309
310
  	[LWTUNNEL_IP6_FLAGS]		= { .type = NLA_U16 },
  };
  
  static int ip6_tun_build_state(struct net_device *dev, struct nlattr *attr,
127eb7cd3   Tom Herbert   lwt: Add cfg argu...
311
  			       unsigned int family, const void *cfg,
32a2b002c   Jiri Benc   ipv6: route: per ...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  			       struct lwtunnel_state **ts)
  {
  	struct ip_tunnel_info *tun_info;
  	struct lwtunnel_state *new_state;
  	struct nlattr *tb[LWTUNNEL_IP6_MAX + 1];
  	int err;
  
  	err = nla_parse_nested(tb, LWTUNNEL_IP6_MAX, attr, ip6_tun_policy);
  	if (err < 0)
  		return err;
  
  	new_state = lwtunnel_state_alloc(sizeof(*tun_info));
  	if (!new_state)
  		return -ENOMEM;
  
  	new_state->type = LWTUNNEL_ENCAP_IP6;
  
  	tun_info = lwt_tun_info(new_state);
  
  	if (tb[LWTUNNEL_IP6_ID])
30d3d83a7   Lance Richardson   ipv4: fix endiann...
332
  		tun_info->key.tun_id = nla_get_be64(tb[LWTUNNEL_IP6_ID]);
32a2b002c   Jiri Benc   ipv6: route: per ...
333
334
335
336
337
338
339
340
341
342
343
344
  
  	if (tb[LWTUNNEL_IP6_DST])
  		tun_info->key.u.ipv6.dst = nla_get_in6_addr(tb[LWTUNNEL_IP6_DST]);
  
  	if (tb[LWTUNNEL_IP6_SRC])
  		tun_info->key.u.ipv6.src = nla_get_in6_addr(tb[LWTUNNEL_IP6_SRC]);
  
  	if (tb[LWTUNNEL_IP6_HOPLIMIT])
  		tun_info->key.ttl = nla_get_u8(tb[LWTUNNEL_IP6_HOPLIMIT]);
  
  	if (tb[LWTUNNEL_IP6_TC])
  		tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP6_TC]);
32a2b002c   Jiri Benc   ipv6: route: per ...
345
  	if (tb[LWTUNNEL_IP6_FLAGS])
30d3d83a7   Lance Richardson   ipv4: fix endiann...
346
  		tun_info->key.tun_flags = nla_get_be16(tb[LWTUNNEL_IP6_FLAGS]);
32a2b002c   Jiri Benc   ipv6: route: per ...
347

7f9562a1f   Jiri Benc   ip_tunnels: recor...
348
  	tun_info->mode = IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6;
32a2b002c   Jiri Benc   ipv6: route: per ...
349
350
351
352
353
354
355
356
357
358
359
  	tun_info->options_len = 0;
  
  	*ts = new_state;
  
  	return 0;
  }
  
  static int ip6_tun_fill_encap_info(struct sk_buff *skb,
  				   struct lwtunnel_state *lwtstate)
  {
  	struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate);
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
360
361
  	if (nla_put_be64(skb, LWTUNNEL_IP6_ID, tun_info->key.tun_id,
  			 LWTUNNEL_IP6_PAD) ||
32a2b002c   Jiri Benc   ipv6: route: per ...
362
363
  	    nla_put_in6_addr(skb, LWTUNNEL_IP6_DST, &tun_info->key.u.ipv6.dst) ||
  	    nla_put_in6_addr(skb, LWTUNNEL_IP6_SRC, &tun_info->key.u.ipv6.src) ||
995096a0a   Quentin Armitage   Fix returned tc a...
364
365
  	    nla_put_u8(skb, LWTUNNEL_IP6_TC, tun_info->key.tos) ||
  	    nla_put_u8(skb, LWTUNNEL_IP6_HOPLIMIT, tun_info->key.ttl) ||
30d3d83a7   Lance Richardson   ipv4: fix endiann...
366
  	    nla_put_be16(skb, LWTUNNEL_IP6_FLAGS, tun_info->key.tun_flags))
32a2b002c   Jiri Benc   ipv6: route: per ...
367
368
369
370
371
372
373
  		return -ENOMEM;
  
  	return 0;
  }
  
  static int ip6_tun_encap_nlsize(struct lwtunnel_state *lwtstate)
  {
b46f6ded9   Nicolas Dichtel   libnl: nla_put_be...
374
  	return nla_total_size_64bit(8)	/* LWTUNNEL_IP6_ID */
32a2b002c   Jiri Benc   ipv6: route: per ...
375
376
377
378
  		+ nla_total_size(16)	/* LWTUNNEL_IP6_DST */
  		+ nla_total_size(16)	/* LWTUNNEL_IP6_SRC */
  		+ nla_total_size(1)	/* LWTUNNEL_IP6_HOPLIMIT */
  		+ nla_total_size(1)	/* LWTUNNEL_IP6_TC */
32a2b002c   Jiri Benc   ipv6: route: per ...
379
380
381
382
383
384
385
386
  		+ nla_total_size(2);	/* LWTUNNEL_IP6_FLAGS */
  }
  
  static const struct lwtunnel_encap_ops ip6_tun_lwt_ops = {
  	.build_state = ip6_tun_build_state,
  	.fill_encap = ip6_tun_fill_encap_info,
  	.get_encap_size = ip6_tun_encap_nlsize,
  	.cmp_encap = ip_tun_cmp_encap,
89c258862   Robert Shearman   net: Specify the ...
387
  	.owner = THIS_MODULE,
32a2b002c   Jiri Benc   ipv6: route: per ...
388
  };
045a0fa0c   Thomas Graf   ip_tunnel: Call i...
389
  void __init ip_tunnel_core_init(void)
3093fbe7f   Thomas Graf   route: Per route ...
390
  {
fca5fdf67   Daniel Borkmann   ip_tunnels, bpf: ...
391
392
393
394
395
  	/* If you land here, make sure whether increasing ip_tunnel_info's
  	 * options_len is a reasonable choice with its usage in front ends
  	 * (f.e., it's part of flow keys, etc).
  	 */
  	BUILD_BUG_ON(IP_TUNNEL_OPTS_MAX != 255);
3093fbe7f   Thomas Graf   route: Per route ...
396
  	lwtunnel_encap_add_ops(&ip_tun_lwt_ops, LWTUNNEL_ENCAP_IP);
32a2b002c   Jiri Benc   ipv6: route: per ...
397
  	lwtunnel_encap_add_ops(&ip6_tun_lwt_ops, LWTUNNEL_ENCAP_IP6);
3093fbe7f   Thomas Graf   route: Per route ...
398
  }
e7030878f   Thomas Graf   fib: Add fib rule...
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  
  struct static_key ip_tunnel_metadata_cnt = STATIC_KEY_INIT_FALSE;
  EXPORT_SYMBOL(ip_tunnel_metadata_cnt);
  
  void ip_tunnel_need_metadata(void)
  {
  	static_key_slow_inc(&ip_tunnel_metadata_cnt);
  }
  EXPORT_SYMBOL_GPL(ip_tunnel_need_metadata);
  
  void ip_tunnel_unneed_metadata(void)
  {
  	static_key_slow_dec(&ip_tunnel_metadata_cnt);
  }
  EXPORT_SYMBOL_GPL(ip_tunnel_unneed_metadata);