34
34
#include <net/netns/generic.h>
35
35
#include <net/rtnetlink.h>
36
36
#include <net/dst_metadata.h>
37
+ #include <net/geneve.h>
37
38
38
39
const struct ip_tunnel_encap_ops __rcu *
39
40
iptun_encaps [MAX_IPTUN_ENCAP_OPS ] __read_mostly ;
@@ -218,31 +219,125 @@ static const struct nla_policy ip_tun_policy[LWTUNNEL_IP_MAX + 1] = {
218
219
[LWTUNNEL_IP_TTL ] = { .type = NLA_U8 },
219
220
[LWTUNNEL_IP_TOS ] = { .type = NLA_U8 },
220
221
[LWTUNNEL_IP_FLAGS ] = { .type = NLA_U16 },
222
+ [LWTUNNEL_IP_OPTS ] = { .type = NLA_NESTED },
221
223
};
222
224
225
+ static const struct nla_policy ip_opts_policy [LWTUNNEL_IP_OPTS_MAX + 1 ] = {
226
+ [LWTUNNEL_IP_OPTS_GENEVE ] = { .type = NLA_NESTED },
227
+ };
228
+
229
+ static const struct nla_policy
230
+ geneve_opt_policy [LWTUNNEL_IP_OPT_GENEVE_MAX + 1 ] = {
231
+ [LWTUNNEL_IP_OPT_GENEVE_CLASS ] = { .type = NLA_U16 },
232
+ [LWTUNNEL_IP_OPT_GENEVE_TYPE ] = { .type = NLA_U8 },
233
+ [LWTUNNEL_IP_OPT_GENEVE_DATA ] = { .type = NLA_BINARY , .len = 128 },
234
+ };
235
+
236
+ static int ip_tun_parse_opts_geneve (struct nlattr * attr ,
237
+ struct ip_tunnel_info * info ,
238
+ struct netlink_ext_ack * extack )
239
+ {
240
+ struct nlattr * tb [LWTUNNEL_IP_OPT_GENEVE_MAX + 1 ];
241
+ int data_len , err ;
242
+
243
+ err = nla_parse_nested_deprecated (tb , LWTUNNEL_IP_OPT_GENEVE_MAX ,
244
+ attr , geneve_opt_policy , extack );
245
+ if (err )
246
+ return err ;
247
+
248
+ if (!tb [LWTUNNEL_IP_OPT_GENEVE_CLASS ] ||
249
+ !tb [LWTUNNEL_IP_OPT_GENEVE_TYPE ] ||
250
+ !tb [LWTUNNEL_IP_OPT_GENEVE_DATA ])
251
+ return - EINVAL ;
252
+
253
+ attr = tb [LWTUNNEL_IP_OPT_GENEVE_DATA ];
254
+ data_len = nla_len (attr );
255
+ if (data_len % 4 )
256
+ return - EINVAL ;
257
+
258
+ if (info ) {
259
+ struct geneve_opt * opt = ip_tunnel_info_opts (info );
260
+
261
+ memcpy (opt -> opt_data , nla_data (attr ), data_len );
262
+ opt -> length = data_len / 4 ;
263
+ attr = tb [LWTUNNEL_IP_OPT_GENEVE_CLASS ];
264
+ opt -> opt_class = nla_get_be16 (attr );
265
+ attr = tb [LWTUNNEL_IP_OPT_GENEVE_TYPE ];
266
+ opt -> type = nla_get_u8 (attr );
267
+ info -> key .tun_flags |= TUNNEL_GENEVE_OPT ;
268
+ }
269
+
270
+ return sizeof (struct geneve_opt ) + data_len ;
271
+ }
272
+
273
+ static int ip_tun_parse_opts (struct nlattr * attr , struct ip_tunnel_info * info ,
274
+ struct netlink_ext_ack * extack )
275
+ {
276
+ struct nlattr * tb [LWTUNNEL_IP_OPTS_MAX + 1 ];
277
+ int err ;
278
+
279
+ if (!attr )
280
+ return 0 ;
281
+
282
+ err = nla_parse_nested_deprecated (tb , LWTUNNEL_IP_OPTS_MAX , attr ,
283
+ ip_opts_policy , extack );
284
+ if (err )
285
+ return err ;
286
+
287
+ if (tb [LWTUNNEL_IP_OPTS_GENEVE ])
288
+ err = ip_tun_parse_opts_geneve (tb [LWTUNNEL_IP_OPTS_GENEVE ],
289
+ info , extack );
290
+ else
291
+ err = - EINVAL ;
292
+
293
+ return err ;
294
+ }
295
+
296
+ static int ip_tun_get_optlen (struct nlattr * attr ,
297
+ struct netlink_ext_ack * extack )
298
+ {
299
+ return ip_tun_parse_opts (attr , NULL , extack );
300
+ }
301
+
302
+ static int ip_tun_set_opts (struct nlattr * attr , struct ip_tunnel_info * info ,
303
+ struct netlink_ext_ack * extack )
304
+ {
305
+ return ip_tun_parse_opts (attr , info , extack );
306
+ }
307
+
223
308
static int ip_tun_build_state (struct nlattr * attr ,
224
309
unsigned int family , const void * cfg ,
225
310
struct lwtunnel_state * * ts ,
226
311
struct netlink_ext_ack * extack )
227
312
{
228
- struct ip_tunnel_info * tun_info ;
229
- struct lwtunnel_state * new_state ;
230
313
struct nlattr * tb [LWTUNNEL_IP_MAX + 1 ];
231
- int err ;
314
+ struct lwtunnel_state * new_state ;
315
+ struct ip_tunnel_info * tun_info ;
316
+ int err , opt_len ;
232
317
233
318
err = nla_parse_nested_deprecated (tb , LWTUNNEL_IP_MAX , attr ,
234
319
ip_tun_policy , extack );
235
320
if (err < 0 )
236
321
return err ;
237
322
238
- new_state = lwtunnel_state_alloc (sizeof (* tun_info ));
323
+ opt_len = ip_tun_get_optlen (tb [LWTUNNEL_IP_OPTS ], extack );
324
+ if (opt_len < 0 )
325
+ return opt_len ;
326
+
327
+ new_state = lwtunnel_state_alloc (sizeof (* tun_info ) + opt_len );
239
328
if (!new_state )
240
329
return - ENOMEM ;
241
330
242
331
new_state -> type = LWTUNNEL_ENCAP_IP ;
243
332
244
333
tun_info = lwt_tun_info (new_state );
245
334
335
+ err = ip_tun_set_opts (tb [LWTUNNEL_IP_OPTS ], tun_info , extack );
336
+ if (err < 0 ) {
337
+ lwtstate_free (new_state );
338
+ return err ;
339
+ }
340
+
246
341
#ifdef CONFIG_DST_CACHE
247
342
err = dst_cache_init (& tun_info -> dst_cache , GFP_KERNEL );
248
343
if (err ) {
@@ -267,10 +362,10 @@ static int ip_tun_build_state(struct nlattr *attr,
267
362
tun_info -> key .tos = nla_get_u8 (tb [LWTUNNEL_IP_TOS ]);
268
363
269
364
if (tb [LWTUNNEL_IP_FLAGS ])
270
- tun_info -> key .tun_flags = nla_get_be16 (tb [LWTUNNEL_IP_FLAGS ]);
365
+ tun_info -> key .tun_flags | = nla_get_be16 (tb [LWTUNNEL_IP_FLAGS ]);
271
366
272
367
tun_info -> mode = IP_TUNNEL_INFO_TX ;
273
- tun_info -> options_len = 0 ;
368
+ tun_info -> options_len = opt_len ;
274
369
275
370
* ts = new_state ;
276
371
@@ -286,6 +381,54 @@ static void ip_tun_destroy_state(struct lwtunnel_state *lwtstate)
286
381
#endif
287
382
}
288
383
384
+ static int ip_tun_fill_encap_opts_geneve (struct sk_buff * skb ,
385
+ struct ip_tunnel_info * tun_info )
386
+ {
387
+ struct geneve_opt * opt ;
388
+ struct nlattr * nest ;
389
+
390
+ nest = nla_nest_start_noflag (skb , LWTUNNEL_IP_OPTS_GENEVE );
391
+ if (!nest )
392
+ return - ENOMEM ;
393
+
394
+ opt = ip_tunnel_info_opts (tun_info );
395
+ if (nla_put_be16 (skb , LWTUNNEL_IP_OPT_GENEVE_CLASS , opt -> opt_class ) ||
396
+ nla_put_u8 (skb , LWTUNNEL_IP_OPT_GENEVE_TYPE , opt -> type ) ||
397
+ nla_put (skb , LWTUNNEL_IP_OPT_GENEVE_DATA , opt -> length * 4 ,
398
+ opt -> opt_data )) {
399
+ nla_nest_cancel (skb , nest );
400
+ return - ENOMEM ;
401
+ }
402
+
403
+ nla_nest_end (skb , nest );
404
+ return 0 ;
405
+ }
406
+
407
+ static int ip_tun_fill_encap_opts (struct sk_buff * skb , int type ,
408
+ struct ip_tunnel_info * tun_info )
409
+ {
410
+ struct nlattr * nest ;
411
+ int err = 0 ;
412
+
413
+ if (!(tun_info -> key .tun_flags & TUNNEL_GENEVE_OPT ))
414
+ return 0 ;
415
+
416
+ nest = nla_nest_start_noflag (skb , type );
417
+ if (!nest )
418
+ return - ENOMEM ;
419
+
420
+ if (tun_info -> key .tun_flags & TUNNEL_GENEVE_OPT )
421
+ err = ip_tun_fill_encap_opts_geneve (skb , tun_info );
422
+
423
+ if (err ) {
424
+ nla_nest_cancel (skb , nest );
425
+ return err ;
426
+ }
427
+
428
+ nla_nest_end (skb , nest );
429
+ return 0 ;
430
+ }
431
+
289
432
static int ip_tun_fill_encap_info (struct sk_buff * skb ,
290
433
struct lwtunnel_state * lwtstate )
291
434
{
@@ -297,20 +440,44 @@ static int ip_tun_fill_encap_info(struct sk_buff *skb,
297
440
nla_put_in_addr (skb , LWTUNNEL_IP_SRC , tun_info -> key .u .ipv4 .src ) ||
298
441
nla_put_u8 (skb , LWTUNNEL_IP_TOS , tun_info -> key .tos ) ||
299
442
nla_put_u8 (skb , LWTUNNEL_IP_TTL , tun_info -> key .ttl ) ||
300
- nla_put_be16 (skb , LWTUNNEL_IP_FLAGS , tun_info -> key .tun_flags ))
443
+ nla_put_be16 (skb , LWTUNNEL_IP_FLAGS , tun_info -> key .tun_flags ) ||
444
+ ip_tun_fill_encap_opts (skb , LWTUNNEL_IP_OPTS , tun_info ))
301
445
return - ENOMEM ;
302
446
303
447
return 0 ;
304
448
}
305
449
450
+ static int ip_tun_opts_nlsize (struct ip_tunnel_info * info )
451
+ {
452
+ int opt_len ;
453
+
454
+ if (!(info -> key .tun_flags & TUNNEL_GENEVE_OPT ))
455
+ return 0 ;
456
+
457
+ opt_len = nla_total_size (0 ); /* LWTUNNEL_IP_OPTS */
458
+ if (info -> key .tun_flags & TUNNEL_GENEVE_OPT ) {
459
+ struct geneve_opt * opt = ip_tunnel_info_opts (info );
460
+
461
+ opt_len += nla_total_size (0 ) /* LWTUNNEL_IP_OPTS_GENEVE */
462
+ + nla_total_size (2 ) /* OPT_GENEVE_CLASS */
463
+ + nla_total_size (1 ) /* OPT_GENEVE_TYPE */
464
+ + nla_total_size (opt -> length * 4 );
465
+ /* OPT_GENEVE_DATA */
466
+ }
467
+
468
+ return opt_len ;
469
+ }
470
+
306
471
static int ip_tun_encap_nlsize (struct lwtunnel_state * lwtstate )
307
472
{
308
473
return nla_total_size_64bit (8 ) /* LWTUNNEL_IP_ID */
309
474
+ nla_total_size (4 ) /* LWTUNNEL_IP_DST */
310
475
+ nla_total_size (4 ) /* LWTUNNEL_IP_SRC */
311
476
+ nla_total_size (1 ) /* LWTUNNEL_IP_TOS */
312
477
+ nla_total_size (1 ) /* LWTUNNEL_IP_TTL */
313
- + nla_total_size (2 ); /* LWTUNNEL_IP_FLAGS */
478
+ + nla_total_size (2 ) /* LWTUNNEL_IP_FLAGS */
479
+ + ip_tun_opts_nlsize (lwt_tun_info (lwtstate ));
480
+ /* LWTUNNEL_IP_OPTS */
314
481
}
315
482
316
483
static int ip_tun_cmp_encap (struct lwtunnel_state * a , struct lwtunnel_state * b )
@@ -348,24 +515,34 @@ static int ip6_tun_build_state(struct nlattr *attr,
348
515
struct lwtunnel_state * * ts ,
349
516
struct netlink_ext_ack * extack )
350
517
{
351
- struct ip_tunnel_info * tun_info ;
352
- struct lwtunnel_state * new_state ;
353
518
struct nlattr * tb [LWTUNNEL_IP6_MAX + 1 ];
354
- int err ;
519
+ struct lwtunnel_state * new_state ;
520
+ struct ip_tunnel_info * tun_info ;
521
+ int err , opt_len ;
355
522
356
523
err = nla_parse_nested_deprecated (tb , LWTUNNEL_IP6_MAX , attr ,
357
524
ip6_tun_policy , extack );
358
525
if (err < 0 )
359
526
return err ;
360
527
361
- new_state = lwtunnel_state_alloc (sizeof (* tun_info ));
528
+ opt_len = ip_tun_get_optlen (tb [LWTUNNEL_IP6_OPTS ], extack );
529
+ if (opt_len < 0 )
530
+ return opt_len ;
531
+
532
+ new_state = lwtunnel_state_alloc (sizeof (* tun_info ) + opt_len );
362
533
if (!new_state )
363
534
return - ENOMEM ;
364
535
365
536
new_state -> type = LWTUNNEL_ENCAP_IP6 ;
366
537
367
538
tun_info = lwt_tun_info (new_state );
368
539
540
+ err = ip_tun_set_opts (tb [LWTUNNEL_IP6_OPTS ], tun_info , extack );
541
+ if (err < 0 ) {
542
+ lwtstate_free (new_state );
543
+ return err ;
544
+ }
545
+
369
546
if (tb [LWTUNNEL_IP6_ID ])
370
547
tun_info -> key .tun_id = nla_get_be64 (tb [LWTUNNEL_IP6_ID ]);
371
548
@@ -382,10 +559,10 @@ static int ip6_tun_build_state(struct nlattr *attr,
382
559
tun_info -> key .tos = nla_get_u8 (tb [LWTUNNEL_IP6_TC ]);
383
560
384
561
if (tb [LWTUNNEL_IP6_FLAGS ])
385
- tun_info -> key .tun_flags = nla_get_be16 (tb [LWTUNNEL_IP6_FLAGS ]);
562
+ tun_info -> key .tun_flags | = nla_get_be16 (tb [LWTUNNEL_IP6_FLAGS ]);
386
563
387
564
tun_info -> mode = IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6 ;
388
- tun_info -> options_len = 0 ;
565
+ tun_info -> options_len = opt_len ;
389
566
390
567
* ts = new_state ;
391
568
@@ -403,7 +580,8 @@ static int ip6_tun_fill_encap_info(struct sk_buff *skb,
403
580
nla_put_in6_addr (skb , LWTUNNEL_IP6_SRC , & tun_info -> key .u .ipv6 .src ) ||
404
581
nla_put_u8 (skb , LWTUNNEL_IP6_TC , tun_info -> key .tos ) ||
405
582
nla_put_u8 (skb , LWTUNNEL_IP6_HOPLIMIT , tun_info -> key .ttl ) ||
406
- nla_put_be16 (skb , LWTUNNEL_IP6_FLAGS , tun_info -> key .tun_flags ))
583
+ nla_put_be16 (skb , LWTUNNEL_IP6_FLAGS , tun_info -> key .tun_flags ) ||
584
+ ip_tun_fill_encap_opts (skb , LWTUNNEL_IP6_OPTS , tun_info ))
407
585
return - ENOMEM ;
408
586
409
587
return 0 ;
@@ -416,7 +594,9 @@ static int ip6_tun_encap_nlsize(struct lwtunnel_state *lwtstate)
416
594
+ nla_total_size (16 ) /* LWTUNNEL_IP6_SRC */
417
595
+ nla_total_size (1 ) /* LWTUNNEL_IP6_HOPLIMIT */
418
596
+ nla_total_size (1 ) /* LWTUNNEL_IP6_TC */
419
- + nla_total_size (2 ); /* LWTUNNEL_IP6_FLAGS */
597
+ + nla_total_size (2 ) /* LWTUNNEL_IP6_FLAGS */
598
+ + ip_tun_opts_nlsize (lwt_tun_info (lwtstate ));
599
+ /* LWTUNNEL_IP6_OPTS */
420
600
}
421
601
422
602
static const struct lwtunnel_encap_ops ip6_tun_lwt_ops = {
0 commit comments