bpf/include/list.h (58 lines of code) (raw):
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#pragma once
#include "api.h"
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_head within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
__u8 i = 0; \
for (pos = list_entry(_((head)->next), typeof(*pos), member), \
n = list_entry(_(pos->member.next), typeof(*pos), member); \
&pos->member != (head) && i < 255; \
pos = n, n = list_entry(_(n->member.next), typeof(*n), member), i++)
// use for for-each the list without for loop(lower linux kernel)
// use list_for_each_entry_init at first, and use list_for_each_entry_data multiples for the loop
#define list_for_each_entry_init() \
bool list_is_first = true; \
bool list_should_enter = false;
#define list_for_each_entry_data(pos, n, head, member) \
if (list_is_first) { \
list_should_enter = true; \
list_is_first = false; \
pos = list_entry(_((head)->next), typeof(*pos), member); \
n = list_entry(_(pos->member.next), typeof(*pos), member); \
} else if (list_should_enter) { \
pos = n; \
n = list_entry(_(n->member.next), typeof(*n), member); \
list_should_enter = &pos->member != (head); \
} \
if (list_should_enter)
// Customized BPF List implementation
struct c_bpf_list_head {
void *data;
struct c_bpf_list_head *next;
};
static inline struct c_bpf_list_head init_bpf_list_head() {
struct c_bpf_list_head head = {};
head.data = NULL;
head.next = NULL;
return head;
}
static inline struct c_bpf_list_head append_bpf_list_head(struct c_bpf_list_head* head, void *data) {
struct c_bpf_list_head new_head = init_bpf_list_head();
new_head.data = data;
new_head.next = head;
return new_head;
}
static inline int bpf_list_empty(struct c_bpf_list_head *head) {
return head->next == NULL;
}
#define bpf_list_for_each_init() \
bool bpf_list_is_first = true; \
struct c_bpf_list_head *current_node = NULL;
#define bpf_list_for_each_foreach(pos, head) \
if (bpf_list_is_first) { \
current_node = head; \
pos = head->data;\
} else if (current_node != NULL) { \
current_node = current_node->next; \
if (current_node != NULL) {\
pos = current_node->data; \
}\
} \
if (current_node != NULL && current_node->next != NULL)