1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2023 Isovalent */ 3 #include <stdbool.h> 4 5 #include <linux/bpf.h> 6 #include <linux/if_ether.h> 7 #include <linux/stddef.h> 8 #include <linux/if_packet.h> 9 #include <bpf/bpf_endian.h> 10 #include <bpf/bpf_helpers.h> 11 12 char LICENSE[] SEC("license") = "GPL"; 13 14 bool seen_tc1; 15 bool seen_tc2; 16 bool seen_tc3; 17 bool seen_tc4; 18 bool seen_tc5; 19 bool seen_tc6; 20 bool seen_tc7; 21 22 bool set_type; 23 24 bool seen_eth; 25 bool seen_host; 26 bool seen_mcast; 27 28 SEC("tc/ingress") 29 int tc1(struct __sk_buff *skb) 30 { 31 struct ethhdr eth = {}; 32 33 if (skb->protocol != __bpf_constant_htons(ETH_P_IP)) 34 goto out; 35 if (bpf_skb_load_bytes(skb, 0, ð, sizeof(eth))) 36 goto out; 37 seen_eth = eth.h_proto == bpf_htons(ETH_P_IP); 38 seen_host = skb->pkt_type == PACKET_HOST; 39 if (seen_host && set_type) { 40 eth.h_dest[0] = 4; 41 if (bpf_skb_store_bytes(skb, 0, ð, sizeof(eth), 0)) 42 goto fail; 43 bpf_skb_change_type(skb, PACKET_MULTICAST); 44 } 45 out: 46 seen_tc1 = true; 47 fail: 48 return TCX_NEXT; 49 } 50 51 SEC("tc/egress") 52 int tc2(struct __sk_buff *skb) 53 { 54 seen_tc2 = true; 55 return TCX_NEXT; 56 } 57 58 SEC("tc/egress") 59 int tc3(struct __sk_buff *skb) 60 { 61 seen_tc3 = true; 62 return TCX_NEXT; 63 } 64 65 SEC("tc/egress") 66 int tc4(struct __sk_buff *skb) 67 { 68 seen_tc4 = true; 69 return TCX_NEXT; 70 } 71 72 SEC("tc/egress") 73 int tc5(struct __sk_buff *skb) 74 { 75 seen_tc5 = true; 76 return TCX_PASS; 77 } 78 79 SEC("tc/egress") 80 int tc6(struct __sk_buff *skb) 81 { 82 seen_tc6 = true; 83 return TCX_PASS; 84 } 85 86 SEC("tc/ingress") 87 int tc7(struct __sk_buff *skb) 88 { 89 struct ethhdr eth = {}; 90 91 if (skb->protocol != __bpf_constant_htons(ETH_P_IP)) 92 goto out; 93 if (bpf_skb_load_bytes(skb, 0, ð, sizeof(eth))) 94 goto out; 95 if (eth.h_dest[0] == 4 && set_type) { 96 seen_mcast = skb->pkt_type == PACKET_MULTICAST; 97 bpf_skb_change_type(skb, PACKET_HOST); 98 } 99 out: 100 seen_tc7 = true; 101 return TCX_PASS; 102 } 103