return mod->table_max_entries(id);
}
+int bpf_table_flags(void *program, const char *table_name) {
+ auto mod = static_cast<ebpf::BPFModule *>(program);
+ if (!mod) return -1;
+ return mod->table_flags(table_name);
+}
+
+int bpf_table_flags_id(void *program, size_t id) {
+ auto mod = static_cast<ebpf::BPFModule *>(program);
+ if (!mod) return -1;
+ return mod->table_flags(id);
+}
+
const char * bpf_table_name(void *program, size_t id) {
auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return nullptr;
int bpf_table_type_id(void *program, size_t id);
size_t bpf_table_max_entries(void *program, const char *table_name);
size_t bpf_table_max_entries_id(void *program, size_t id);
+int bpf_table_flags(void *program, const char *table_name);
+int bpf_table_flags_id(void *program, size_t id);
const char * bpf_table_name(void *program, size_t id);
const char * bpf_table_key_desc(void *program, const char *table_name);
const char * bpf_table_key_desc_id(void *program, size_t id);
return (*tables_)[id].max_entries;
}
+int BPFModule::table_flags(const string &name) const {
+ return table_flags(table_id(name));
+}
+
+int BPFModule::table_flags(size_t id) const {
+ if (id >= tables_->size()) return -1;
+ return (*tables_)[id].flags;
+}
+
const char * BPFModule::table_name(size_t id) const {
if (id >= tables_->size()) return nullptr;
return (*tables_)[id].name.c_str();
int table_type(size_t id) const;
size_t table_max_entries(const std::string &name) const;
size_t table_max_entries(size_t id) const;
+ int table_flags(const std::string &name) const;
+ int table_flags(size_t id) const;
const char * table_key_desc(size_t id) const;
const char * table_key_desc(const std::string &name) const;
size_t table_key_size(size_t id) const;
#define SEC(NAME) __attribute__((section(NAME), used))
// Changes to the macro require changes in BFrontendAction classes
-#define BPF_TABLE(_table_type, _key_type, _leaf_type, _name, _max_entries) \
+#define BPF_F_TABLE(_table_type, _key_type, _leaf_type, _name, _max_entries, _flags) \
struct _name##_table_t { \
_key_type key; \
_leaf_type leaf; \
void (*increment) (_key_type); \
int (*get_stackid) (void *, u64); \
_leaf_type data[_max_entries]; \
+ int flags; \
}; \
__attribute__((section("maps/" _table_type))) \
-struct _name##_table_t _name
+struct _name##_table_t _name = { .flags = (_flags) }
+
+#define BPF_TABLE(_table_type, _key_type, _leaf_type, _name, _max_entries) \
+BPF_F_TABLE(_table_type, _key_type, _leaf_type, _name, _max_entries, 0);
// define a table same as above but allow it to be referenced by other modules
#define BPF_TABLE_PUBLIC(_table_type, _key_type, _leaf_type, _name, _max_entries) \
decl_gvar->setSection("maps");
tables_[n] = decl_gvar;
- int map_fd = bpf_create_map(map_type, key->bit_width_ / 8, leaf->bit_width_ / 8, n->size_);
+ int map_fd = bpf_create_map(map_type, key->bit_width_ / 8, leaf->bit_width_ / 8, n->size_, 0);
if (map_fd >= 0)
table_fds_[n] = map_fd;
} else {
table.first->key_type_->bit_width_ >> 3,
table.first->leaf_type_->bit_width_ >> 3,
table.first->size_,
+ 0,
"", "",
});
}
}
const RecordDecl *RD = R->getDecl()->getDefinition();
- int major = 0, minor = 0;
- struct utsname un;
- if (uname(&un) == 0) {
- // release format: <major>.<minor>.<revision>[-<othertag>]
- sscanf(un.release, "%d.%d.", &major, &minor);
- }
-
TableDesc table = {};
table.name = Decl->getName();
visitor.TraverseType(F->getType());
} else if (F->getName() == "data") {
table.max_entries = sz / table.leaf_size;
+ } else if (F->getName() == "flags") {
+ unsigned idx = F->getFieldIndex();
+ if (auto I = dyn_cast_or_null<InitListExpr>(Decl->getInit())) {
+ llvm::APSInt res;
+ if (I->getInit(idx)->EvaluateAsInt(res, C)) {
+ table.flags = res.getExtValue();
+ }
+ }
}
++i;
}
+
bool is_extern = false;
bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC;
if (A->getName() == "maps/hash") {
}
table.type = map_type;
- table.fd = bpf_create_map(map_type, table.key_size, table.leaf_size, table.max_entries);
+ table.fd = bpf_create_map(map_type, table.key_size, table.leaf_size, table.max_entries, table.flags);
}
if (table.fd < 0) {
error(Decl->getLocStart(), "could not open bpf map: %0\nis %1 map type enabled in your kernel?") <<
struct TableDesc;
-namespace cc {
-class Parser;
-class CodegenLLVM;
-}
-
class ClangLoader {
public:
explicit ClangLoader(llvm::LLVMContext *ctx, unsigned flags);
return (__u64) (unsigned long) ptr;
}
-int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries)
+int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries, int map_flags)
{
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.key_size = key_size;
attr.value_size = value_size;
attr.max_entries = max_entries;
+ attr.map_flags = map_flags;
int ret = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
if (ret < 0 && errno == EPERM) {
}
ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
-
+
if (ret < 0 && errno == EPERM) {
// When EPERM is returned, two reasons are possible:
// 1. user has no permissions for bpf()
fprintf(stderr, "bpf: %s\n%s\n", strerror(errno), bpf_log_buffer);
- free(bpf_log_buffer);
+ free(bpf_log_buffer);
}
return ret;
}
#endif
int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
- int max_entries);
+ int max_entries, int map_flags);
int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
size_t key_size; // sizes are in bytes
size_t leaf_size;
size_t max_entries;
+ int flags;
std::string key_desc;
std::string leaf_desc;
llvm::Function *key_sscanf;
BPF_PROG_TYPE_SCHED_ACT,
};
-int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries);
+int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int max_entries, int map_flags);
int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags);
int bpf_lookup_elem(int fd, void *key, void *value);
int bpf_delete_elem(int fd, void *key);
int bpf_table_type_id(void *program, size_t id);
size_t bpf_table_max_entries(void *program, const char *table_name);
size_t bpf_table_max_entries_id(void *program, size_t id);
+int bpf_table_flags(void *program, const char *table_name);
+int bpf_table_flags_id(void *program, size_t id);
const char * bpf_table_name(void *program, size_t id);
const char * bpf_table_key_desc(void *program, const char *table_name);
const char * bpf_table_key_desc_id(void *program, size_t id);
lib.bpf_table_type_id.argtypes = [ct.c_void_p, ct.c_ulonglong]
lib.bpf_table_max_entries_id.restype = ct.c_ulonglong
lib.bpf_table_max_entries_id.argtypes = [ct.c_void_p, ct.c_ulonglong]
+lib.bpf_table_flags_id.restype = ct.c_int
+lib.bpf_table_flags_id.argtypes = [ct.c_void_p, ct.c_ulonglong]
lib.bpf_table_key_desc.restype = ct.c_char_p
lib.bpf_table_key_desc.argtypes = [ct.c_void_p, ct.c_char_p]
lib.bpf_table_leaf_desc.restype = ct.c_char_p
self.Key = keytype
self.Leaf = leaftype
self.ttype = lib.bpf_table_type_id(self.bpf.module, self.map_id)
+ self.flags = lib.bpf_table_flags_id(self.bpf.module, self.map_id)
self._cbs = {}
def key_sprintf(self, key):
--- /dev/null
+#!/usr/bin/env python
+# Copyright (c) PLUMgrid, Inc.
+# Licensed under the Apache License, Version 2.0 (the "License")
+
+import unittest
+from bcc import BPF
+
+class TestLru(unittest.TestCase):
+ def test_lru_map_flags(self):
+ test_prog1 = """
+ BPF_F_TABLE("lru_hash", int, u64, lru, 1024, BPF_F_NO_COMMON_LRU);
+ """
+ b = BPF(text=test_prog1)
+ t = b["lru"]
+ self.assertEqual(t.flags, 2);
+
+ def test_hash_map_flags(self):
+ test_prog1 = """
+ BPF_F_TABLE("hash", int, u64, hash, 1024, BPF_F_NO_PREALLOC);
+ """
+ b = BPF(text=test_prog1)
+ t = b["hash"]
+ self.assertEqual(t.flags, 1);
+
+if __name__ == "__main__":
+ unittest.main()