ircd::net::bpf: Add preliminary epbf support.

This commit is contained in:
Jason Volk 2022-07-07 16:44:42 -07:00
parent 11e75db293
commit d3584274ac
5 changed files with 274 additions and 0 deletions

View File

@ -1258,6 +1258,7 @@ RB_CHK_SYSHEADER(linux/hw_breakpoint.h, [LINUX_HW_BREAKPOINT_H])
RB_CHK_SYSHEADER(linux/io_uring.h, [LINUX_IO_URING_H])
RB_CHK_SYSHEADER(linux/icmp.h, [LINUX_ICMP_H])
RB_CHK_SYSHEADER(linux/input-event-codes.h, [LINUX_INPUT_EVENT_CODES_H])
RB_CHK_SYSHEADER(linux/bpf.h, [LINUX_BPF_H])
dnl windows platform
RB_CHK_SYSHEADER(windows.h, [WINDOWS_H])

51
include/ircd/net/bpf.h Normal file
View File

@ -0,0 +1,51 @@
// Matrix Construct
//
// Copyright (C) Matrix 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.
#pragma once
#define HAVE_IRCD_NET_BPF_H
namespace ircd::net::bpf
{
struct map;
struct prog;
extern log::log log;
}
struct ircd::net::bpf::map
{
fs::fd fd;
public:
explicit operator bool() const
{
return bool(fd);
}
map();
~map() noexcept;
};
struct ircd::net::bpf::prog
{
const_buffer insns;
mutable_buffer log_buf;
fs::fd fd;
public:
explicit operator bool() const
{
return bool(fd);
}
prog(const const_buffer &, const mutable_buffer &log_buf);
prog(const const_buffer &);
~prog() noexcept;
};

View File

@ -37,6 +37,7 @@ namespace ircd::net
#include "hostport.h"
#include "ipaddr.h"
#include "ipport.h"
#include "bpf.h"
#include "dns.h"
#include "dns_cache.h"
#include "listener.h"

View File

@ -247,6 +247,9 @@ libircd_la_SOURCES += net_dns_cache.cc
libircd_la_SOURCES += net_dns_resolver.cc
libircd_la_SOURCES += net_listener.cc
libircd_la_SOURCES += net_listener_udp.cc
if LINUX
libircd_la_SOURCES += net_bpf.cc
endif
libircd_la_SOURCES += server.cc
libircd_la_SOURCES += client.cc
libircd_la_SOURCES += resource.cc

218
ircd/net_bpf.cc Normal file
View File

@ -0,0 +1,218 @@
// 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;
}