github.com/cilium/cilium@v1.16.2/bpf/tests/mcast_tests.c (about) 1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 /* Copyright Authors of Cilium */ 3 4 #include "bpf/ctx/skb.h" 5 #include "node_config.h" 6 #include "common.h" 7 #include "lib/endian.h" 8 #include "lib/common.h" 9 #include "lib/eth.h" 10 #include "pktgen.h" 11 12 #define ENABLE_IPV4 13 #define ENABLE_MULTICAST 1 14 #define ENCAP_IFINDEX 1 15 16 #include <linux/igmp.h> 17 #include <linux/in.h> 18 #include "../lib/mcast.h" 19 20 static __always_inline int default_packet(struct __ctx_buff *ctx) 21 { 22 struct pktgen builder; 23 struct ethhdr *eh; 24 struct iphdr *iph; 25 26 pktgen__init(&builder, ctx); 27 28 eh = pktgen__push_ethhdr(&builder); 29 if (!eh) 30 return TEST_ERROR; 31 32 iph = pktgen__push_default_iphdr(&builder); 33 if (!iph) 34 return TEST_ERROR; 35 36 pktgen__finish(&builder); 37 38 return 0; 39 } 40 41 static __always_inline int igmpv3_join_packet(struct __ctx_buff *ctx) 42 { 43 struct pktgen builder; 44 struct ethhdr *eh; 45 struct iphdr *iph; 46 struct igmpv3_report *rep; 47 48 pktgen__init(&builder, ctx); 49 50 eh = pktgen__push_ethhdr(&builder); 51 if (!eh) 52 return TEST_ERROR; 53 54 iph = pktgen__push_default_iphdr(&builder); 55 if (!iph) 56 return TEST_ERROR; 57 iph->saddr = 0x1010101;/* 1.1.1.1 */ 58 iph->daddr = 0x160000e0;/* 224.0.0.22 */ 59 iph->protocol = IPPROTO_IGMP; 60 61 rep = pktgen__push_rawhdr(&builder, sizeof(struct igmpv3_report), 62 PKT_LAYER_DATA); 63 if (!rep) 64 return TEST_ERROR; 65 66 rep->type = IGMPV3_HOST_MEMBERSHIP_REPORT; 67 68 pktgen__finish(&builder); 69 70 return 0; 71 } 72 73 CHECK("tc", "mcast_tests") 74 int test1_check(struct __ctx_buff *ctx) 75 { 76 test_init(); 77 78 /* test we correctly identify igmp packets */ 79 TEST("is_igmp", { 80 int ret; 81 struct iphdr *ip4; 82 83 ret = igmpv3_join_packet(ctx); 84 if (ret) 85 return ret; 86 87 void *data = (void *)(long)ctx->data; 88 void *data_end = (void *)(long)ctx->data_end; 89 90 if ((data + sizeof(struct ethhdr) + sizeof(struct iphdr)) > data_end) 91 test_fatal("ctx not big enough"); 92 93 ip4 = data + sizeof(struct ethhdr); 94 95 if (mcast_ipv4_is_igmp(ip4) != 1) 96 test_fatal("expected true for ipv4 protocol %x", ip4->protocol); 97 }); 98 99 /* test we do not incorrectly identify non igmp packets */ 100 TEST("is_not_igmp", { 101 int ret; 102 struct iphdr *ip4; 103 104 ret = default_packet(ctx); 105 if (ret) 106 return ret; 107 108 void *data = (void *)(long)ctx->data; 109 void *data_end = (void *)(long)ctx->data_end; 110 111 if ((data + sizeof(struct ethhdr) + sizeof(struct iphdr)) > data_end) 112 test_fatal("ctx not big enough"); 113 114 ip4 = data + sizeof(struct ethhdr); 115 116 if (mcast_ipv4_is_igmp(ip4) == 1) 117 test_fatal("expected false for ipv4 protocol %x", ip4->protocol); 118 }); 119 120 /* test we extract the correct IGMP type */ 121 TEST("igmp_type", { 122 int ret; 123 struct iphdr *ip4; 124 __s32 type = 0; 125 126 ret = igmpv3_join_packet(ctx); 127 if (ret) 128 return ret; 129 130 void *data = (void *)(long)ctx->data; 131 void *data_end = (void *)(long)ctx->data_end; 132 133 if ((data + sizeof(struct ethhdr) + sizeof(struct iphdr)) > data_end) 134 test_fatal("ctx not big enough"); 135 136 ip4 = data + sizeof(struct ethhdr); 137 138 type = mcast_ipv4_igmp_type(ip4, data, data_end); 139 if (type != IGMPV3_HOST_MEMBERSHIP_REPORT) 140 test_fatal("expected 0x22, got %x", type); 141 }); 142 143 test_finish(); 144 }