Commit 8e40c235 authored by Brenden Blanco's avatar Brenden Blanco

Fix map.clear() usage for array type maps

Calling delete on an array type map entry does not have an effect.
Instead, the entry needs to be zeroed out, since the array slot always
exists. To avoid unnecessary calls to update(), only call update() when
the map type is array-like. The type was not exposed to python up until
now, so add it.
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent 136d85ff
......@@ -122,6 +122,18 @@ int bpf_table_fd_id(void *program, size_t id) {
return mod->table_fd(id);
}
int bpf_table_type(void *program, const char *table_name) {
auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return -1;
return mod->table_type(table_name);
}
int bpf_table_type_id(void *program, size_t id) {
auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return -1;
return mod->table_type(id);
}
const char * bpf_table_name(void *program, size_t id) {
auto mod = static_cast<ebpf::BPFModule *>(program);
if (!mod) return nullptr;
......
......@@ -40,6 +40,8 @@ size_t bpf_num_tables(void *program);
size_t bpf_table_id(void *program, const char *table_name);
int bpf_table_fd(void *program, const char *table_name);
int bpf_table_fd_id(void *program, size_t id);
int bpf_table_type(void *program, const char *table_name);
int bpf_table_type_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);
......
......@@ -488,6 +488,15 @@ int BPFModule::table_fd(size_t id) const {
return (*tables_)[id].fd;
}
int BPFModule::table_type(const string &name) const {
return table_type(table_id(name));
}
int BPFModule::table_type(size_t id) const {
if (id >= tables_->size()) return -1;
return (*tables_)[id].type;
}
const char * BPFModule::table_name(size_t id) const {
if (id >= tables_->size()) return nullptr;
return (*tables_)[id].name.c_str();
......
......@@ -68,6 +68,8 @@ class BPFModule {
int table_fd(size_t id) const;
int table_fd(const std::string &name) const;
const char * table_name(size_t id) const;
int table_type(const std::string &name) const;
int table_type(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;
......
......@@ -1232,9 +1232,15 @@ StatusTuple CodegenLLVM::visit(Node* root, vector<TableDesc> &tables) {
//TRY2(print_parser());
for (auto table : tables_) {
bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC;
if (table.first->type_id()->name_ == "FIXED_MATCH")
map_type = BPF_MAP_TYPE_HASH;
else if (table.first->type_id()->name_ == "INDEXED")
map_type = BPF_MAP_TYPE_ARRAY;
tables.push_back({
table.first->id_->name_,
table_fds_[table.first],
map_type,
table.first->key_type_->bit_width_ >> 3,
table.first->leaf_type_->bit_width_ >> 3,
table.first->size_,
......
......@@ -408,6 +408,7 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
return false;
}
}
table.type = map_type;
table.fd = bpf_create_map(map_type, table.key_size, table.leaf_size, table.max_entries);
if (table.fd < 0) {
C.getDiagnostics().Report(Decl->getLocStart(), diag::err_expected)
......
......@@ -26,6 +26,7 @@ namespace ebpf {
struct TableDesc {
std::string name;
int fd;
int type;
size_t key_size; // sizes are in bytes
size_t leaf_size;
size_t max_entries;
......
......@@ -44,6 +44,8 @@ lib.bpf_table_id.restype = ct.c_ulonglong
lib.bpf_table_id.argtypes = [ct.c_void_p, ct.c_char_p]
lib.bpf_table_fd.restype = ct.c_int
lib.bpf_table_fd.argtypes = [ct.c_void_p, ct.c_char_p]
lib.bpf_table_type_id.restype = ct.c_int
lib.bpf_table_type_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
......@@ -103,6 +105,10 @@ class BPF(object):
SCHED_CLS = 3
SCHED_ACT = 4
HASH = 1
ARRAY = 2
PROG_ARRAY = 3
class Function(object):
def __init__(self, bpf, name, fd):
self.bpf = bpf
......@@ -116,6 +122,7 @@ class BPF(object):
self.map_fd = map_fd
self.Key = keytype
self.Leaf = leaftype
self.ttype = lib.bpf_table_type_id(self.bpf.module, self.map_id)
def key_sprintf(self, key):
key_p = ct.pointer(key)
......@@ -180,9 +187,33 @@ class BPF(object):
def __delitem__(self, key):
key_p = ct.pointer(key)
res = lib.bpf_delete_elem(self.map_fd, ct.cast(key_p, ct.c_void_p))
if res < 0:
raise KeyError
ttype = lib.bpf_table_type_id(self.bpf.module, self.map_id)
# Deleting from array type maps does not have an effect, so
# zero out the entry instead.
if ttype in (BPF.ARRAY, BPF.PROG_ARRAY):
leaf = self.Leaf()
leaf_p = ct.pointer(leaf)
res = lib.bpf_update_elem(self.map_fd,
ct.cast(key_p, ct.c_void_p),
ct.cast(leaf_p, ct.c_void_p), 0)
if res < 0:
raise Exception("Could not clear item")
else:
res = lib.bpf_delete_elem(self.map_fd,
ct.cast(key_p, ct.c_void_p))
if res < 0:
raise KeyError
def clear(self):
if self.ttype in (BPF.ARRAY, BPF.PROG_ARRAY):
# Special case clear, since this class is currently behaving
# like a dict but popitem on an array causes an infinite loop.
# TODO: derive Table from array.array instead
for k in self.keys():
self.__delitem__(k)
else:
super(BPF.Table, self).clear()
def __iter__(self):
return BPF.Table.Iter(self, self.Key)
......
#!/usr/bin/python
# vim: ts=8 noet sw=8
#
# pidpersec Count new processes (via fork).
# For Linux, uses BCC, eBPF. See .c file.
......@@ -32,8 +33,8 @@ while (1):
try:
sleep(1)
except KeyboardInterrupt:
pass; exit()
exit()
print("%s: PIDs/sec: %d" % (strftime("%H:%M:%S"),
(b["stats"][S_COUNT].value - last)))
last = b["stats"][S_COUNT].value
(b["stats"][S_COUNT].value)))
b["stats"].clear()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment