mirror of
https://github.com/matrix-construct/construct
synced 2024-12-11 08:02:59 +01:00
218 lines
3.3 KiB
C++
218 lines
3.3 KiB
C++
// The Construct
|
|
//
|
|
// Copyright (C) The Construct Developers, Authors & Contributors
|
|
// Copyright (C) 2016-2022 Jason Volk <jason@zemos.net>
|
|
//
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
// full license for this software is available in the LICENSE file.
|
|
|
|
#include <sys/syscall.h>
|
|
#include <linux/bpf.h>
|
|
|
|
namespace ircd::net::bpf
|
|
{
|
|
struct [[clang::internal_linkage]] call;
|
|
|
|
static constexpr uint
|
|
log_bufs{8},
|
|
log_buf_sz{4_KiB};
|
|
|
|
static thread_local uint log_bufn;
|
|
static thread_local char log_buf[log_bufs][log_buf_sz];
|
|
}
|
|
|
|
class [[gnu::visibility("internal")]]
|
|
ircd::net::bpf::call
|
|
{
|
|
int ret;
|
|
|
|
public:
|
|
operator const int &() const;
|
|
|
|
call(const int &, union bpf_attr *const &);
|
|
call(const int &, const union bpf_attr &);
|
|
};
|
|
|
|
decltype(ircd::net::bpf::log)
|
|
ircd::net::bpf::log
|
|
{
|
|
"net.bpf"
|
|
};
|
|
|
|
//
|
|
// bpf::prog
|
|
//
|
|
|
|
ircd::net::bpf::prog::prog(const const_buffer &insns)
|
|
:prog
|
|
{
|
|
insns, mutable_buffer
|
|
{
|
|
bpf::log_buf[log_bufn++ % log_bufs], log_buf_sz
|
|
}
|
|
}
|
|
{
|
|
assert(log_bufn <= log_bufs); //TODO: XXX
|
|
}
|
|
|
|
ircd::net::bpf::prog::prog(const const_buffer &insns,
|
|
const mutable_buffer &log_buf)
|
|
try
|
|
:insns
|
|
{
|
|
insns
|
|
}
|
|
,log_buf
|
|
{
|
|
log_buf
|
|
}
|
|
,fd
|
|
{
|
|
#if defined(__clang__) || RB_CXX_EPOCH >= 11
|
|
empty(insns)? -1: call
|
|
{
|
|
BPF_PROG_LOAD, bpf_attr
|
|
{
|
|
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
|
|
.insn_cnt = u32(size(insns) / sizeof(bpf_insn)),
|
|
.insns = uintptr_t(data(insns)),
|
|
#ifdef _GNU_SOURCE
|
|
.license = uintptr_t("GPL"),
|
|
#endif
|
|
.log_level = !empty(log_buf)? 1U: 0,
|
|
.log_size = u32(size(log_buf)),
|
|
.log_buf = uintptr_t(data(log_buf)),
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
{
|
|
if(!fd)
|
|
return;
|
|
|
|
log::debug
|
|
{
|
|
log, "Loaded prog:%p fd:%d bin:%p bytes:%zu",
|
|
this,
|
|
int(fd),
|
|
ircd::data(insns),
|
|
ircd::size(insns),
|
|
};
|
|
}
|
|
catch(const std::exception &e)
|
|
{
|
|
const string_view log_str
|
|
{
|
|
data(log_buf), strnlen(data(log_buf), size(log_buf))
|
|
};
|
|
|
|
uint i(0);
|
|
ircd::tokens(log_str, '\n', [this, &i]
|
|
(const string_view &line)
|
|
{
|
|
if(likely(line))
|
|
log::error
|
|
{
|
|
log, "Log prog:%p %2u :%s",
|
|
this,
|
|
i++,
|
|
line,
|
|
};
|
|
});
|
|
|
|
log::critical
|
|
{
|
|
log, "Failed to load prog:%p bin:%p bytes:%zu :%s",
|
|
this,
|
|
data(insns),
|
|
size(insns),
|
|
e.what(),
|
|
};
|
|
|
|
throw;
|
|
}
|
|
|
|
ircd::net::bpf::prog::~prog()
|
|
noexcept
|
|
{
|
|
if(!fd)
|
|
return;
|
|
|
|
log::debug
|
|
{
|
|
log, "Unloading prog:%p fd:%d ...",
|
|
this,
|
|
int(fd),
|
|
};
|
|
}
|
|
|
|
//
|
|
// bpf::map
|
|
//
|
|
|
|
ircd::net::bpf::map::map()
|
|
try
|
|
:fd
|
|
{
|
|
#if defined(__clang__) || RB_CXX_EPOCH >= 11
|
|
call
|
|
{
|
|
BPF_MAP_CREATE, bpf_attr
|
|
{
|
|
.map_type = BPF_MAP_TYPE_UNSPEC,
|
|
.key_size = 8,
|
|
.value_size = 8,
|
|
.max_entries = 8,
|
|
},
|
|
},
|
|
#endif
|
|
}
|
|
{
|
|
}
|
|
catch(const std::exception &e)
|
|
{
|
|
char pbuf[48];
|
|
log::error
|
|
{
|
|
log, "Mapping failed :%s",
|
|
e.what(),
|
|
};
|
|
|
|
throw;
|
|
}
|
|
|
|
ircd::net::bpf::map::~map()
|
|
noexcept
|
|
{
|
|
}
|
|
|
|
//
|
|
// internal
|
|
//
|
|
|
|
ircd::net::bpf::call::call(const int &cmd,
|
|
const union bpf_attr &attr)
|
|
:call
|
|
{
|
|
cmd, mutable_cast(&attr)
|
|
}
|
|
{
|
|
}
|
|
|
|
ircd::net::bpf::call::call(const int &cmd,
|
|
union bpf_attr *const &attr)
|
|
:ret
|
|
{
|
|
int(sys::call<SYS_bpf>(cmd, attr, sizeof(union bpf_attr)))
|
|
}
|
|
{
|
|
}
|
|
|
|
ircd::net::bpf::call::operator
|
|
const int &()
|
|
const
|
|
{
|
|
return ret;
|
|
}
|