bpf: Abstract loop unrolling pragmas in BPF selftests
authorJose E. Marchesi <jose.marchesi@oracle.com>
Thu, 8 Feb 2024 20:36:12 +0000 (21:36 +0100)
committerAndrii Nakryiko <andrii@kernel.org>
Tue, 13 Feb 2024 19:17:30 +0000 (11:17 -0800)
[Changes from V1:
- Avoid conflict by rebasing with latest master.]

Some BPF tests use loop unrolling compiler pragmas that are clang
specific and not supported by GCC.  These pragmas, along with their
GCC equivalences are:

  #pragma clang loop unroll_count(N)
  #pragma GCC unroll N

  #pragma clang loop unroll(full)
  #pragma GCC unroll 65534

  #pragma clang loop unroll(disable)
  #pragma GCC unroll 1

  #pragma unroll [aka #pragma clang loop unroll(enable)]
  There is no GCC equivalence to this pragma.  It enables unrolling on
  loops that the compiler would not ordinarily unroll even with
  -O2|-funroll-loops, but it is not equivalent to full unrolling
  either.

This patch adds a new header progs/bpf_compiler.h that defines the
following macros, which correspond to each pair of compiler-specific
pragmas above:

  __pragma_loop_unroll_count(N)
  __pragma_loop_unroll_full
  __pragma_loop_no_unroll
  __pragma_loop_unroll

The selftests using loop unrolling pragmas are then changed to include
the header and use these macros in place of the explicit pragmas.

Tested in bpf-next master.
No regressions.

Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/bpf/20240208203612.29611-1-jose.marchesi@oracle.com
19 files changed:
tools/testing/selftests/bpf/progs/bpf_compiler.h [new file with mode: 0644]
tools/testing/selftests/bpf/progs/iters.c
tools/testing/selftests/bpf/progs/loop4.c
tools/testing/selftests/bpf/progs/profiler.inc.h
tools/testing/selftests/bpf/progs/pyperf.h
tools/testing/selftests/bpf/progs/strobemeta.h
tools/testing/selftests/bpf/progs/test_cls_redirect.c
tools/testing/selftests/bpf/progs/test_lwt_seg6local.c
tools/testing/selftests/bpf/progs/test_seg6_loop.c
tools/testing/selftests/bpf/progs/test_skb_ctx.c
tools/testing/selftests/bpf/progs/test_sysctl_loop1.c
tools/testing/selftests/bpf/progs/test_sysctl_loop2.c
tools/testing/selftests/bpf/progs/test_sysctl_prog.c
tools/testing/selftests/bpf/progs/test_tc_tunnel.c
tools/testing/selftests/bpf/progs/test_xdp.c
tools/testing/selftests/bpf/progs/test_xdp_loop.c
tools/testing/selftests/bpf/progs/test_xdp_noinline.c
tools/testing/selftests/bpf/progs/xdp_synproxy_kern.c
tools/testing/selftests/bpf/progs/xdping_kern.c

diff --git a/tools/testing/selftests/bpf/progs/bpf_compiler.h b/tools/testing/selftests/bpf/progs/bpf_compiler.h
new file mode 100644 (file)
index 0000000..a7c343d
--- /dev/null
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __BPF_COMPILER_H__
+#define __BPF_COMPILER_H__
+
+#define DO_PRAGMA_(X) _Pragma(#X)
+
+#if __clang__
+#define __pragma_loop_unroll DO_PRAGMA_(clang loop unroll(enable))
+#else
+/* In GCC -funroll-loops, which is enabled with -O2, should have the
+   same impact than the loop-unroll-enable pragma above.  */
+#define __pragma_loop_unroll
+#endif
+
+#if __clang__
+#define __pragma_loop_unroll_count(N) DO_PRAGMA_(clang loop unroll_count(N))
+#else
+#define __pragma_loop_unroll_count(N) DO_PRAGMA_(GCC unroll N)
+#endif
+
+#if __clang__
+#define __pragma_loop_unroll_full DO_PRAGMA_(clang loop unroll(full))
+#else
+#define __pragma_loop_unroll_full DO_PRAGMA_(GCC unroll 65534)
+#endif
+
+#if __clang__
+#define __pragma_loop_no_unroll DO_PRAGMA_(clang loop unroll(disable))
+#else
+#define __pragma_loop_no_unroll DO_PRAGMA_(GCC unroll 1)
+#endif
+
+#endif
index 225f02dd66d066f740a144fa09a00f1ad60051f1..3db416606f2f0e13536ba805221fd85f577f729a 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
 #include "bpf_misc.h"
