1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <linux/kernel.h>
3 #include <linux/init.h>
4 #include <linux/module.h>
5 #include <linux/seqlock.h>
6 #include <linux/netlink.h>
7 #include <linux/netfilter.h>
8 #include <linux/netfilter/nf_tables.h>
9 #include <net/netfilter/nf_tables.h>
10 #include <net/dst_metadata.h>
11 #include <net/ip_tunnels.h>
12 #include <net/vxlan.h>
13 #include <net/erspan.h>
14 #include <net/geneve.h>
17 enum nft_tunnel_keys key
:8;
18 enum nft_registers dreg
:8;
19 enum nft_tunnel_mode mode
:8;
22 static void nft_tunnel_get_eval(const struct nft_expr
*expr
,
23 struct nft_regs
*regs
,
24 const struct nft_pktinfo
*pkt
)
26 const struct nft_tunnel
*priv
= nft_expr_priv(expr
);
27 u32
*dest
= ®s
->data
[priv
->dreg
];
28 struct ip_tunnel_info
*tun_info
;
30 tun_info
= skb_tunnel_info(pkt
->skb
);
35 nft_reg_store8(dest
, false);
38 if (priv
->mode
== NFT_TUNNEL_MODE_NONE
||
39 (priv
->mode
== NFT_TUNNEL_MODE_RX
&&
40 !(tun_info
->mode
& IP_TUNNEL_INFO_TX
)) ||
41 (priv
->mode
== NFT_TUNNEL_MODE_TX
&&
42 (tun_info
->mode
& IP_TUNNEL_INFO_TX
)))
43 nft_reg_store8(dest
, true);
45 nft_reg_store8(dest
, false);
49 regs
->verdict
.code
= NFT_BREAK
;
52 if (priv
->mode
== NFT_TUNNEL_MODE_NONE
||
53 (priv
->mode
== NFT_TUNNEL_MODE_RX
&&
54 !(tun_info
->mode
& IP_TUNNEL_INFO_TX
)) ||
55 (priv
->mode
== NFT_TUNNEL_MODE_TX
&&
56 (tun_info
->mode
& IP_TUNNEL_INFO_TX
)))
57 *dest
= ntohl(tunnel_id_to_key32(tun_info
->key
.tun_id
));
59 regs
->verdict
.code
= NFT_BREAK
;
63 regs
->verdict
.code
= NFT_BREAK
;
67 static const struct nla_policy nft_tunnel_policy
[NFTA_TUNNEL_MAX
+ 1] = {
68 [NFTA_TUNNEL_KEY
] = { .type
= NLA_U32
},
69 [NFTA_TUNNEL_DREG
] = { .type
= NLA_U32
},
70 [NFTA_TUNNEL_MODE
] = { .type
= NLA_U32
},
73 static int nft_tunnel_get_init(const struct nft_ctx
*ctx
,
74 const struct nft_expr
*expr
,
75 const struct nlattr
* const tb
[])
77 struct nft_tunnel
*priv
= nft_expr_priv(expr
);
80 if (!tb
[NFTA_TUNNEL_KEY
] ||
81 !tb
[NFTA_TUNNEL_DREG
])
84 priv
->key
= ntohl(nla_get_be32(tb
[NFTA_TUNNEL_KEY
]));
96 priv
->dreg
= nft_parse_register(tb
[NFTA_TUNNEL_DREG
]);
98 if (tb
[NFTA_TUNNEL_MODE
]) {
99 priv
->mode
= ntohl(nla_get_be32(tb
[NFTA_TUNNEL_MODE
]));
100 if (priv
->mode
> NFT_TUNNEL_MODE_MAX
)
103 priv
->mode
= NFT_TUNNEL_MODE_NONE
;
106 return nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
107 NFT_DATA_VALUE
, len
);
110 static int nft_tunnel_get_dump(struct sk_buff
*skb
,
111 const struct nft_expr
*expr
)
113 const struct nft_tunnel
*priv
= nft_expr_priv(expr
);
115 if (nla_put_be32(skb
, NFTA_TUNNEL_KEY
, htonl(priv
->key
)))
116 goto nla_put_failure
;
117 if (nft_dump_register(skb
, NFTA_TUNNEL_DREG
, priv
->dreg
))
118 goto nla_put_failure
;
119 if (nla_put_be32(skb
, NFTA_TUNNEL_MODE
, htonl(priv
->mode
)))
120 goto nla_put_failure
;
127 static struct nft_expr_type nft_tunnel_type
;
128 static const struct nft_expr_ops nft_tunnel_get_ops
= {
129 .type
= &nft_tunnel_type
,
130 .size
= NFT_EXPR_SIZE(sizeof(struct nft_tunnel
)),
131 .eval
= nft_tunnel_get_eval
,
132 .init
= nft_tunnel_get_init
,
133 .dump
= nft_tunnel_get_dump
,
136 static struct nft_expr_type nft_tunnel_type __read_mostly
= {
138 .ops
= &nft_tunnel_get_ops
,
139 .policy
= nft_tunnel_policy
,
140 .maxattr
= NFTA_TUNNEL_MAX
,
141 .owner
= THIS_MODULE
,
144 struct nft_tunnel_opts
{
146 struct vxlan_metadata vxlan
;
147 struct erspan_metadata erspan
;
148 u8 data
[IP_TUNNEL_OPTS_MAX
];
154 struct nft_tunnel_obj
{
155 struct metadata_dst
*md
;
156 struct nft_tunnel_opts opts
;
159 static const struct nla_policy nft_tunnel_ip_policy
[NFTA_TUNNEL_KEY_IP_MAX
+ 1] = {
160 [NFTA_TUNNEL_KEY_IP_SRC
] = { .type
= NLA_U32
},
161 [NFTA_TUNNEL_KEY_IP_DST
] = { .type
= NLA_U32
},
164 static int nft_tunnel_obj_ip_init(const struct nft_ctx
*ctx
,
165 const struct nlattr
*attr
,
166 struct ip_tunnel_info
*info
)
168 struct nlattr
*tb
[NFTA_TUNNEL_KEY_IP_MAX
+ 1];
171 err
= nla_parse_nested_deprecated(tb
, NFTA_TUNNEL_KEY_IP_MAX
, attr
,
172 nft_tunnel_ip_policy
, NULL
);
176 if (!tb
[NFTA_TUNNEL_KEY_IP_DST
])
179 if (tb
[NFTA_TUNNEL_KEY_IP_SRC
])
180 info
->key
.u
.ipv4
.src
= nla_get_be32(tb
[NFTA_TUNNEL_KEY_IP_SRC
]);
181 if (tb
[NFTA_TUNNEL_KEY_IP_DST
])
182 info
->key
.u
.ipv4
.dst
= nla_get_be32(tb
[NFTA_TUNNEL_KEY_IP_DST
]);
187 static const struct nla_policy nft_tunnel_ip6_policy
[NFTA_TUNNEL_KEY_IP6_MAX
+ 1] = {
188 [NFTA_TUNNEL_KEY_IP6_SRC
] = { .len
= sizeof(struct in6_addr
), },
189 [NFTA_TUNNEL_KEY_IP6_DST
] = { .len
= sizeof(struct in6_addr
), },
190 [NFTA_TUNNEL_KEY_IP6_FLOWLABEL
] = { .type
= NLA_U32
, }
193 static int nft_tunnel_obj_ip6_init(const struct nft_ctx
*ctx
,
194 const struct nlattr
*attr
,
195 struct ip_tunnel_info
*info
)
197 struct nlattr
*tb
[NFTA_TUNNEL_KEY_IP6_MAX
+ 1];
200 err
= nla_parse_nested_deprecated(tb
, NFTA_TUNNEL_KEY_IP6_MAX
, attr
,
201 nft_tunnel_ip6_policy
, NULL
);
205 if (!tb
[NFTA_TUNNEL_KEY_IP6_DST
])
208 if (tb
[NFTA_TUNNEL_KEY_IP6_SRC
]) {
209 memcpy(&info
->key
.u
.ipv6
.src
,
210 nla_data(tb
[NFTA_TUNNEL_KEY_IP6_SRC
]),
211 sizeof(struct in6_addr
));
213 if (tb
[NFTA_TUNNEL_KEY_IP6_DST
]) {
214 memcpy(&info
->key
.u
.ipv6
.dst
,
215 nla_data(tb
[NFTA_TUNNEL_KEY_IP6_DST
]),
216 sizeof(struct in6_addr
));
218 if (tb
[NFTA_TUNNEL_KEY_IP6_FLOWLABEL
])
219 info
->key
.label
= nla_get_be32(tb
[NFTA_TUNNEL_KEY_IP6_FLOWLABEL
]);
221 info
->mode
|= IP_TUNNEL_INFO_IPV6
;
226 static const struct nla_policy nft_tunnel_opts_vxlan_policy
[NFTA_TUNNEL_KEY_VXLAN_MAX
+ 1] = {
227 [NFTA_TUNNEL_KEY_VXLAN_GBP
] = { .type
= NLA_U32
},
230 static int nft_tunnel_obj_vxlan_init(const struct nlattr
*attr
,
231 struct nft_tunnel_opts
*opts
)
233 struct nlattr
*tb
[NFTA_TUNNEL_KEY_VXLAN_MAX
+ 1];
236 err
= nla_parse_nested_deprecated(tb
, NFTA_TUNNEL_KEY_VXLAN_MAX
, attr
,
237 nft_tunnel_opts_vxlan_policy
, NULL
);
241 if (!tb
[NFTA_TUNNEL_KEY_VXLAN_GBP
])
244 opts
->u
.vxlan
.gbp
= ntohl(nla_get_be32(tb
[NFTA_TUNNEL_KEY_VXLAN_GBP
]));
246 opts
->len
= sizeof(struct vxlan_metadata
);
247 opts
->flags
= TUNNEL_VXLAN_OPT
;
252 static const struct nla_policy nft_tunnel_opts_erspan_policy
[NFTA_TUNNEL_KEY_ERSPAN_MAX
+ 1] = {
253 [NFTA_TUNNEL_KEY_ERSPAN_VERSION
] = { .type
= NLA_U32
},
254 [NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX
] = { .type
= NLA_U32
},
255 [NFTA_TUNNEL_KEY_ERSPAN_V2_DIR
] = { .type
= NLA_U8
},
256 [NFTA_TUNNEL_KEY_ERSPAN_V2_HWID
] = { .type
= NLA_U8
},
259 static int nft_tunnel_obj_erspan_init(const struct nlattr
*attr
,
260 struct nft_tunnel_opts
*opts
)
262 struct nlattr
*tb
[NFTA_TUNNEL_KEY_ERSPAN_MAX
+ 1];
266 err
= nla_parse_nested_deprecated(tb
, NFTA_TUNNEL_KEY_ERSPAN_MAX
,
267 attr
, nft_tunnel_opts_erspan_policy
,
272 if (!tb
[NFTA_TUNNEL_KEY_ERSPAN_VERSION
])
275 version
= ntohl(nla_get_be32(tb
[NFTA_TUNNEL_KEY_ERSPAN_VERSION
]));
278 if (!tb
[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX
])
281 opts
->u
.erspan
.u
.index
=
282 nla_get_be32(tb
[NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX
]);
284 case ERSPAN_VERSION2
:
285 if (!tb
[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR
] ||
286 !tb
[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID
])
289 hwid
= nla_get_u8(tb
[NFTA_TUNNEL_KEY_ERSPAN_V2_HWID
]);
290 dir
= nla_get_u8(tb
[NFTA_TUNNEL_KEY_ERSPAN_V2_DIR
]);
292 set_hwid(&opts
->u
.erspan
.u
.md2
, hwid
);
293 opts
->u
.erspan
.u
.md2
.dir
= dir
;
298 opts
->u
.erspan
.version
= version
;
300 opts
->len
= sizeof(struct erspan_metadata
);
301 opts
->flags
= TUNNEL_ERSPAN_OPT
;
306 static const struct nla_policy nft_tunnel_opts_geneve_policy
[NFTA_TUNNEL_KEY_GENEVE_MAX
+ 1] = {
307 [NFTA_TUNNEL_KEY_GENEVE_CLASS
] = { .type
= NLA_U16
},
308 [NFTA_TUNNEL_KEY_GENEVE_TYPE
] = { .type
= NLA_U8
},
309 [NFTA_TUNNEL_KEY_GENEVE_DATA
] = { .type
= NLA_BINARY
, .len
= 128 },
312 static int nft_tunnel_obj_geneve_init(const struct nlattr
*attr
,
313 struct nft_tunnel_opts
*opts
)
315 struct geneve_opt
*opt
= (struct geneve_opt
*)opts
->u
.data
+ opts
->len
;
316 struct nlattr
*tb
[NFTA_TUNNEL_KEY_GENEVE_MAX
+ 1];
319 err
= nla_parse_nested(tb
, NFTA_TUNNEL_KEY_GENEVE_MAX
, attr
,
320 nft_tunnel_opts_geneve_policy
, NULL
);
324 if (!tb
[NFTA_TUNNEL_KEY_GENEVE_CLASS
] ||
325 !tb
[NFTA_TUNNEL_KEY_GENEVE_TYPE
] ||
326 !tb
[NFTA_TUNNEL_KEY_GENEVE_DATA
])
329 attr
= tb
[NFTA_TUNNEL_KEY_GENEVE_DATA
];
330 data_len
= nla_len(attr
);
334 opts
->len
+= sizeof(*opt
) + data_len
;
335 if (opts
->len
> IP_TUNNEL_OPTS_MAX
)
338 memcpy(opt
->opt_data
, nla_data(attr
), data_len
);
339 opt
->length
= data_len
/ 4;
340 opt
->opt_class
= nla_get_be16(tb
[NFTA_TUNNEL_KEY_GENEVE_CLASS
]);
341 opt
->type
= nla_get_u8(tb
[NFTA_TUNNEL_KEY_GENEVE_TYPE
]);
342 opts
->flags
= TUNNEL_GENEVE_OPT
;
347 static const struct nla_policy nft_tunnel_opts_policy
[NFTA_TUNNEL_KEY_OPTS_MAX
+ 1] = {
348 [NFTA_TUNNEL_KEY_OPTS_UNSPEC
] = {
349 .strict_start_type
= NFTA_TUNNEL_KEY_OPTS_GENEVE
},
350 [NFTA_TUNNEL_KEY_OPTS_VXLAN
] = { .type
= NLA_NESTED
, },
351 [NFTA_TUNNEL_KEY_OPTS_ERSPAN
] = { .type
= NLA_NESTED
, },
352 [NFTA_TUNNEL_KEY_OPTS_GENEVE
] = { .type
= NLA_NESTED
, },
355 static int nft_tunnel_obj_opts_init(const struct nft_ctx
*ctx
,
356 const struct nlattr
*attr
,
357 struct ip_tunnel_info
*info
,
358 struct nft_tunnel_opts
*opts
)
360 int err
, rem
, type
= 0;
363 err
= nla_validate_nested_deprecated(attr
, NFTA_TUNNEL_KEY_OPTS_MAX
,
364 nft_tunnel_opts_policy
, NULL
);
368 nla_for_each_attr(nla
, nla_data(attr
), nla_len(attr
), rem
) {
369 switch (nla_type(nla
)) {
370 case NFTA_TUNNEL_KEY_OPTS_VXLAN
:
373 err
= nft_tunnel_obj_vxlan_init(nla
, opts
);
376 type
= TUNNEL_VXLAN_OPT
;
378 case NFTA_TUNNEL_KEY_OPTS_ERSPAN
:
381 err
= nft_tunnel_obj_erspan_init(nla
, opts
);
384 type
= TUNNEL_ERSPAN_OPT
;
386 case NFTA_TUNNEL_KEY_OPTS_GENEVE
:
387 if (type
&& type
!= TUNNEL_GENEVE_OPT
)
389 err
= nft_tunnel_obj_geneve_init(nla
, opts
);
392 type
= TUNNEL_GENEVE_OPT
;
402 static const struct nla_policy nft_tunnel_key_policy
[NFTA_TUNNEL_KEY_MAX
+ 1] = {
403 [NFTA_TUNNEL_KEY_IP
] = { .type
= NLA_NESTED
, },
404 [NFTA_TUNNEL_KEY_IP6
] = { .type
= NLA_NESTED
, },
405 [NFTA_TUNNEL_KEY_ID
] = { .type
= NLA_U32
, },
406 [NFTA_TUNNEL_KEY_FLAGS
] = { .type
= NLA_U32
, },
407 [NFTA_TUNNEL_KEY_TOS
] = { .type
= NLA_U8
, },
408 [NFTA_TUNNEL_KEY_TTL
] = { .type
= NLA_U8
, },
409 [NFTA_TUNNEL_KEY_SPORT
] = { .type
= NLA_U16
, },
410 [NFTA_TUNNEL_KEY_DPORT
] = { .type
= NLA_U16
, },
411 [NFTA_TUNNEL_KEY_OPTS
] = { .type
= NLA_NESTED
, },
414 static int nft_tunnel_obj_init(const struct nft_ctx
*ctx
,
415 const struct nlattr
* const tb
[],
416 struct nft_object
*obj
)
418 struct nft_tunnel_obj
*priv
= nft_obj_data(obj
);
419 struct ip_tunnel_info info
;
420 struct metadata_dst
*md
;
423 if (!tb
[NFTA_TUNNEL_KEY_ID
])
426 memset(&info
, 0, sizeof(info
));
427 info
.mode
= IP_TUNNEL_INFO_TX
;
428 info
.key
.tun_id
= key32_to_tunnel_id(nla_get_be32(tb
[NFTA_TUNNEL_KEY_ID
]));
429 info
.key
.tun_flags
= TUNNEL_KEY
| TUNNEL_CSUM
| TUNNEL_NOCACHE
;
431 if (tb
[NFTA_TUNNEL_KEY_IP
]) {
432 err
= nft_tunnel_obj_ip_init(ctx
, tb
[NFTA_TUNNEL_KEY_IP
], &info
);
435 } else if (tb
[NFTA_TUNNEL_KEY_IP6
]) {
436 err
= nft_tunnel_obj_ip6_init(ctx
, tb
[NFTA_TUNNEL_KEY_IP6
], &info
);
443 if (tb
[NFTA_TUNNEL_KEY_SPORT
]) {
444 info
.key
.tp_src
= nla_get_be16(tb
[NFTA_TUNNEL_KEY_SPORT
]);
446 if (tb
[NFTA_TUNNEL_KEY_DPORT
]) {
447 info
.key
.tp_dst
= nla_get_be16(tb
[NFTA_TUNNEL_KEY_DPORT
]);
450 if (tb
[NFTA_TUNNEL_KEY_FLAGS
]) {
453 tun_flags
= ntohl(nla_get_be32(tb
[NFTA_TUNNEL_KEY_FLAGS
]));
454 if (tun_flags
& ~NFT_TUNNEL_F_MASK
)
457 if (tun_flags
& NFT_TUNNEL_F_ZERO_CSUM_TX
)
458 info
.key
.tun_flags
&= ~TUNNEL_CSUM
;
459 if (tun_flags
& NFT_TUNNEL_F_DONT_FRAGMENT
)
460 info
.key
.tun_flags
|= TUNNEL_DONT_FRAGMENT
;
461 if (tun_flags
& NFT_TUNNEL_F_SEQ_NUMBER
)
462 info
.key
.tun_flags
|= TUNNEL_SEQ
;
464 if (tb
[NFTA_TUNNEL_KEY_TOS
])
465 info
.key
.tos
= nla_get_u8(tb
[NFTA_TUNNEL_KEY_TOS
]);
466 if (tb
[NFTA_TUNNEL_KEY_TTL
])
467 info
.key
.ttl
= nla_get_u8(tb
[NFTA_TUNNEL_KEY_TTL
]);
469 info
.key
.ttl
= U8_MAX
;
471 if (tb
[NFTA_TUNNEL_KEY_OPTS
]) {
472 err
= nft_tunnel_obj_opts_init(ctx
, tb
[NFTA_TUNNEL_KEY_OPTS
],
478 md
= metadata_dst_alloc(priv
->opts
.len
, METADATA_IP_TUNNEL
, GFP_KERNEL
);
482 memcpy(&md
->u
.tun_info
, &info
, sizeof(info
));
483 #ifdef CONFIG_DST_CACHE
484 err
= dst_cache_init(&md
->u
.tun_info
.dst_cache
, GFP_KERNEL
);
486 metadata_dst_free(md
);
490 ip_tunnel_info_opts_set(&md
->u
.tun_info
, &priv
->opts
.u
, priv
->opts
.len
,
497 static inline void nft_tunnel_obj_eval(struct nft_object
*obj
,
498 struct nft_regs
*regs
,
499 const struct nft_pktinfo
*pkt
)
501 struct nft_tunnel_obj
*priv
= nft_obj_data(obj
);
502 struct sk_buff
*skb
= pkt
->skb
;
505 dst_hold((struct dst_entry
*) priv
->md
);
506 skb_dst_set(skb
, (struct dst_entry
*) priv
->md
);
509 static int nft_tunnel_ip_dump(struct sk_buff
*skb
, struct ip_tunnel_info
*info
)
513 if (info
->mode
& IP_TUNNEL_INFO_IPV6
) {
514 nest
= nla_nest_start_noflag(skb
, NFTA_TUNNEL_KEY_IP6
);
518 if (nla_put_in6_addr(skb
, NFTA_TUNNEL_KEY_IP6_SRC
,
519 &info
->key
.u
.ipv6
.src
) < 0 ||
520 nla_put_in6_addr(skb
, NFTA_TUNNEL_KEY_IP6_DST
,
521 &info
->key
.u
.ipv6
.dst
) < 0 ||
522 nla_put_be32(skb
, NFTA_TUNNEL_KEY_IP6_FLOWLABEL
,
524 nla_nest_cancel(skb
, nest
);
528 nla_nest_end(skb
, nest
);
530 nest
= nla_nest_start_noflag(skb
, NFTA_TUNNEL_KEY_IP
);
534 if (nla_put_in_addr(skb
, NFTA_TUNNEL_KEY_IP_SRC
,
535 info
->key
.u
.ipv4
.src
) < 0 ||
536 nla_put_in_addr(skb
, NFTA_TUNNEL_KEY_IP_DST
,
537 info
->key
.u
.ipv4
.dst
) < 0) {
538 nla_nest_cancel(skb
, nest
);
542 nla_nest_end(skb
, nest
);
548 static int nft_tunnel_opts_dump(struct sk_buff
*skb
,
549 struct nft_tunnel_obj
*priv
)
551 struct nft_tunnel_opts
*opts
= &priv
->opts
;
552 struct nlattr
*nest
, *inner
;
554 nest
= nla_nest_start_noflag(skb
, NFTA_TUNNEL_KEY_OPTS
);
558 if (opts
->flags
& TUNNEL_VXLAN_OPT
) {
559 inner
= nla_nest_start_noflag(skb
, NFTA_TUNNEL_KEY_OPTS_VXLAN
);
562 if (nla_put_be32(skb
, NFTA_TUNNEL_KEY_VXLAN_GBP
,
563 htonl(opts
->u
.vxlan
.gbp
)))
565 nla_nest_end(skb
, inner
);
566 } else if (opts
->flags
& TUNNEL_ERSPAN_OPT
) {
567 inner
= nla_nest_start_noflag(skb
, NFTA_TUNNEL_KEY_OPTS_ERSPAN
);
570 if (nla_put_be32(skb
, NFTA_TUNNEL_KEY_ERSPAN_VERSION
,
571 htonl(opts
->u
.erspan
.version
)))
573 switch (opts
->u
.erspan
.version
) {
575 if (nla_put_be32(skb
, NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX
,
576 opts
->u
.erspan
.u
.index
))
579 case ERSPAN_VERSION2
:
580 if (nla_put_u8(skb
, NFTA_TUNNEL_KEY_ERSPAN_V2_HWID
,
581 get_hwid(&opts
->u
.erspan
.u
.md2
)) ||
582 nla_put_u8(skb
, NFTA_TUNNEL_KEY_ERSPAN_V2_DIR
,
583 opts
->u
.erspan
.u
.md2
.dir
))
587 nla_nest_end(skb
, inner
);
588 } else if (opts
->flags
& TUNNEL_GENEVE_OPT
) {
589 struct geneve_opt
*opt
;
592 inner
= nla_nest_start_noflag(skb
, NFTA_TUNNEL_KEY_OPTS_GENEVE
);
595 while (opts
->len
> offset
) {
596 opt
= (struct geneve_opt
*)opts
->u
.data
+ offset
;
597 if (nla_put_be16(skb
, NFTA_TUNNEL_KEY_GENEVE_CLASS
,
599 nla_put_u8(skb
, NFTA_TUNNEL_KEY_GENEVE_TYPE
,
601 nla_put(skb
, NFTA_TUNNEL_KEY_GENEVE_DATA
,
602 opt
->length
* 4, opt
->opt_data
))
604 offset
+= sizeof(*opt
) + opt
->length
* 4;
606 nla_nest_end(skb
, inner
);
608 nla_nest_end(skb
, nest
);
612 nla_nest_cancel(skb
, inner
);
614 nla_nest_cancel(skb
, nest
);
618 static int nft_tunnel_ports_dump(struct sk_buff
*skb
,
619 struct ip_tunnel_info
*info
)
621 if (nla_put_be16(skb
, NFTA_TUNNEL_KEY_SPORT
, info
->key
.tp_src
) < 0 ||
622 nla_put_be16(skb
, NFTA_TUNNEL_KEY_DPORT
, info
->key
.tp_dst
) < 0)
628 static int nft_tunnel_flags_dump(struct sk_buff
*skb
,
629 struct ip_tunnel_info
*info
)
633 if (info
->key
.tun_flags
& TUNNEL_DONT_FRAGMENT
)
634 flags
|= NFT_TUNNEL_F_DONT_FRAGMENT
;
635 if (!(info
->key
.tun_flags
& TUNNEL_CSUM
))
636 flags
|= NFT_TUNNEL_F_ZERO_CSUM_TX
;
637 if (info
->key
.tun_flags
& TUNNEL_SEQ
)
638 flags
|= NFT_TUNNEL_F_SEQ_NUMBER
;
640 if (nla_put_be32(skb
, NFTA_TUNNEL_KEY_FLAGS
, htonl(flags
)) < 0)
646 static int nft_tunnel_obj_dump(struct sk_buff
*skb
,
647 struct nft_object
*obj
, bool reset
)
649 struct nft_tunnel_obj
*priv
= nft_obj_data(obj
);
650 struct ip_tunnel_info
*info
= &priv
->md
->u
.tun_info
;
652 if (nla_put_be32(skb
, NFTA_TUNNEL_KEY_ID
,
653 tunnel_id_to_key32(info
->key
.tun_id
)) ||
654 nft_tunnel_ip_dump(skb
, info
) < 0 ||
655 nft_tunnel_ports_dump(skb
, info
) < 0 ||
656 nft_tunnel_flags_dump(skb
, info
) < 0 ||
657 nla_put_u8(skb
, NFTA_TUNNEL_KEY_TOS
, info
->key
.tos
) ||
658 nla_put_u8(skb
, NFTA_TUNNEL_KEY_TTL
, info
->key
.ttl
) ||
659 nft_tunnel_opts_dump(skb
, priv
) < 0)
660 goto nla_put_failure
;
668 static void nft_tunnel_obj_destroy(const struct nft_ctx
*ctx
,
669 struct nft_object
*obj
)
671 struct nft_tunnel_obj
*priv
= nft_obj_data(obj
);
673 metadata_dst_free(priv
->md
);
676 static struct nft_object_type nft_tunnel_obj_type
;
677 static const struct nft_object_ops nft_tunnel_obj_ops
= {
678 .type
= &nft_tunnel_obj_type
,
679 .size
= sizeof(struct nft_tunnel_obj
),
680 .eval
= nft_tunnel_obj_eval
,
681 .init
= nft_tunnel_obj_init
,
682 .destroy
= nft_tunnel_obj_destroy
,
683 .dump
= nft_tunnel_obj_dump
,
686 static struct nft_object_type nft_tunnel_obj_type __read_mostly
= {
687 .type
= NFT_OBJECT_TUNNEL
,
688 .ops
= &nft_tunnel_obj_ops
,
689 .maxattr
= NFTA_TUNNEL_KEY_MAX
,
690 .policy
= nft_tunnel_key_policy
,
691 .owner
= THIS_MODULE
,
694 static int __init
nft_tunnel_module_init(void)
698 err
= nft_register_expr(&nft_tunnel_type
);
702 err
= nft_register_obj(&nft_tunnel_obj_type
);
704 nft_unregister_expr(&nft_tunnel_type
);
709 static void __exit
nft_tunnel_module_exit(void)
711 nft_unregister_obj(&nft_tunnel_obj_type
);
712 nft_unregister_expr(&nft_tunnel_type
);
715 module_init(nft_tunnel_module_init
);
716 module_exit(nft_tunnel_module_exit
);
718 MODULE_LICENSE("GPL");
719 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
720 MODULE_ALIAS_NFT_EXPR("tunnel");
721 MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_TUNNEL
);