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
88 LWTUNNEL_ENCAP_MPLS,
99 LWTUNNEL_ENCAP_IP,
1010 LWTUNNEL_ENCAP_ILA,
11+ LWTUNNEL_ENCAP_IP6,
1112 __LWTUNNEL_ENCAP_MAX,
1213 };
1314
@@ -28,4 +29,19 @@ enum lwtunnel_ip_t { · 14 unmodified lines
2829
2930 #define LWTUNNEL_IP_MAX (__LWTUNNEL_IP_MAX - 1)
3031
32+enum 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+
3147 #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
299299 .cmp_encap = ip_tun_cmp_encap,
300300 };
301301
302+static 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+
313+static 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+
366+static 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+
384+static 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+
396+static 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+
302403 void __init ip_tunnel_core_init(void)
303404 {
304405 lwtunnel_encap_add_ops(&ip_tun_lwt_ops, LWTUNNEL_ENCAP_IP);
406+ lwtunnel_encap_add_ops(&ip6_tun_lwt_ops, LWTUNNEL_ENCAP_IP6);
305407 }
306408
307409 struct static_key ip_tunnel_metadata_cnt = STATIC_KEY_INIT_FALSE;