Skip to content

Commit 32a2b00

Browse files
Jiri Bencdavem330
authored andcommitted
ipv6: route: per route IP tunnel metadata via lightweight tunnel
Allow specification of per route IP tunnel instructions also for IPv6. This complements commit 3093fbe ("route: Per route IP tunnel metadata via lightweight tunnel"). Signed-off-by: Jiri Benc <[email protected]> CC: YOSHIFUJI Hideaki <[email protected]> Acked-by: Thomas Graf <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 904af04 commit 32a2b00

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

include/uapi/linux/lwtunnel.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ enum lwtunnel_encap_types {
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 {
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

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,111 @@ static const struct lwtunnel_encap_ops ip_tun_lwt_ops = {
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;

0 commit comments

Comments
 (0)