@@ -299,9 +299,111 @@ static const struct lwtunnel_encap_ops ip_tun_lwt_ops = {
299
299
.cmp_encap = ip_tun_cmp_encap ,
300
300
};
301
301
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
+
302
403
void __init ip_tunnel_core_init (void )
303
404
{
304
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
307
409
struct static_key ip_tunnel_metadata_cnt = STATIC_KEY_INIT_FALSE ;
0 commit comments