@@ -38,6 +38,10 @@ static const int cfg_udp_src = 20000;
3838#define VXLAN_FLAGS 0x8
3939#define VXLAN_VNI 1
4040
41+ #ifndef NEXTHDR_DEST
42+ #define NEXTHDR_DEST 60
43+ #endif
44+
4145/* MPLS label 1000 with S bit (last label) set and ttl of 255. */
4246static const __u32 mpls_label = __bpf_constant_htonl (1000 << 12 |
4347 MPLS_LS_S_MASK | 0xff );
@@ -363,6 +367,61 @@ static __always_inline int __encap_ipv6(struct __sk_buff *skb, __u8 encap_proto,
363367 return TC_ACT_OK ;
364368}
365369
370+ static int encap_ipv6_ipip6 (struct __sk_buff * skb )
371+ {
372+ struct iphdr iph_inner ;
373+ struct v6hdr h_outer ;
374+ struct tcphdr tcph ;
375+ struct ethhdr eth ;
376+ __u64 flags ;
377+ int olen ;
378+
379+ if (bpf_skb_load_bytes (skb , ETH_HLEN , & iph_inner ,
380+ sizeof (iph_inner )) < 0 )
381+ return TC_ACT_OK ;
382+
383+ /* filter only packets we want */
384+ if (bpf_skb_load_bytes (skb , ETH_HLEN + (iph_inner .ihl << 2 ),
385+ & tcph , sizeof (tcph )) < 0 )
386+ return TC_ACT_OK ;
387+
388+ if (tcph .dest != __bpf_constant_htons (cfg_port ))
389+ return TC_ACT_OK ;
390+
391+ olen = sizeof (h_outer .ip );
392+
393+ flags = BPF_F_ADJ_ROOM_FIXED_GSO | BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 ;
394+
395+ /* add room between mac and network header */
396+ if (bpf_skb_adjust_room (skb , olen , BPF_ADJ_ROOM_MAC , flags ))
397+ return TC_ACT_SHOT ;
398+
399+ /* prepare new outer network header */
400+ memset (& h_outer .ip , 0 , sizeof (h_outer .ip ));
401+ h_outer .ip .version = 6 ;
402+ h_outer .ip .hop_limit = iph_inner .ttl ;
403+ h_outer .ip .saddr .s6_addr [1 ] = 0xfd ;
404+ h_outer .ip .saddr .s6_addr [15 ] = 1 ;
405+ h_outer .ip .daddr .s6_addr [1 ] = 0xfd ;
406+ h_outer .ip .daddr .s6_addr [15 ] = 2 ;
407+ h_outer .ip .payload_len = iph_inner .tot_len ;
408+ h_outer .ip .nexthdr = IPPROTO_IPIP ;
409+
410+ /* store new outer network header */
411+ if (bpf_skb_store_bytes (skb , ETH_HLEN , & h_outer , olen ,
412+ BPF_F_INVALIDATE_HASH ) < 0 )
413+ return TC_ACT_SHOT ;
414+
415+ /* update eth->h_proto */
416+ if (bpf_skb_load_bytes (skb , 0 , & eth , sizeof (eth )) < 0 )
417+ return TC_ACT_SHOT ;
418+ eth .h_proto = bpf_htons (ETH_P_IPV6 );
419+ if (bpf_skb_store_bytes (skb , 0 , & eth , sizeof (eth ), 0 ) < 0 )
420+ return TC_ACT_SHOT ;
421+
422+ return TC_ACT_OK ;
423+ }
424+
366425static __always_inline int encap_ipv6 (struct __sk_buff * skb , __u8 encap_proto ,
367426 __u16 l2_proto )
368427{
@@ -461,6 +520,15 @@ int __encap_ip6tnl_none(struct __sk_buff *skb)
461520 return TC_ACT_OK ;
462521}
463522
523+ SEC ("encap_ipip6_none" )
524+ int __encap_ipip6_none (struct __sk_buff * skb )
525+ {
526+ if (skb -> protocol == __bpf_constant_htons (ETH_P_IP ))
527+ return encap_ipv6_ipip6 (skb );
528+ else
529+ return TC_ACT_OK ;
530+ }
531+
464532SEC ("encap_ip6gre_none" )
465533int __encap_ip6gre_none (struct __sk_buff * skb )
466534{
@@ -528,13 +596,33 @@ int __encap_ip6vxlan_eth(struct __sk_buff *skb)
528596
529597static int decap_internal (struct __sk_buff * skb , int off , int len , char proto )
530598{
599+ __u64 flags = BPF_F_ADJ_ROOM_FIXED_GSO ;
600+ struct ipv6_opt_hdr ip6_opt_hdr ;
531601 struct gre_hdr greh ;
532602 struct udphdr udph ;
533603 int olen = len ;
534604
535605 switch (proto ) {
536606 case IPPROTO_IPIP :
607+ flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV4 ;
608+ break ;
537609 case IPPROTO_IPV6 :
610+ flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV6 ;
611+ break ;
612+ case NEXTHDR_DEST :
613+ if (bpf_skb_load_bytes (skb , off + len , & ip6_opt_hdr ,
614+ sizeof (ip6_opt_hdr )) < 0 )
615+ return TC_ACT_OK ;
616+ switch (ip6_opt_hdr .nexthdr ) {
617+ case IPPROTO_IPIP :
618+ flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV4 ;
619+ break ;
620+ case IPPROTO_IPV6 :
621+ flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV6 ;
622+ break ;
623+ default :
624+ return TC_ACT_OK ;
625+ }
538626 break ;
539627 case IPPROTO_GRE :
540628 olen += sizeof (struct gre_hdr );
@@ -569,8 +657,7 @@ static int decap_internal(struct __sk_buff *skb, int off, int len, char proto)
569657 return TC_ACT_OK ;
570658 }
571659
572- if (bpf_skb_adjust_room (skb , - olen , BPF_ADJ_ROOM_MAC ,
573- BPF_F_ADJ_ROOM_FIXED_GSO ))
660+ if (bpf_skb_adjust_room (skb , - olen , BPF_ADJ_ROOM_MAC , flags ))
574661 return TC_ACT_SHOT ;
575662
576663 return TC_ACT_OK ;
0 commit comments