mirror of
				https://github.com/xdp-project/bpf-examples.git
				synced 2024-05-06 15:54:53 +00:00 
			
		
		
		
	Makes sure the ethertype is set correctly depending on the type of encapsulation. Fixes #2. Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
		
			
				
	
	
		
			72 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			72 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #define NEXTHDR_IPV6		41
 | |
| 
 | |
| #ifdef IPV6
 | |
| static void encap_ipv6(volatile void *data, volatile void *data_end)
 | |
| {
 | |
| 	volatile struct ipv6hdr *ip6h;
 | |
| 	volatile struct ethhdr *eth;
 | |
| 	size_t len;
 | |
| 
 | |
| 	struct ipv6hdr encap_hdr = {
 | |
| 		.version = 6,
 | |
| 		.nexthdr = NEXTHDR_IPV6,
 | |
| 		.hop_limit = 16,
 | |
| 		.saddr = { .s6_addr = { 0xfc, 0x00, 0xde, 0xad, 0xca, 0xfe,
 | |
| 					0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
 | |
| 					0x00, 0x00, 0x00, 0x02 } },
 | |
| 		.daddr = { .s6_addr = { 0xfc, 0x00, 0xde, 0xad, 0xca, 0xfe,
 | |
| 					0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
 | |
| 					0x00, 0x00, 0x00, 0x01 } },
 | |
| 	};
 | |
| 
 | |
| 	eth = data;
 | |
| 	ip6h = (void *)(eth +1);
 | |
| 	if (ip6h + 1 > data_end)
 | |
| 		return;
 | |
| 
 | |
| 	eth->h_proto = bpf_htons(ETH_P_IPV6);
 | |
| 	*ip6h = encap_hdr;
 | |
| 
 | |
| 	len = (data_end - data);
 | |
| 	ip6h->payload_len = bpf_htons(len - sizeof(struct ethhdr) - sizeof(*ip6h));
 | |
| }
 | |
| #else
 | |
| 
 | |
| static __always_inline __u16 csum_fold_helper(__u32 csum)
 | |
| {
 | |
| 	__u32 sum;
 | |
| 	sum = (csum >> 16) + (csum & 0xffff);
 | |
| 	sum += (sum >> 16);
 | |
| 	return ~sum;
 | |
| }
 | |
| 
 | |
| static void encap_ipv4(volatile void *data, volatile void *data_end)
 | |
| {
 | |
| 	volatile struct ethhdr *eth;
 | |
| 	volatile struct iphdr *iph;
 | |
| 	size_t len;
 | |
| 
 | |
| 	struct iphdr encap_hdr = {
 | |
| 		.version = 4,
 | |
| 		.ihl = 5,
 | |
| 		.protocol = NEXTHDR_IPV6,
 | |
| 		.ttl = 16,
 | |
| 		.saddr = bpf_htonl(0x0a0b0202),
 | |
| 		.daddr = bpf_htonl(0x0a0b0201),
 | |
| 	};
 | |
| 
 | |
| 	eth = data;
 | |
| 	iph = (void *)(eth +1);
 | |
| 	if (iph + 1 > data_end)
 | |
| 		return;
 | |
| 
 | |
| 	eth->h_proto = bpf_htons(ETH_P_IP);
 | |
| 	*iph = encap_hdr;
 | |
| 
 | |
| 	len = (data_end - data);
 | |
| 	iph->tot_len = bpf_htons(len - sizeof(struct ethhdr));
 | |
| 	iph->check = csum_fold_helper(bpf_csum_diff((__be32 *)iph, 0, (__be32 *)iph, sizeof(*iph), 0));
 | |
| }
 | |
| 
 | |
| #endif
 |