+#include "bpf_compiler.h"
 
 #define ARRAY_SIZE(x) (int)(sizeof(x) / sizeof((x)[0]))
 
@@ -183,7 +184,7 @@ int iter_pragma_unroll_loop(const void *ctx)
        MY_PID_GUARD();
 
        bpf_iter_num_new(&it, 0, 2);
-#pragma nounroll
+       __pragma_loop_no_unroll
        for (i = 0; i < 3; i++) {
                v = bpf_iter_num_next(&it);
                bpf_printk("ITER_BASIC: E3 VAL: i=%d v=%d", i, v ? *v : -1);
@@ -238,7 +239,7 @@ int iter_multiple_sequential_loops(const void *ctx)
        bpf_iter_num_destroy(&it);
 
        bpf_iter_num_new(&it, 0, 2);
-#pragma nounroll
+       __pragma_loop_no_unroll
        for (i = 0; i < 3; i++) {
                v = bpf_iter_num_next(&it);
                bpf_printk("ITER_BASIC: E3 VAL: i=%d v=%d", i, v ? *v : -1);
index b35337926d665b3a07e49850ea8644403e0c83a4..0de0357f57ccb7306f80ddc57e5d0dccc1c846d4 100644 (file)
@@ -3,6 +3,8 @@
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
 
+#include "bpf_compiler.h"
+
 char _license[] SEC("license") = "GPL";
 
 SEC("socket")
@@ -10,7 +12,7 @@ int combinations(volatile struct __sk_buff* skb)
 {
        int ret = 0, i;
 
-#pragma nounroll
+       __pragma_loop_no_unroll
        for (i = 0; i < 20; i++)
                if (skb->len)
                        ret |= 1 << i;
index de3b6e4e4d0a76712109479e5821815a8f6f8189..6957d9f2805eb3009fe972d04e137ab157b05c94 100644 (file)
@@ -8,6 +8,7 @@
 #include "profiler.h"
 #include "err.h"
 #include "bpf_experimental.h"
+#include "bpf_compiler.h"
 
 #ifndef NULL
 #define NULL 0
@@ -169,7 +170,7 @@ static INLINE int get_var_spid_index(struct var_kill_data_arr_t* arr_struct,
                                     int spid)
 {
 #ifdef UNROLL
-#pragma unroll
+       __pragma_loop_unroll
 #endif
        for (int i = 0; i < ARRAY_SIZE(arr_struct->array); i++)
                if (arr_struct->array[i].meta.pid == spid)
@@ -185,7 +186,7 @@ static INLINE void populate_ancestors(struct task_struct* task,
 
        ancestors_data->num_ancestors = 0;
 #ifdef UNROLL
-#pragma unroll
+       __pragma_loop_unroll
 #endif
        for (num_ancestors = 0; num_ancestors < MAX_ANCESTORS; num_ancestors++) {
                parent = BPF_CORE_READ(parent, real_parent);
@@ -212,7 +213,7 @@ static INLINE void* read_full_cgroup_path(struct kernfs_node* cgroup_node,
        size_t filepart_length;
 
 #ifdef UNROLL
-#pragma unroll
+       __pragma_loop_unroll
 #endif
        for (int i = 0; i < MAX_CGROUPS_PATH_DEPTH; i++) {
                filepart_length =
@@ -261,7 +262,7 @@ static INLINE void* populate_cgroup_info(struct cgroup_data_t* cgroup_data,
                int cgrp_id = bpf_core_enum_value(enum cgroup_subsys_id___local,
                                                  pids_cgrp_id___local);
 #ifdef UNROLL
-#pragma unroll
+               __pragma_loop_unroll
 #endif
                for (int i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
                        struct cgroup_subsys_state* subsys =
@@ -402,7 +403,7 @@ static INLINE int trace_var_sys_kill(void* ctx, int tpid, int sig)
                        if (kill_data == NULL)
                                return 0;
 #ifdef UNROLL
-#pragma unroll
+                       __pragma_loop_unroll
 #endif
                        for (int i = 0; i < ARRAY_SIZE(arr_struct->array); i++)
                                if (arr_struct->array[i].meta.pid == 0) {
@@ -482,7 +483,7 @@ read_absolute_file_path_from_dentry(struct dentry* filp_dentry, void* payload)
        struct dentry* parent_dentry;
 
 #ifdef UNROLL
-#pragma unroll
+       __pragma_loop_unroll
 #endif
        for (int i = 0; i < MAX_PATH_DEPTH; i++) {
                filepart_length =
@@ -508,7 +509,7 @@ is_ancestor_in_allowed_inodes(struct dentry* filp_dentry)
 {
        struct dentry* parent_dentry;
 #ifdef UNROLL
-#pragma unroll
+       __pragma_loop_unroll
 #endif
        for (int i = 0; i < MAX_PATH_DEPTH; i++) {
                u64 dir_ino = BPF_CORE_READ(filp_dentry, d_inode, i_ino);
@@ -629,7 +630,7 @@ int raw_tracepoint__sched_process_exit(void* ctx)
        struct kernfs_node* proc_kernfs = BPF_CORE_READ(task, cgroups, dfl_cgrp, kn);
 
 #ifdef UNROLL
-#pragma unroll
+       __pragma_loop_unroll
 #endif
        for (int i = 0; i < ARRAY_SIZE(arr_struct->array); i++) {
                struct var_kill_data_t* past_kill_data = &arr_struct->array[i];
index 026d573ce1797ba715bf76f8d99a105643c57554..86484f07e1d19121687cec2635873b1e7c47632d 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
 #include "bpf_misc.h"
+#include "bpf_compiler.h"
 
 #define FUNCTION_NAME_LEN 64
 #define FILE_NAME_LEN 128
@@ -298,11 +299,11 @@ int __on_event(struct bpf_raw_tracepoint_args *ctx)
 #if defined(USE_ITER)
 /* no for loop, no unrolling */
 #elif defined(NO_UNROLL)
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
 #elif defined(UNROLL_COUNT)
-#pragma clang loop unroll_count(UNROLL_COUNT)
+       __pragma_loop_unroll_count(UNROLL_COUNT)
 #else
-#pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
 #endif /* NO_UNROLL */
                /* Unwind python stack */
 #ifdef USE_ITER
index 40df2cc26eaf9d83005756fa8c67fd2e20171847..f74459eead263fd56358c6a2d89fc0e4d79d72f7 100644 (file)
@@ -10,6 +10,8 @@
 #include <linux/types.h>
 #include <bpf/bpf_helpers.h>
 
+#include "bpf_compiler.h"
+
 typedef uint32_t pid_t;
 struct task_struct {};
 
@@ -419,9 +421,9 @@ static __always_inline uint64_t read_map_var(struct strobemeta_cfg *cfg,
        }
 
 #ifdef NO_UNROLL
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
 #else
-#pragma unroll
+       __pragma_loop_unroll
 #endif
        for (int i = 0; i < STROBE_MAX_MAP_ENTRIES; ++i) {
                if (i >= map.cnt)
@@ -560,25 +562,25 @@ static void *read_strobe_meta(struct task_struct *task,
                payload_off = sizeof(data->payload);
 #else
 #ifdef NO_UNROLL
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
 #else
-#pragma unroll
+       __pragma_loop_unroll
 #endif /* NO_UNROLL */
        for (int i = 0; i < STROBE_MAX_INTS; ++i) {
                read_int_var(cfg, i, tls_base, &value, data);
        }
 #ifdef NO_UNROLL
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
 #else
-#pragma unroll
+       __pragma_loop_unroll
 #endif /* NO_UNROLL */
        for (int i = 0; i < STROBE_MAX_STRS; ++i) {
                payload_off = read_str_var(cfg, i, tls_base, &value, data, payload_off);
        }
 #ifdef NO_UNROLL
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
 #else
-#pragma unroll
+       __pragma_loop_unroll
 #endif /* NO_UNROLL */
        for (int i = 0; i < STROBE_MAX_MAPS; ++i) {
                payload_off = read_map_var(cfg, i, tls_base, &value, data, payload_off);
index bfc9179259d5b26c6cd5cd24928ba4400ee6d9aa..683c8aaa63dac3ceee8b4d7a5807642e30ab121e 100644 (file)
@@ -20,6 +20,7 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
 
+#include "bpf_compiler.h"
 #include "test_cls_redirect.h"
 
 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
@@ -269,7 +270,7 @@ static INLINING void pkt_ipv4_checksum(struct iphdr *iph)
        uint32_t acc = 0;
        uint16_t *ipw = (uint16_t *)iph;
 
-#pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (size_t i = 0; i < sizeof(struct iphdr) / 2; i++) {
                acc += ipw[i];
        }
@@ -296,7 +297,7 @@ bool pkt_skip_ipv6_extension_headers(buf_t *pkt,
        };
        *is_fragment = false;
 
-#pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (int i = 0; i < 6; i++) {
                switch (exthdr.next) {
                case IPPROTO_FRAGMENT:
index 48ff2b2ad5e767445444b784255a99957a3050ea..fed66f36adb6c83c7aae6005025ed50b6995506e 100644 (file)
@@ -6,6 +6,8 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
 
+#include "bpf_compiler.h"
+
 /* Packet parsing state machine helpers. */
 #define cursor_advance(_cursor, _len) \
        ({ void *_tmp = _cursor; _cursor += _len; _tmp; })
@@ -131,7 +133,7 @@ int is_valid_tlv_boundary(struct __sk_buff *skb, struct ip6_srh_t *srh,
        *pad_off = 0;
 
        // we can only go as far as ~10 TLVs due to the BPF max stack size
-       #pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (int i = 0; i < 10; i++) {
                struct sr6_tlv_t tlv;
 
@@ -302,7 +304,7 @@ int __encap_srh(struct __sk_buff *skb)
 
        seg = (struct ip6_addr_t *)((char *)srh + sizeof(*srh));
 
-       #pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (unsigned long long lo = 0; lo < 4; lo++) {
                seg->lo = bpf_cpu_to_be64(4 - lo);
                seg->hi = bpf_cpu_to_be64(hi);
index a7278f064368e15e5354d6092b7e10deedddaaf7..5059050f74f6c723c64137532add6019efd9319a 100644 (file)
@@ -6,6 +6,8 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
 
+#include "bpf_compiler.h"
+
 /* Packet parsing state machine helpers. */
 #define cursor_advance(_cursor, _len) \
        ({ void *_tmp = _cursor; _cursor += _len; _tmp; })
@@ -134,7 +136,7 @@ static __always_inline int is_valid_tlv_boundary(struct __sk_buff *skb,
        // we can only go as far as ~10 TLVs due to the BPF max stack size
        // workaround: define induction variable "i" as "long" instead
        // of "int" to prevent alu32 sub-register spilling.
-       #pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
        for (long i = 0; i < 100; i++) {
                struct sr6_tlv_t tlv;
 
index c482110cfc9560f2d15811b3de48c56930f65548..a724a70c6700cc98bfeacd4e5bbe219801660e34 100644 (file)
@@ -3,12 +3,14 @@
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
 
+#include "bpf_compiler.h"
+
 char _license[] SEC("license") = "GPL";
 
 SEC("tc")
 int process(struct __sk_buff *skb)
 {
-       #pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (int i = 0; i < 5; i++) {
                if (skb->cb[i] != i + 1)
                        return 1;
index 553a282d816aba6ca7d6b507a40da973142b07b2..7f74077d6622f2fa77666a62ad5bdf4fbe28df4b 100644 (file)
@@ -9,6 +9,8 @@
 
 #include <bpf/bpf_helpers.h>
 
+#include "bpf_compiler.h"
+
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 #endif
@@ -30,7 +32,7 @@ static __always_inline int is_tcp_mem(struct bpf_sysctl *ctx)
        if (ret < 0 || ret != sizeof(tcp_mem_name) - 1)
                return 0;
 
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
        for (i = 0; i < sizeof(tcp_mem_name); ++i)
                if (name[i] != tcp_mem_name[i])
                        return 0;
@@ -59,7 +61,7 @@ int sysctl_tcp_mem(struct bpf_sysctl *ctx)
        if (ret < 0 || ret >= MAX_VALUE_STR_LEN)
                return 0;
 
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
        for (i = 0; i < ARRAY_SIZE(tcp_mem); ++i) {
                ret = bpf_strtoul(value + off, MAX_ULONG_STR_LEN, 0,
                                  tcp_mem + i);
index 2b64bc563a12ece18ca08bdede8a7203f514dd48..68a75436e8af0bf0e3ec6a47d703c2065b980eda 100644 (file)
@@ -9,6 +9,8 @@
 
 #include <bpf/bpf_helpers.h>
 
+#include "bpf_compiler.h"
+
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 #endif
@@ -30,7 +32,7 @@ static __attribute__((noinline)) int is_tcp_mem(struct bpf_sysctl *ctx)
        if (ret < 0 || ret != sizeof(tcp_mem_name) - 1)
                return 0;
 
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
        for (i = 0; i < sizeof(tcp_mem_name); ++i)
                if (name[i] != tcp_mem_name[i])
                        return 0;
@@ -57,7 +59,7 @@ int sysctl_tcp_mem(struct bpf_sysctl *ctx)
        if (ret < 0 || ret >= MAX_VALUE_STR_LEN)
                return 0;
 
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
        for (i = 0; i < ARRAY_SIZE(tcp_mem); ++i) {
                ret = bpf_strtoul(value + off, MAX_ULONG_STR_LEN, 0,
                                  tcp_mem + i);
index 5489823c83fc29efdf3ab0f48a6fa9a440cc25e4..efc3c61f78521067555b50d75630466b52cc5efb 100644 (file)
@@ -9,6 +9,8 @@
 
 #include <bpf/bpf_helpers.h>
 
+#include "bpf_compiler.h"
+
 /* Max supported length of a string with unsigned long in base 10 (pow2 - 1). */
 #define MAX_ULONG_STR_LEN 0xF
 
@@ -31,7 +33,7 @@ static __always_inline int is_tcp_mem(struct bpf_sysctl *ctx)
        if (ret < 0 || ret != sizeof(tcp_mem_name) - 1)
                return 0;
 
-#pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (i = 0; i < sizeof(tcp_mem_name); ++i)
                if (name[i] != tcp_mem_name[i])
                        return 0;
@@ -57,7 +59,7 @@ int sysctl_tcp_mem(struct bpf_sysctl *ctx)
        if (ret < 0 || ret >= MAX_VALUE_STR_LEN)
                return 0;
 
-#pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (i = 0; i < ARRAY_SIZE(tcp_mem); ++i) {
                ret = bpf_strtoul(value + off, MAX_ULONG_STR_LEN, 0,
                                  tcp_mem + i);
index d8d7ab5e8e30fa8fe8821a033485f7df7a38ef5a..404124a9389278949e6952a6f1a50eea9a1bc473 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <bpf/bpf_endian.h>
 #include <bpf/bpf_helpers.h>
+#include "bpf_compiler.h"
 
 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
 
@@ -83,7 +84,7 @@ static __always_inline void set_ipv4_csum(struct iphdr *iph)
 
        iph->check = 0;
 
-#pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (i = 0, csum = 0; i < sizeof(*iph) >> 1; i++)
                csum += *iph16++;
 
index d7a9a74b7245390504e1e6e1c6c5f0fac9f51883..8caf58be58183585cbbc82f71808738892f84936 100644 (file)
@@ -19,6 +19,7 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
 #include "test_iptunnel_common.h"
+#include "bpf_compiler.h"
 
 struct {
        __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
@@ -137,7 +138,7 @@ static __always_inline int handle_ipv4(struct xdp_md *xdp)
        iph->ttl = 8;
 
        next_iph = (__u16 *)iph;
-#pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (i = 0; i < sizeof(*iph) >> 1; i++)
                csum += *next_iph++;
 
index c98fb44156f04d3d2a0f96ed2b3725060fc47a9e..93267a68825beb0c27f0c356eda0bc42b299e754 100644 (file)
@@ -15,6 +15,7 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
 #include "test_iptunnel_common.h"
+#include "bpf_compiler.h"
 
 struct {
        __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
@@ -133,7 +134,7 @@ static __always_inline int handle_ipv4(struct xdp_md *xdp)
        iph->ttl = 8;
 
        next_iph = (__u16 *)iph;
-#pragma clang loop unroll(disable)
+       __pragma_loop_no_unroll
        for (i = 0; i < sizeof(*iph) >> 1; i++)
                csum += *next_iph++;
 
index 42c8f6ded0e4d2b0c5d3def1f5b9483ff0fada1c..5c7e4758a0cab9e38297d353f8926209041063b5 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/udp.h>
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
+#include "bpf_compiler.h"
 
 static __always_inline __u32 rol32(__u32 word, unsigned int shift)
 {
@@ -362,7 +363,7 @@ bool encap_v4(struct xdp_md *xdp, struct ctl_value *cval,
        iph->ttl = 4;
 
        next_iph_u16 = (__u16 *) iph;
-#pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (int i = 0; i < sizeof(struct iphdr) >> 1; i++)
                csum += *next_iph_u16++;
        iph->check = ~((csum & 0xffff) + (csum >> 16));
@@ -409,7 +410,7 @@ int send_icmp_reply(void *data, void *data_end)
        iph->saddr = tmp_addr;
        iph->check = 0;
        next_iph_u16 = (__u16 *) iph;
-#pragma clang loop unroll(full)
+       __pragma_loop_unroll_full
        for (int i = 0; i < sizeof(struct iphdr) >> 1; i++)
                csum += *next_iph_u16++;
        iph->check = ~((csum & 0xffff) + (csum >> 16));
index 518329c666e93fa9d55b628d25a5e8919e3d5af1..7ea9785738b5a0f79fc32af8d9950b4723f18ce5 100644 (file)
@@ -7,6 +7,8 @@
 #include <bpf/bpf_endian.h>
 #include <asm/errno.h>
 
+#include "bpf_compiler.h"
+
 #define TC_ACT_OK 0
 #define TC_ACT_SHOT 2
 
@@ -151,11 +153,11 @@ static __always_inline __u16 csum_ipv6_magic(const struct in6_addr *saddr,
        __u64 sum = csum;
        int i;
 
-#pragma unroll
+       __pragma_loop_unroll
        for (i = 0; i < 4; i++)
                sum += (__u32)saddr->in6_u.u6_addr32[i];
 
-#pragma unroll
+       __pragma_loop_unroll
        for (i = 0; i < 4; i++)
                sum += (__u32)daddr->in6_u.u6_addr32[i];
 
index 54cf1765118b800c57788bfdb95d8553f1560ce6..44e2b0ef23ae4233c55796f541b94fc434bcf9b8 100644 (file)
@@ -15,6 +15,7 @@
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
 
+#include "bpf_compiler.h"
 #include "xdping.h"
 
 struct {
@@ -116,7 +117,7 @@ int xdping_client(struct xdp_md *ctx)
                return XDP_PASS;
 
        if (pinginfo->start) {
-#pragma clang loop unroll(full)
+               __pragma_loop_unroll_full
                for (i = 0; i < XDPING_MAX_COUNT; i++) {
                        if (pinginfo->times[i] == 0)
                                break;