diff --git a/include/ircd/net/sock_opts.h b/include/ircd/net/sock_opts.h index 4998d9773..3a37656d9 100644 --- a/include/ircd/net/sock_opts.h +++ b/include/ircd/net/sock_opts.h @@ -25,6 +25,7 @@ namespace ircd::net size_t write_bufsz(const socket &); size_t read_lowat(const socket &); size_t write_lowat(const socket &); + int attach(const socket &); void v6only(socket &, const bool &); void blocking(socket &, const bool &); @@ -36,6 +37,10 @@ namespace ircd::net void write_bufsz(socket &, const size_t &bytes); void read_lowat(socket &, const size_t &bytes); void write_lowat(socket &, const size_t &bytes); + void attach(const int &sd, const int &fd); + void attach(socket &, const int &fd); + void detach(const int &sd, const int &fd); + void detach(socket &, const int &fd); void set(socket &, const sock_opts &); } @@ -59,6 +64,7 @@ struct ircd::net::sock_opts ssize_t write_bufsz { IGN }; ssize_t read_lowat { IGN }; ssize_t write_lowat { IGN }; + int ebpf { -1 }; sock_opts(const socket &); // Get options from socket sock_opts() = default; diff --git a/ircd/net.cc b/ircd/net.cc index 81fe85af1..e658cda83 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -841,8 +841,65 @@ ircd::net::set(socket &socket, if(opts.write_lowat != opts.IGN) net::write_lowat(socket, opts.write_lowat); + + if(opts.ebpf != -1) + net::attach(socket, opts.ebpf); } +void +ircd::net::detach(socket &socket, + const int &prog_fd) +{ + ip::tcp::socket &sd(socket); + const auto &fd + { + sd.lowest_layer().native_handle() + }; + + return detach(fd, prog_fd); +} + +void +ircd::net::detach(const int &sd, + const int &prog_fd) +#if defined(SO_DETACH_BPF) && defined(SOL_SOCKET) +{ + const socklen_t len(sizeof(prog_fd)); + sys::call(::setsockopt, sd, SOL_SOCKET, SO_DETACH_BPF, &prog_fd, len); +} +#else +{ + #warning "SO_DETACH_BPF is not defined on this platform." +} +#endif + +void +ircd::net::attach(socket &socket, + const int &prog_fd) +{ + ip::tcp::socket &sd(socket); + const auto &fd + { + sd.lowest_layer().native_handle() + }; + + return attach(fd, prog_fd); +} + +void +ircd::net::attach(const int &sd, + const int &prog_fd) +#if defined(SO_ATTACH_BPF) && defined(SOL_SOCKET) +{ + const socklen_t len(sizeof(prog_fd)); + sys::call(::setsockopt, sd, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd, len); +} +#else +{ + #warning "SO_ATTACH_BPF is not defined on this platform." +} +#endif + void ircd::net::write_lowat(socket &socket, const size_t &bytes) @@ -995,6 +1052,28 @@ ircd::net::v6only(socket &socket, sd.set_option(option); } +int +ircd::net::attach(const socket &socket) +#if defined(SO_ATTACH_BPF) && defined(SOL_SOCKET) +{ + const ip::tcp::socket &sd(socket); + const auto &fd + { + mutable_cast(sd).lowest_layer().native_handle() + }; + + int ret {-1}; + socklen_t len(sizeof(ret)); + sys::call(::getsockopt, fd, SOL_SOCKET, SO_ATTACH_BPF, &ret, &len); + assert(len <= sizeof(ret)); + return ret; +} +#else +{ + #warning "SO_ATTACH_BPF is not defined on this platform." +} +#endif + size_t ircd::net::write_lowat(const socket &socket) {