Commit ee286326 authored by 4ast's avatar 4ast

Merge pull request #158 from iovisor/bblanco_dev

Fix map.clear() usage for array type maps
parents 136d85ff 8e40c235
......@@ -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