History

ipv6: route: per route IP tunnel metadata via lightweight tunnel

Allow specification of per route IP tunnel instructions also for IPv6. This complements commit 3093fbe7ff4b ("route: Per route IP tunnel metadata via lightweight tunnel").

Jiri Benc committed 11 years ago

Commit 32a2b001 parent 904af042 files · +118 −0Browse files

Unified · Split

2 files
  1. include/uapi/linux/lwtunnel.h +16 −0
  2. net/ipv4/ip_tunnel_core.c +102 −0
include/uapi/linux/lwtunnel.h+16−0
@@ -8,6 +8,7 @@ enum lwtunnel_encap_types { · 7 unmodified lines
8 LWTUNNEL_ENCAP_MPLS,8 LWTUNNEL_ENCAP_MPLS,
9 LWTUNNEL_ENCAP_IP,9 LWTUNNEL_ENCAP_IP,
10 LWTUNNEL_ENCAP_ILA,10 LWTUNNEL_ENCAP_ILA,
11 LWTUNNEL_ENCAP_IP6,
11 __LWTUNNEL_ENCAP_MAX,12 __LWTUNNEL_ENCAP_MAX,
12};13};
13 14
@@ -28,4 +29,19 @@ enum lwtunnel_ip_t { · 14 unmodified lines
28 29
29#define LWTUNNEL_IP_MAX (__LWTUNNEL_IP_MAX - 1)30#define LWTUNNEL_IP_MAX (__LWTUNNEL_IP_MAX - 1)
30 31
32enum lwtunnel_ip6_t {
33 LWTUNNEL_IP6_UNSPEC,
34 LWTUNNEL_IP6_ID,
35 LWTUNNEL_IP6_DST,
36 LWTUNNEL_IP6_SRC,
37 LWTUNNEL_IP6_HOPLIMIT,
38 LWTUNNEL_IP6_TC,
39 LWTUNNEL_IP6_SPORT,
40 LWTUNNEL_IP6_DPORT,
41 LWTUNNEL_IP6_FLAGS,
42 __LWTUNNEL_IP6_MAX,
43};
44
45#define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1)
46
31#endif /* _UAPI_LWTUNNEL_H_ */47#endif /* _UAPI_LWTUNNEL_H_ */
net/ipv4/ip_tunnel_core.c+102−0
@@ -299,9 +299,111 @@ static const struct lwtunnel_encap_ops ip_tun_lwt_ops = { · 298 unmodified lines
299 .cmp_encap = ip_tun_cmp_encap,299 .cmp_encap = ip_tun_cmp_encap,
300};300};
301 301
302static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = {
303 [LWTUNNEL_IP6_ID] = { .type = NLA_U64 },
304 [LWTUNNEL_IP6_DST] = { .len = sizeof(struct in6_addr) },
305 [LWTUNNEL_IP6_SRC] = { .len = sizeof(struct in6_addr) },
306 [LWTUNNEL_IP6_HOPLIMIT] = { .type = NLA_U8 },
307 [LWTUNNEL_IP6_TC] = { .type = NLA_U8 },
308 [LWTUNNEL_IP6_SPORT] = { .type = NLA_U16 },
309 [LWTUNNEL_IP6_DPORT] = { .type = NLA_U16 },
310 [LWTUNNEL_IP6_FLAGS] = { .type = NLA_U16 },
311};
312
313static int ip6_tun_build_state(struct net_device *dev, struct nlattr *attr,
314 struct lwtunnel_state **ts)
315{
316 struct ip_tunnel_info *tun_info;
317 struct lwtunnel_state *new_state;
318 struct nlattr *tb[LWTUNNEL_IP6_MAX + 1];
319 int err;
320
321 err = nla_parse_nested(tb, LWTUNNEL_IP6_MAX, attr, ip6_tun_policy);
322 if (err < 0)
323 return err;
324
325 new_state = lwtunnel_state_alloc(sizeof(*tun_info));
326 if (!new_state)
327 return -ENOMEM;
328
329 new_state->type = LWTUNNEL_ENCAP_IP6;
330
331 tun_info = lwt_tun_info(new_state);
332
333 if (tb[LWTUNNEL_IP6_ID])
334 tun_info->key.tun_id = nla_get_u64(tb[LWTUNNEL_IP6_ID]);
335
336 if (tb[LWTUNNEL_IP6_DST])
337 tun_info->key.u.ipv6.dst = nla_get_in6_addr(tb[LWTUNNEL_IP6_DST]);
338
339 if (tb[LWTUNNEL_IP6_SRC])
340 tun_info->key.u.ipv6.src = nla_get_in6_addr(tb[LWTUNNEL_IP6_SRC]);
341
342 if (tb[LWTUNNEL_IP6_HOPLIMIT])
343 tun_info->key.ttl = nla_get_u8(tb[LWTUNNEL_IP6_HOPLIMIT]);
344
345 if (tb[LWTUNNEL_IP6_TC])
346 tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP6_TC]);
347
348 if (tb[LWTUNNEL_IP6_SPORT])
349 tun_info->key.tp_src = nla_get_be16(tb[LWTUNNEL_IP6_SPORT]);
350
351 if (tb[LWTUNNEL_IP6_DPORT])
352 tun_info->key.tp_dst = nla_get_be16(tb[LWTUNNEL_IP6_DPORT]);
353
354 if (tb[LWTUNNEL_IP6_FLAGS])
355 tun_info->key.tun_flags = nla_get_u16(tb[LWTUNNEL_IP6_FLAGS]);
356
357 tun_info->mode = IP_TUNNEL_INFO_TX;
358 tun_info->options = NULL;
359 tun_info->options_len = 0;
360
361 *ts = new_state;
362
363 return 0;
364}
365
366static int ip6_tun_fill_encap_info(struct sk_buff *skb,
367 struct lwtunnel_state *lwtstate)
368{
369 struct ip_tunnel_info *tun_info = lwt_tun_info(lwtstate);
370
371 if (nla_put_u64(skb, LWTUNNEL_IP6_ID, tun_info->key.tun_id) ||
372 nla_put_in6_addr(skb, LWTUNNEL_IP6_DST, &tun_info->key.u.ipv6.dst) ||
373 nla_put_in6_addr(skb, LWTUNNEL_IP6_SRC, &tun_info->key.u.ipv6.src) ||
374 nla_put_u8(skb, LWTUNNEL_IP6_HOPLIMIT, tun_info->key.tos) ||
375 nla_put_u8(skb, LWTUNNEL_IP6_TC, tun_info->key.ttl) ||
376 nla_put_u16(skb, LWTUNNEL_IP6_SPORT, tun_info->key.tp_src) ||
377 nla_put_u16(skb, LWTUNNEL_IP6_DPORT, tun_info->key.tp_dst) ||
378 nla_put_u16(skb, LWTUNNEL_IP6_FLAGS, tun_info->key.tun_flags))
379 return -ENOMEM;
380
381 return 0;
382}
383
384static int ip6_tun_encap_nlsize(struct lwtunnel_state *lwtstate)
385{
386 return nla_total_size(8) /* LWTUNNEL_IP6_ID */
387 + nla_total_size(16) /* LWTUNNEL_IP6_DST */
388 + nla_total_size(16) /* LWTUNNEL_IP6_SRC */
389 + nla_total_size(1) /* LWTUNNEL_IP6_HOPLIMIT */
390 + nla_total_size(1) /* LWTUNNEL_IP6_TC */
391 + nla_total_size(2) /* LWTUNNEL_IP6_SPORT */
392 + nla_total_size(2) /* LWTUNNEL_IP6_DPORT */
393 + nla_total_size(2); /* LWTUNNEL_IP6_FLAGS */
394}
395
396static const struct lwtunnel_encap_ops ip6_tun_lwt_ops = {
397 .build_state = ip6_tun_build_state,
398 .fill_encap = ip6_tun_fill_encap_info,
399 .get_encap_size = ip6_tun_encap_nlsize,
400 .cmp_encap = ip_tun_cmp_encap,
401};
402
302void __init ip_tunnel_core_init(void)403void __init ip_tunnel_core_init(void)
303{404{
304 lwtunnel_encap_add_ops(&ip_tun_lwt_ops, LWTUNNEL_ENCAP_IP);405 lwtunnel_encap_add_ops(&ip_tun_lwt_ops, LWTUNNEL_ENCAP_IP);
406 lwtunnel_encap_add_ops(&ip6_tun_lwt_ops, LWTUNNEL_ENCAP_IP6);
305}407}
306 408
307struct static_key ip_tunnel_metadata_cnt = STATIC_KEY_INIT_FALSE;409struct static_key ip_tunnel_metadata_cnt = STATIC_KEY_INIT_FALSE;