-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Upstream WebAssembly VM and Null VM from envoyproxy/envoy-wasm. (#8020)
Description: Upstream from envoyproxy/envoy-wasm the WebAssembly VM support along with the Null VM support and tests. This is the first PR dealing with WebAssembly filter support in envoy. See https://github.com/envoyproxy/envoy-wasm/blob/master/WASM.md and https://github.com/envoyproxy/envoy-wasm/blob/master/docs/root/api-v2/config/wasm/wasm.rst for details. Risk Level: Medium Testing: Unit tests. Docs Changes: N/A Release Notes: N/A Part of #4272 Signed-off-by: John Plevyak <jplevyak@gmail.com>
- Loading branch information
Showing
15 changed files
with
875 additions
and
1 deletion.
There are no files selected for viewing
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
licenses(["notice"]) # Apache 2 | ||
|
||
load( | ||
"//bazel:envoy_build_system.bzl", | ||
"envoy_cc_library", | ||
"envoy_package", | ||
) | ||
|
||
envoy_package() | ||
|
||
envoy_cc_library( | ||
name = "well_known_names", | ||
hdrs = ["well_known_names.h"], | ||
deps = [ | ||
"//source/common/singleton:const_singleton", | ||
], | ||
) | ||
|
||
envoy_cc_library( | ||
name = "wasm_vm_interface", | ||
hdrs = ["wasm_vm.h"], | ||
deps = [ | ||
":well_known_names", | ||
"//source/common/common:minimal_logger_lib", | ||
], | ||
) | ||
|
||
envoy_cc_library( | ||
name = "wasm_vm_lib", | ||
srcs = ["wasm_vm.cc"], | ||
deps = [ | ||
":wasm_vm_interface", | ||
"//source/common/common:assert_lib", | ||
"//source/extensions/common/wasm/null:null_lib", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
licenses(["notice"]) # Apache 2 | ||
|
||
load( | ||
"//bazel:envoy_build_system.bzl", | ||
"envoy_cc_library", | ||
"envoy_package", | ||
) | ||
|
||
envoy_package() | ||
|
||
envoy_cc_library( | ||
name = "null_vm_plugin_interface", | ||
hdrs = ["null_vm_plugin.h"], | ||
deps = [ | ||
"//source/extensions/common/wasm:wasm_vm_interface", | ||
"//source/extensions/common/wasm:well_known_names", | ||
], | ||
) | ||
|
||
envoy_cc_library( | ||
name = "null_vm_lib", | ||
srcs = ["null_vm.cc"], | ||
hdrs = ["null_vm.h"], | ||
deps = [ | ||
":null_vm_plugin_interface", | ||
"//external:abseil_node_hash_map", | ||
"//include/envoy/registry", | ||
"//source/common/common:assert_lib", | ||
"//source/extensions/common/wasm:wasm_vm_interface", | ||
"//source/extensions/common/wasm:well_known_names", | ||
], | ||
) | ||
|
||
envoy_cc_library( | ||
name = "null_lib", | ||
srcs = ["null.cc"], | ||
hdrs = ["null.h"], | ||
deps = [ | ||
":null_vm_lib", | ||
":null_vm_plugin_interface", | ||
"//external:abseil_node_hash_map", | ||
"//include/envoy/registry", | ||
"//source/common/common:assert_lib", | ||
"//source/extensions/common/wasm:wasm_vm_interface", | ||
"//source/extensions/common/wasm:well_known_names", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#include "extensions/common/wasm/null/null.h" | ||
|
||
#include <memory> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "envoy/registry/registry.h" | ||
|
||
#include "common/common/assert.h" | ||
|
||
#include "extensions/common/wasm/null/null_vm.h" | ||
#include "extensions/common/wasm/null/null_vm_plugin.h" | ||
#include "extensions/common/wasm/well_known_names.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Common { | ||
namespace Wasm { | ||
namespace Null { | ||
|
||
WasmVmPtr createVm() { return std::make_unique<NullVm>(); } | ||
|
||
} // namespace Null | ||
} // namespace Wasm | ||
} // namespace Common | ||
} // namespace Extensions | ||
} // namespace Envoy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#pragma once | ||
|
||
#include <memory> | ||
|
||
#include "extensions/common/wasm/null/null_vm_plugin.h" | ||
#include "extensions/common/wasm/wasm_vm.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Common { | ||
namespace Wasm { | ||
namespace Null { | ||
|
||
WasmVmPtr createVm(); | ||
|
||
} // namespace Null | ||
} // namespace Wasm | ||
} // namespace Common | ||
} // namespace Extensions | ||
} // namespace Envoy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#include "extensions/common/wasm/null/null_vm.h" | ||
|
||
#include <memory> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "envoy/registry/registry.h" | ||
|
||
#include "common/common/assert.h" | ||
|
||
#include "extensions/common/wasm/null/null_vm_plugin.h" | ||
#include "extensions/common/wasm/well_known_names.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Common { | ||
namespace Wasm { | ||
namespace Null { | ||
|
||
WasmVmPtr NullVm::clone() { | ||
auto cloned_null_vm = std::make_unique<NullVm>(*this); | ||
cloned_null_vm->load(plugin_name_, false /* unused */); | ||
return cloned_null_vm; | ||
} | ||
|
||
// "Load" the plugin by obtaining a pointer to it from the factory. | ||
bool NullVm::load(const std::string& name, bool /* allow_precompiled */) { | ||
auto factory = Registry::FactoryRegistry<NullVmPluginFactory>::getFactory(name); | ||
if (!factory) { | ||
return false; | ||
} | ||
plugin_name_ = name; | ||
plugin_ = factory->create(); | ||
return true; | ||
} | ||
|
||
void NullVm::link(absl::string_view /* name */, bool /* needs_emscripten */) {} | ||
|
||
void NullVm::makeModule(absl::string_view /* name */) { | ||
// NullVm does not advertise code as emscripten so this will not get called. | ||
NOT_REACHED_GCOVR_EXCL_LINE; | ||
} | ||
|
||
void NullVm::start(Common::Wasm::Context* context) { | ||
SaveRestoreContext saved_context(context); | ||
plugin_->start(); | ||
} | ||
|
||
uint64_t NullVm::getMemorySize() { return std::numeric_limits<uint64_t>::max(); } | ||
|
||
// NulVm pointers are just native pointers. | ||
absl::optional<absl::string_view> NullVm::getMemory(uint64_t pointer, uint64_t size) { | ||
if (pointer == 0 && size != 0) { | ||
return absl::nullopt; | ||
} | ||
return absl::string_view(reinterpret_cast<char*>(pointer), static_cast<size_t>(size)); | ||
} | ||
|
||
bool NullVm::getMemoryOffset(void* host_pointer, uint64_t* vm_pointer) { | ||
*vm_pointer = reinterpret_cast<uint64_t>(host_pointer); | ||
return true; | ||
} | ||
|
||
bool NullVm::setMemory(uint64_t pointer, uint64_t size, const void* data) { | ||
if ((pointer == 0 || data == nullptr)) { | ||
if (size != 0) { | ||
return false; | ||
} else { | ||
return true; | ||
} | ||
} | ||
auto p = reinterpret_cast<char*>(pointer); | ||
memcpy(p, data, size); | ||
return true; | ||
} | ||
|
||
bool NullVm::setWord(uint64_t pointer, Word data) { | ||
if (pointer == 0) { | ||
return false; | ||
} | ||
auto p = reinterpret_cast<char*>(pointer); | ||
memcpy(p, &data.u64_, sizeof(data.u64_)); | ||
return true; | ||
} | ||
|
||
bool NullVm::getWord(uint64_t pointer, Word* data) { | ||
if (pointer == 0) { | ||
return false; | ||
} | ||
auto p = reinterpret_cast<char*>(pointer); | ||
memcpy(&data->u64_, p, sizeof(data->u64_)); | ||
return true; | ||
} | ||
|
||
absl::string_view NullVm::getUserSection(absl::string_view /* name */) { | ||
// Return nothing: there is no WASM file. | ||
return {}; | ||
} | ||
|
||
} // namespace Null | ||
} // namespace Wasm | ||
} // namespace Common | ||
} // namespace Extensions | ||
} // namespace Envoy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#pragma once | ||
|
||
#include <memory> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "envoy/registry/registry.h" | ||
|
||
#include "common/common/assert.h" | ||
|
||
#include "extensions/common/wasm/null/null_vm_plugin.h" | ||
#include "extensions/common/wasm/well_known_names.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Common { | ||
namespace Wasm { | ||
namespace Null { | ||
|
||
// The NullVm wraps a C++ WASM plugin which has been compiled with the WASM API | ||
// and linked directly into the Envoy process. This is useful for development | ||
// in that it permits the debugger to set breakpoints in both Envoy and the plugin. | ||
struct NullVm : public WasmVm { | ||
NullVm() = default; | ||
NullVm(const NullVm& other) : plugin_name_(other.plugin_name_) {} | ||
|
||
// WasmVm | ||
absl::string_view vm() override { return WasmVmNames::get().Null; } | ||
bool cloneable() override { return true; }; | ||
WasmVmPtr clone() override; | ||
bool load(const std::string& code, bool allow_precompiled) override; | ||
void link(absl::string_view debug_name, bool needs_emscripten) override; | ||
void setMemoryLayout(uint64_t, uint64_t, uint64_t) override {} | ||
void start(Common::Wasm::Context* context) override; | ||
uint64_t getMemorySize() override; | ||
absl::optional<absl::string_view> getMemory(uint64_t pointer, uint64_t size) override; | ||
bool getMemoryOffset(void* host_pointer, uint64_t* vm_pointer) override; | ||
bool setMemory(uint64_t pointer, uint64_t size, const void* data) override; | ||
bool setWord(uint64_t pointer, Word data) override; | ||
bool getWord(uint64_t pointer, Word* data) override; | ||
void makeModule(absl::string_view name) override; | ||
absl::string_view getUserSection(absl::string_view name) override; | ||
|
||
#define _FORWARD_GET_FUNCTION(_T) \ | ||
void getFunction(absl::string_view function_name, _T* f) override { \ | ||
plugin_->getFunction(function_name, f); \ | ||
} | ||
FOR_ALL_WASM_VM_EXPORTS(_FORWARD_GET_FUNCTION) | ||
#undef _FORWARD_GET_FUNCTION | ||
|
||
// These are not needed for NullVm which invokes the handlers directly. | ||
#define _REGISTER_CALLBACK(_T) \ | ||
void registerCallback(absl::string_view, absl::string_view, _T, \ | ||
typename ConvertFunctionTypeWordToUint32<_T>::type) override{}; | ||
FOR_ALL_WASM_VM_IMPORTS(_REGISTER_CALLBACK) | ||
#undef _REGISTER_CALLBACK | ||
|
||
// NullVm does not advertise code as emscripten so this will not get called. | ||
std::unique_ptr<Global<double>> makeGlobal(absl::string_view, absl::string_view, | ||
double) override { | ||
NOT_REACHED_GCOVR_EXCL_LINE; | ||
}; | ||
std::unique_ptr<Global<Word>> makeGlobal(absl::string_view, absl::string_view, Word) override { | ||
NOT_REACHED_GCOVR_EXCL_LINE; | ||
}; | ||
|
||
std::string plugin_name_; | ||
std::unique_ptr<NullVmPlugin> plugin_; | ||
}; | ||
|
||
} // namespace Null | ||
} // namespace Wasm | ||
} // namespace Common | ||
} // namespace Extensions | ||
} // namespace Envoy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#pragma once | ||
|
||
#include "extensions/common/wasm/wasm_vm.h" | ||
|
||
namespace Envoy { | ||
namespace Extensions { | ||
namespace Common { | ||
namespace Wasm { | ||
namespace Null { | ||
|
||
// A wrapper for the natively compiled NullVm plugin which implements the WASM ABI. | ||
class NullVmPlugin { | ||
public: | ||
NullVmPlugin() = default; | ||
virtual ~NullVmPlugin() = default; | ||
|
||
// NB: These are defined rather than declared PURE because gmock uses __LINE__ internally for | ||
// uniqueness, making it impossible to use FOR_ALL_WASM_VM_EXPORTS with MOCK_METHOD2. | ||
#define _DEFINE_GET_FUNCTION(_T) \ | ||
virtual void getFunction(absl::string_view, _T* f) { *f = nullptr; } | ||
FOR_ALL_WASM_VM_EXPORTS(_DEFINE_GET_FUNCTION) | ||
#undef _DEFIN_GET_FUNCTIONE | ||
|
||
virtual void start() PURE; | ||
}; | ||
|
||
/** | ||
* Pseudo-WASM plugins using the NullVM should implement this factory and register via | ||
* Registry::registerFactory or the convenience class RegisterFactory. | ||
*/ | ||
class NullVmPluginFactory { | ||
public: | ||
virtual ~NullVmPluginFactory() = default; | ||
|
||
/** | ||
* Name of the plugin. | ||
*/ | ||
virtual const std::string name() const PURE; | ||
|
||
/** | ||
* Create an instance of the plugin. | ||
*/ | ||
virtual std::unique_ptr<NullVmPlugin> create() const PURE; | ||
}; | ||
|
||
} // namespace Null | ||
} // namespace Wasm | ||
} // namespace Common | ||
} // namespace Extensions | ||
} // namespace Envoy |
Oops, something went wrong.